1
+ #include " gobject.hpp"
2
+
1
3
namespace Nui ::Impl::Linux
2
4
{
5
+ struct AsyncResponse
6
+ {
7
+ GObjectReference<GInputStream> stream;
8
+ GObjectReference<WebKitURISchemeResponse> response;
9
+ std::string data;
10
+ };
11
+
3
12
struct SchemeContext
4
13
{
5
14
std::size_t id;
6
15
std::weak_ptr<Window::LinuxImplementation> impl;
7
16
CustomScheme schemeInfo;
17
+ std::mutex asyncResponsesGuard;
18
+ std::map<int , AsyncResponse> asyncResponses;
19
+ int asyncResponseCounter = 0 ;
20
+
21
+ void gcResponses ()
22
+ {
23
+ std::lock_guard<std::mutex> asyncResponsesGuard{this ->asyncResponsesGuard };
24
+ std::vector<int > removals{};
25
+ for (auto it = asyncResponses.begin (); it != asyncResponses.end (); ++it)
26
+ {
27
+ GInputStream* stream = it->second .stream .get ();
28
+ if (g_input_stream_is_closed (stream))
29
+ {
30
+ removals.push_back (it->first );
31
+ break ;
32
+ }
33
+ }
34
+ for (auto const & removal : removals)
35
+ asyncResponses.erase (removal);
36
+ }
8
37
};
9
38
}
10
39
@@ -19,7 +48,10 @@ std::size_t strlenLimited(char const* str, std::size_t limit)
19
48
extern " C" {
20
49
void uriSchemeRequestCallback (WebKitURISchemeRequest* request, gpointer userData)
21
50
{
51
+ using namespace std ::string_literals;
52
+
22
53
auto * schemeContext = static_cast <Nui::Impl::Linux::SchemeContext*>(userData);
54
+ schemeContext->gcResponses ();
23
55
24
56
// const auto path = std::string_view{webkit_uri_scheme_request_get_path(request)};
25
57
// const auto scheme = std::string_view{webkit_uri_scheme_request_get_scheme(request)};
@@ -102,50 +134,59 @@ extern "C" {
102
134
.method = std::string{cmethod},
103
135
});
104
136
105
- GInputStream* stream;
106
- stream = g_memory_input_stream_new_from_data (
107
- responseObj.body .c_str (), static_cast <gssize>(responseObj.body .size ()), nullptr );
108
- auto deleteStream = Nui::ScopeExit{[stream] {
109
- g_object_unref (stream);
110
- }};
111
-
112
- WebKitURISchemeResponse* response;
113
- response = webkit_uri_scheme_response_new (stream, static_cast <gint64>(responseObj.body .size ()));
114
-
115
- std::string contentType;
116
- if (responseObj.headers .find (" Content-Type" ) != responseObj.headers .end ())
117
- {
118
- auto range = responseObj.headers .equal_range (" Content-Type" );
119
- for (auto it = range.first ; it != range.second ; ++it)
120
- contentType += it->second + " ; " ;
121
- }
122
- else
123
- contentType = " application/octet-stream" ;
124
-
125
- webkit_uri_scheme_response_set_content_type (response, contentType.c_str ());
126
- webkit_uri_scheme_response_set_status (response, static_cast <guint>(responseObj.statusCode ), nullptr );
127
-
128
- auto * responseHeaders = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE);
129
- auto deleteResponseHeaders = Nui::ScopeExit{[responseHeaders] {
130
- g_object_unref (responseHeaders);
131
- }};
132
- for (auto const & [key, value] : responseObj.headers )
133
- soup_message_headers_append (responseHeaders, key.c_str (), value.c_str ());
134
-
135
- if (responseObj.headers .find (" Access-Control-Allow-Origin" ) == responseObj.headers .end () &&
136
- !schemeInfo.allowedOrigins .empty ())
137
- {
138
- auto const & front = schemeInfo.allowedOrigins .front ();
139
- soup_message_headers_append (responseHeaders, " Access-Control-Allow-Origin" , front.c_str ());
140
- }
141
-
142
- webkit_uri_scheme_response_set_http_headers (response, responseHeaders);
143
- webkit_uri_scheme_request_finish_with_response (request, response);
137
+ using Nui::GObjectReference;
138
+
139
+ std::lock_guard<std::mutex> asyncResponsesGuard{schemeContext->asyncResponsesGuard };
140
+ ++schemeContext->asyncResponseCounter ;
141
+ schemeContext->asyncResponses [schemeContext->asyncResponseCounter ] = Nui::Impl::Linux::AsyncResponse{};
142
+ auto & asyncResponse = schemeContext->asyncResponses [schemeContext->asyncResponseCounter ];
143
+ asyncResponse.data = std::move (responseObj.body );
144
+
145
+ asyncResponse.stream = Nui::GObjectReference<GInputStream>::adoptReference (g_memory_input_stream_new_from_data (
146
+ asyncResponse.data .data (), static_cast <gssize>(asyncResponse.data .size ()), nullptr ));
147
+
148
+ asyncResponse.response = Nui::GObjectReference<WebKitURISchemeResponse>::adoptReference (
149
+ webkit_uri_scheme_response_new (asyncResponse.stream .get (), static_cast <gint64>(asyncResponse.data .size ())));
150
+
151
+ const std::string contentType = [&]() {
152
+ if (responseObj.headers .find (" Content-Type" ) != responseObj.headers .end ())
153
+ {
154
+ std::string contentType;
155
+ auto range = responseObj.headers .equal_range (" Content-Type" );
156
+ for (auto it = range.first ; it != range.second ; ++it)
157
+ contentType += it->second + " ; " ;
158
+ contentType.pop_back ();
159
+ contentType.pop_back ();
160
+ return contentType;
161
+ }
162
+ return " application/octet-stream" s;
163
+ }();
164
+
165
+ webkit_uri_scheme_response_set_content_type (asyncResponse.response .get (), contentType.c_str ());
166
+ webkit_uri_scheme_response_set_status (
167
+ asyncResponse.response .get (), static_cast <guint>(responseObj.statusCode ), nullptr );
168
+
169
+ auto setHeaders = [&]() {
170
+ auto * responseHeaders = soup_message_headers_new (SOUP_MESSAGE_HEADERS_RESPONSE);
171
+ for (auto const & [key, value] : responseObj.headers )
172
+ soup_message_headers_append (responseHeaders, key.c_str (), value.c_str ());
173
+
174
+ if (responseObj.headers .find (" Access-Control-Allow-Origin" ) == responseObj.headers .end () &&
175
+ !schemeInfo.allowedOrigins .empty ())
176
+ {
177
+ auto const & front = schemeInfo.allowedOrigins .front ();
178
+ soup_message_headers_append (responseHeaders, " Access-Control-Allow-Origin" , front.c_str ());
179
+ }
180
+ webkit_uri_scheme_response_set_http_headers (asyncResponse.response .get (), responseHeaders);
181
+ };
182
+
183
+ setHeaders ();
184
+ webkit_uri_scheme_request_finish_with_response (request, asyncResponse.response .get ());
144
185
}
145
186
146
- void uriSchemeDestroyNotify (void *)
187
+ void uriSchemeDestroyNotify (void * userData )
147
188
{
148
- // Happens when everything else is already dead.
189
+ // Useless, because called when everything is already destroyed
149
190
}
150
191
}
151
192
0 commit comments