mirror of
https://github.com/cesanta/mongoose.git
synced 2024-11-27 20:59:00 +08:00
Make mg_http_serve_file public
A way to serve a single, specific file as opposed to the hairy monster that is mg_serve_http. PUBLISHED_FROM=6ed1bc487b9d41d212a5907337182f23b040aecf
This commit is contained in:
parent
1070dd2d87
commit
5fa544fc78
@ -26,6 +26,7 @@ items:
|
||||
- { type: file, name: mg_connect_http.md }
|
||||
- { type: file, name: mg_connect_http_opt.md }
|
||||
- { type: file, name: mg_serve_http.md }
|
||||
- { type: file, name: mg_http_serve_file.md }
|
||||
- { type: file, name: mg_register_http_endpoint.md }
|
||||
- { type: file, name: mg_file_upload_handler.md }
|
||||
- { type: file, name: mg_http_check_digest_auth.md }
|
||||
|
28
docs/c-api/http.h/mg_http_serve_file.md
Normal file
28
docs/c-api/http.h/mg_http_serve_file.md
Normal file
@ -0,0 +1,28 @@
|
||||
---
|
||||
title: "mg_http_serve_file()"
|
||||
decl_name: "mg_http_serve_file"
|
||||
symbol_kind: "func"
|
||||
signature: |
|
||||
void mg_http_serve_file(struct mg_connection *nc, struct http_message *hm,
|
||||
const char *path, const struct mg_str mime_type,
|
||||
const struct mg_str extra_headers);
|
||||
---
|
||||
|
||||
Serves a specific file with a given MIME type and optional extra headers.
|
||||
|
||||
Example code snippet:
|
||||
|
||||
```c
|
||||
static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
||||
switch (ev) {
|
||||
case MG_EV_HTTP_REQUEST: {
|
||||
struct http_message *hm = (struct http_message *) ev_data;
|
||||
mg_http_serve_file(nc, hm, "file.txt",
|
||||
mg_mk_str("text/plain"), mg_mk_str(""));
|
||||
break;
|
||||
}
|
||||
...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
57
mongoose.c
57
mongoose.c
@ -5108,8 +5108,8 @@ void mg_send_websocket_handshake(struct mg_connection *nc, const char *path,
|
||||
|
||||
#endif /* MG_DISABLE_HTTP_WEBSOCKET */
|
||||
|
||||
void mg_send_response_line(struct mg_connection *nc, int status_code,
|
||||
const char *extra_headers) {
|
||||
void mg_send_response_line_s(struct mg_connection *nc, int status_code,
|
||||
const struct mg_str extra_headers) {
|
||||
const char *status_message = "OK";
|
||||
switch (status_code) {
|
||||
case 206:
|
||||
@ -5142,11 +5142,16 @@ void mg_send_response_line(struct mg_connection *nc, int status_code,
|
||||
}
|
||||
mg_printf(nc, "HTTP/1.1 %d %s\r\nServer: %s\r\n", status_code, status_message,
|
||||
mg_version_header);
|
||||
if (extra_headers != NULL) {
|
||||
mg_printf(nc, "%s\r\n", extra_headers);
|
||||
if (extra_headers.len > 0) {
|
||||
mg_printf(nc, "%.*s\r\n", (int) extra_headers.len, extra_headers.p);
|
||||
}
|
||||
}
|
||||
|
||||
void mg_send_response_line(struct mg_connection *nc, int status_code,
|
||||
const char *extra_headers) {
|
||||
mg_send_response_line_s(nc, status_code, mg_mk_str(extra_headers));
|
||||
}
|
||||
|
||||
void mg_send_head(struct mg_connection *c, int status_code,
|
||||
int64_t content_length, const char *extra_headers) {
|
||||
mg_send_response_line(c, status_code, extra_headers);
|
||||
@ -5332,6 +5337,7 @@ static void mg_handle_ssi_request(struct mg_connection *nc, const char *path,
|
||||
const struct mg_serve_http_opts *opts) {
|
||||
FILE *fp;
|
||||
struct mg_str mime_type;
|
||||
DBG(("%p %s", nc, path));
|
||||
|
||||
if ((fp = fopen(path, "rb")) == NULL) {
|
||||
mg_http_send_error(nc, 404, NULL);
|
||||
@ -5383,15 +5389,13 @@ static int mg_http_parse_range_header(const struct mg_str *header, int64_t *a,
|
||||
return result;
|
||||
}
|
||||
|
||||
static void mg_http_send_file2(struct mg_connection *nc, const char *path,
|
||||
cs_stat_t *st, struct http_message *hm,
|
||||
struct mg_serve_http_opts *opts) {
|
||||
void mg_http_serve_file(struct mg_connection *nc, struct http_message *hm,
|
||||
const char *path, const struct mg_str mime_type,
|
||||
const struct mg_str extra_headers) {
|
||||
struct mg_http_proto_data *pd = mg_http_get_proto_data(nc);
|
||||
struct mg_str mime_type;
|
||||
|
||||
DBG(("%p [%s]", nc, path));
|
||||
mg_http_free_proto_data_file(&pd->file);
|
||||
if ((pd->file.fp = fopen(path, "rb")) == NULL) {
|
||||
cs_stat_t st;
|
||||
DBG(("%p [%s] %.*s", nc, path, (int) mime_type.len, mime_type.p));
|
||||
if (mg_stat(path, &st) != 0 || (pd->file.fp = fopen(path, "rb")) == NULL) {
|
||||
int code;
|
||||
switch (errno) {
|
||||
case EACCES:
|
||||
@ -5404,13 +5408,10 @@ static void mg_http_send_file2(struct mg_connection *nc, const char *path,
|
||||
code = 500;
|
||||
};
|
||||
mg_http_send_error(nc, code, "Open failed");
|
||||
} else if (mg_match_prefix(opts->ssi_pattern, strlen(opts->ssi_pattern),
|
||||
path) > 0) {
|
||||
mg_handle_ssi_request(nc, path, opts);
|
||||
} else {
|
||||
char etag[50], current_time[50], last_modified[50], range[70];
|
||||
time_t t = time(NULL);
|
||||
int64_t r1 = 0, r2 = 0, cl = st->st_size;
|
||||
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;
|
||||
|
||||
@ -5428,13 +5429,13 @@ static void mg_http_send_file2(struct mg_connection *nc, const char *path,
|
||||
cl = 0;
|
||||
snprintf(range, sizeof(range),
|
||||
"Content-Range: bytes */%" INT64_FMT "\r\n",
|
||||
(int64_t) st->st_size);
|
||||
(int64_t) st.st_size);
|
||||
} else {
|
||||
status_code = 206;
|
||||
cl = r2 - r1 + 1;
|
||||
snprintf(range, sizeof(range), "Content-Range: bytes %" INT64_FMT
|
||||
"-%" INT64_FMT "/%" INT64_FMT "\r\n",
|
||||
r1, r1 + cl - 1, (int64_t) st->st_size);
|
||||
r1, r1 + cl - 1, (int64_t) st.st_size);
|
||||
#if _FILE_OFFSET_BITS == 64 || _POSIX_C_SOURCE >= 200112L || \
|
||||
_XOPEN_SOURCE >= 600
|
||||
fseeko(pd->file.fp, r1, SEEK_SET);
|
||||
@ -5455,10 +5456,9 @@ static void mg_http_send_file2(struct mg_connection *nc, const char *path,
|
||||
}
|
||||
#endif
|
||||
|
||||
mg_http_construct_etag(etag, sizeof(etag), st);
|
||||
mg_http_construct_etag(etag, sizeof(etag), &st);
|
||||
mg_gmt_time_string(current_time, sizeof(current_time), &t);
|
||||
mg_gmt_time_string(last_modified, sizeof(last_modified), &st->st_mtime);
|
||||
mime_type = mg_get_mime_type(path, "text/plain", opts);
|
||||
mg_gmt_time_string(last_modified, sizeof(last_modified), &st.st_mtime);
|
||||
/*
|
||||
* Content length casted to size_t because:
|
||||
* 1) that's the maximum buffer size anyway
|
||||
@ -5466,7 +5466,7 @@ static void mg_http_send_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_send_response_line_s(nc, status_code, extra_headers);
|
||||
mg_printf(nc,
|
||||
"Date: %s\r\n"
|
||||
"Last-Modified: %s\r\n"
|
||||
@ -5486,6 +5486,17 @@ static void mg_http_send_file2(struct mg_connection *nc, const char *path,
|
||||
}
|
||||
}
|
||||
|
||||
static void mg_http_serve_file2(struct mg_connection *nc, const char *path,
|
||||
struct http_message *hm,
|
||||
struct mg_serve_http_opts *opts) {
|
||||
if (mg_match_prefix(opts->ssi_pattern, strlen(opts->ssi_pattern), path) > 0) {
|
||||
mg_handle_ssi_request(nc, path, opts);
|
||||
return;
|
||||
}
|
||||
mg_http_serve_file(nc, hm, path, mg_get_mime_type(path, "text/plain", opts),
|
||||
mg_mk_str(opts->extra_headers));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int mg_url_decode(const char *src, int src_len, char *dst, int dst_len,
|
||||
@ -7050,7 +7061,7 @@ MG_INTERNAL void mg_send_http_file(struct mg_connection *nc, char *path,
|
||||
} else if (mg_is_not_modified(hm, &st)) {
|
||||
mg_http_send_error(nc, 304, "Not Modified");
|
||||
} else {
|
||||
mg_http_send_file2(nc, index_file ? index_file : path, &st, hm, opts);
|
||||
mg_http_serve_file2(nc, index_file ? index_file : path, hm, opts);
|
||||
}
|
||||
MG_FREE(index_file);
|
||||
}
|
||||
|
23
mongoose.h
23
mongoose.h
@ -2687,6 +2687,29 @@ struct mg_serve_http_opts {
|
||||
void mg_serve_http(struct mg_connection *nc, struct http_message *hm,
|
||||
struct mg_serve_http_opts opts);
|
||||
|
||||
/*
|
||||
* Serves a specific file with a given MIME type and optional extra headers.
|
||||
*
|
||||
* Example code snippet:
|
||||
*
|
||||
* ```c
|
||||
* static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
|
||||
* switch (ev) {
|
||||
* case MG_EV_HTTP_REQUEST: {
|
||||
* struct http_message *hm = (struct http_message *) ev_data;
|
||||
* mg_http_serve_file(nc, hm, "file.txt",
|
||||
* mg_mk_str("text/plain"), mg_mk_str(""));
|
||||
* break;
|
||||
* }
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
void mg_http_serve_file(struct mg_connection *nc, struct http_message *hm,
|
||||
const char *path, const struct mg_str mime_type,
|
||||
const struct mg_str extra_headers);
|
||||
|
||||
/*
|
||||
* Registers a callback for a specified http endpoint
|
||||
* Note: if callback is registered it is called instead of the
|
||||
|
Loading…
Reference in New Issue
Block a user