Skip to content

Commit 4e263d3

Browse files
committed
Handle CORS preflight options
1 parent d47a15c commit 4e263d3

File tree

2 files changed

+27
-11
lines changed

2 files changed

+27
-11
lines changed

src/apps/api/package.d

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ nothrow @nogc:
7373
{
7474
_server.add_uri_handler(HTTPMethod.GET, _uri, &handle_request);
7575
_server.add_uri_handler(HTTPMethod.POST, _uri, &handle_request);
76+
_server.add_uri_handler(HTTPMethod.OPTIONS, _uri, &handle_request);
7677
}
7778
else
7879
_default_handler = _server.hook_global_handler(&handle_request);
@@ -110,6 +111,10 @@ private:
110111
{
111112
const(char)[] tail = request.request_target[_uri.length .. $];
112113

114+
// Handle CORS preflight OPTIONS requests
115+
if (request.method == HTTPMethod.OPTIONS)
116+
return handle_options(request, stream);
117+
113118
if (tail == "/health")
114119
return handle_health(request, stream);
115120
if (tail == "/cli/execute")
@@ -126,9 +131,25 @@ private:
126131
return 0;
127132
}
128133

134+
void add_cors_headers(ref HTTPMessage response)
135+
{
136+
response.headers ~= HTTPParam(StringLit!"Access-Control-Allow-Origin", StringLit!"*");
137+
response.headers ~= HTTPParam(StringLit!"Access-Control-Allow-Methods", StringLit!"GET, POST, PUT, DELETE, OPTIONS");
138+
response.headers ~= HTTPParam(StringLit!"Access-Control-Allow-Headers", StringLit!"Content-Type");
139+
}
140+
141+
int handle_options(ref const HTTPMessage request, ref Stream stream)
142+
{
143+
HTTPMessage response = create_response(request.http_version, 204, StringLit!"No Content", String(), null);
144+
add_cors_headers(response);
145+
stream.write(response.format_message()[]);
146+
return 0;
147+
}
148+
129149
int handle_health(ref const HTTPMessage request, ref Stream stream)
130150
{
131151
HTTPMessage response = create_response(request.http_version, 200, StringLit!"OK", StringLit!"application/json", tconcat("{\"status\":\"healthy\",\"uptime\":", getAppTime().as!"seconds", "}"));
152+
add_cors_headers(response);
132153
stream.write(response.format_message()[]);
133154
return 0;
134155
}
@@ -149,6 +170,7 @@ private:
149170
if (command_text.length == 0)
150171
{
151172
HTTPMessage response = create_response(request.http_version, 400, StringLit!"Bad Request", StringLit!"application/json", "{\"error\":\"Command body required\"}");
173+
add_cors_headers(response);
152174
stream.write(response.format_message()[]);
153175
return 0;
154176
}
@@ -186,7 +208,7 @@ private:
186208
}
187209
else
188210
response.content ~= "\"\"}";
189-
211+
add_cors_headers(response);
190212
stream.write(response.format_message()[]);
191213
}
192214

src/protocol/http/message.d

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,8 @@ nothrow @nogc:
198198
break;
199199
}
200200

201+
message.content_type = message.header("Content-Type");
202+
201203
if (state == ParseState.ReadingTailHeaders || message.method == HTTPMethod.HEAD)
202204
goto message_done;
203205

@@ -323,7 +325,7 @@ nothrow @nogc:
323325
private:
324326
static bool read_http_version(ref const(char)[] msg, ref HTTPMessage message)
325327
{
326-
string http = "HTTP/";
328+
enum http = "HTTP/";
327329
if (msg[0..http.length] != http)
328330
return false;
329331

@@ -353,7 +355,7 @@ private:
353355

354356
static bool is_response(const char[] msg)
355357
{
356-
string http = "HTTP/";
358+
enum http = "HTTP/";
357359
return msg[0..http.length] == http;
358360
}
359361

@@ -417,14 +419,6 @@ private:
417419
return 0;
418420
}
419421

420-
// asterisk-form
421-
if (message.method == HTTPMethod.OPTIONS)
422-
{
423-
// OPTIONS * HTTP/1.1
424-
message.request_target = StringLit!"/";
425-
return 0;
426-
}
427-
428422
const(char)[] query = request_target;
429423
request_target = query.split!('?', false);
430424

0 commit comments

Comments
 (0)