From 0c95290f932c33dad3c778c24a9428134ae90b8a Mon Sep 17 00:00:00 2001 From: Sergey Lyubka Date: Wed, 18 Nov 2015 07:39:51 +0000 Subject: [PATCH] Add extra headers support (allows CORS) PUBLISHED_FROM=2279e31315bba4d19e2ae568cba94ea5dea3ef6a --- mongoose.c | 38 ++++++++++++++++++++++++++++---------- mongoose.h | 22 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 10 deletions(-) diff --git a/mongoose.c b/mongoose.c index 14f5a21e..0eda7dc0 100644 --- a/mongoose.c +++ b/mongoose.c @@ -4469,6 +4469,27 @@ void mg_send_websocket_handshake(struct mg_connection *nc, const char *uri, #endif /* MG_DISABLE_HTTP_WEBSOCKET */ #ifndef MG_DISABLE_FILESYSTEM + +void mg_send_response_line(struct mg_connection *nc, int status_code, + const char *extra_headers) { + const char *status_message = "OK"; + switch (status_code) { + case 206: + status_message = "Partial Content"; + break; + case 416: + status_message = "Requested range not satisfiable"; + break; + case 418: + status_message = "I'm a teapot"; + break; + } + mg_printf(nc, "HTTP/1.1 %d %s\r\n", status_code, status_message); + if (extra_headers != NULL) { + mg_printf(nc, "%s\r\n", extra_headers); + } +} + static void send_http_error(struct mg_connection *nc, int code, const char *reason) { if (reason == NULL) { @@ -4643,8 +4664,8 @@ static void handle_ssi_request(struct mg_connection *nc, const char *path, mg_set_close_on_exec(fileno(fp)); mime_type = get_mime_type(path, "text/plain", opts); + mg_send_response_line(nc, 200, opts->extra_headers); mg_printf(nc, - "HTTP/1.1 200 OK\r\n" "Content-Type: %.*s\r\n" "Connection: close\r\n\r\n", (int) mime_type.len, mime_type.p); @@ -4709,7 +4730,6 @@ static void mg_send_http_file2(struct mg_connection *nc, const char *path, int64_t r1 = 0, r2 = 0, cl = st->st_size; struct mg_str *range_hdr = mg_get_http_header(hm, "Range"); int n, status_code = 200; - const char *status_message = "OK"; /* Handle Range header */ range[0] = '\0'; @@ -4722,14 +4742,12 @@ static void mg_send_http_file2(struct mg_connection *nc, const char *path, } if (r1 > r2 || r2 >= cl) { status_code = 416; - status_message = "Requested range not satisfiable"; cl = 0; snprintf(range, sizeof(range), "Content-Range: bytes */%" INT64_FMT "\r\n", (int64_t) st->st_size); } else { status_code = 206; - status_message = "Partial Content"; cl = r2 - r1 + 1; snprintf(range, sizeof(range), "Content-Range: bytes %" INT64_FMT "-%" INT64_FMT "/%" INT64_FMT "\r\n", @@ -4749,8 +4767,8 @@ static void mg_send_http_file2(struct mg_connection *nc, const char *path, * position * TODO(mkm): fix ESP8266 RTOS SDK */ + mg_send_response_line(nc, status_code, opts->extra_headers); mg_printf(nc, - "HTTP/1.1 %d %s\r\n" "Date: %s\r\n" "Last-Modified: %s\r\n" "Accept-Ranges: bytes\r\n" @@ -4761,8 +4779,8 @@ static void mg_send_http_file2(struct mg_connection *nc, const char *path, "Content-Length: %" SIZE_T_FMT "\r\n" "%sEtag: %s\r\n\r\n", - status_code, status_message, current_time, last_modified, - (int) mime_type.len, mime_type.p, (size_t) cl, range, etag); + current_time, last_modified, (int) mime_type.len, mime_type.p, + (size_t) cl, range, etag); nc->proto_data = (void *) dp; dp->cl = cl; @@ -5219,9 +5237,9 @@ static void send_directory_listing(struct mg_connection *nc, const char *dir, "document.onclick = function(ev){ " "var c = ev.target.rel; if (c) srt(tb, c)}; srt(tb, 2); };"; - mg_printf(nc, "%s\r\n%s: %s\r\n%s: %s\r\n\r\n", "HTTP/1.1 200 OK", - "Transfer-Encoding", "chunked", "Content-Type", - "text/html; charset=utf-8"); + mg_send_response_line(nc, 200, opts->extra_headers); + mg_printf(nc, "%s: %s\r\n%s: %s\r\n\r\n", "Transfer-Encoding", "chunked", + "Content-Type", "text/html; charset=utf-8"); mg_printf_http_chunk( nc, diff --git a/mongoose.h b/mongoose.h index 91627e58..550eccf0 100644 --- a/mongoose.h +++ b/mongoose.h @@ -1499,6 +1499,22 @@ void mg_send_http_chunk(struct mg_connection *nc, const char *buf, size_t len); */ void mg_printf_http_chunk(struct mg_connection *, const char *, ...); +/* + * Send response status line. + * If `extra_headers` is not NULL, then `extra_headers` are also sent + * after the reponse line, followed by a new line. + * Example: + * + * mg_send_response_line(nc, 200, "Access-Control-Allow-Origin: *"); + * + * Will result in: + * + * HTTP/1.1 200 OK\r\n + * Access-Control-Allow-Origin: *\r\n + */ +void mg_send_response_line(struct mg_connection *nc, int status_code, + const char *extra_headers); + /* * Send printf-formatted HTTP chunk, escaping HTML tags. */ @@ -1726,6 +1742,12 @@ struct mg_serve_http_opts { * ".txt=text/plain; charset=utf-8,.c=text/plain" */ const char *custom_mime_types; + + /* + * Extra HTTP headers to add to each server response. + * Example: to enable CORS, set this to "Access-Control-Allow-Origin: *". + */ + const char *extra_headers; }; /*