Add extra param to http_reply()

This commit is contained in:
cpq 2020-12-17 22:45:22 +00:00
parent 29d31ba919
commit 82a378e519
9 changed files with 47 additions and 40 deletions

View File

@ -648,11 +648,18 @@ Serve static file.
### mg\_http\_reply()
```c
void mg_http_reply(struct mg_connection *c, int code, const char *fmt, ...);
void mg_http_reply(struct mg_connection *c, int status_code, const char *headers,
const char *body_fmt, ...);
```
Send simple HTTP response using `printf()` semantic.
`code` is HTTP response code, `fmt` is format for the HTTP body.
Send simple HTTP response using `printf()` semantic. This function formats
response body according to a `body_fmt`, and automatically appends a correct
`Content-Length` header. Extra headers could be passed via `headers`
parameter.
- `status_code` - an HTTP response code
- `headers` - extra headers, default NULL. If not NULL, must end with `\r\n`
- `fmt` - a format string for the HTTP body, in a printf semantics
### mg\_http\_header()

View File

@ -10,7 +10,7 @@
// Event handler for an accepted connection
static void cb(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_MSG) {
mg_http_reply(c, 200, "Hello from ESP32!");
mg_http_reply(c, 200, "", "Hello from ESP32!");
}
}

View File

@ -14,9 +14,9 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_http_match_uri(hm, "/api/f1")) {
mg_http_reply(c, 200, "{\"result\": %d}\n", 123); // Serve REST response
mg_http_reply(c, 200, "", "{\"result\": %d}\n", 123); // Serve REST
} else if (mg_http_match_uri(hm, "/api/f2/*")) {
mg_http_reply(c, 200, "{\"result\": \"%.*s\"}\n", (int) hm->uri.len,
mg_http_reply(c, 200, "", "{\"result\": \"%.*s\"}\n", (int) hm->uri.len,
hm->uri.ptr);
} else {
mg_http_serve_dir(c, ev_data, s_web_directory); // Serve static files

View File

@ -24,7 +24,7 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
mg_ws_upgrade(c, hm);
} else if (mg_http_match_uri(hm, "/rest")) {
// Serve REST response
mg_http_reply(c, 200, "{\"result\": %d}\n", 123);
mg_http_reply(c, 200, "", "{\"result\": %d}\n", 123);
} else {
// Serve static files
mg_http_serve_dir(c, ev_data, s_web_directory);

View File

@ -586,17 +586,16 @@ void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len) {
mg_send(c, "\r\n", 2);
}
void mg_http_reply(struct mg_connection *c, int code, const char *fmt, ...) {
void mg_http_reply(struct mg_connection *c, int code, const char *headers,
const char *fmt, ...) {
char mem[100], *buf = mem;
va_list ap;
int len;
va_start(ap, fmt);
len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
va_end(ap);
mg_printf(c,
"HTTP/1.1 %d OK\r\nContent-Type: text/plain\r\n"
"Content-Length: %d\r\n\r\n",
code, len);
mg_printf(c, "HTTP/1.1 %d OK\r\n%sContent-Length: %d\r\n\r\n", code,
headers == NULL ? "" : headers, len);
mg_send(c, buf, len);
if (buf != mem) free(buf);
}
@ -623,7 +622,7 @@ int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
mg_http_get_var(&hm->query, "offset", offset, sizeof(offset));
mg_http_get_var(&hm->query, "name", name, sizeof(name));
if (name[0] == '\0') {
mg_http_reply(c, 400, "%s", "name required");
mg_http_reply(c, 400, "", "%s", "name required");
return -1;
} else {
FILE *fp;
@ -632,12 +631,12 @@ int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
LOG(LL_DEBUG,
("%p %d bytes @ %d [%s]", c->fd, (int) hm->body.len, (int) oft, name));
if ((fp = fopen(path, oft == 0 ? "wb" : "a")) == NULL) {
mg_http_reply(c, 400, "fopen(%s): %d", name, errno);
mg_http_reply(c, 400, "", "fopen(%s): %d", name, errno);
return -2;
} else {
fwrite(hm->body.ptr, 1, hm->body.len, fp);
fclose(fp);
mg_http_reply(c, 200, "");
mg_http_reply(c, 200, "", "");
return hm->body.len;
}
}
@ -730,7 +729,7 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
char etag[64];
if (fp == NULL || stat(path, &st) != 0 ||
mg_http_etag(etag, sizeof(etag), &st) != etag) {
mg_http_reply(c, 404, "%s", "Not found\n");
mg_http_reply(c, 404, "", "%s", "Not found\n");
} else if (inm != NULL && mg_vcasecmp(inm, etag) == 0) {
mg_printf(c, "HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n");
} else {
@ -950,7 +949,7 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm,
MG_VERSION);
mg_http_write_chunk(c, "", 0);
} else {
mg_http_reply(c, 400, "Cannot open dir");
mg_http_reply(c, 400, "", "Cannot open dir");
LOG(LL_DEBUG, ("%p opendir(%s) -> %d", c->fd, dir, errno));
}
}
@ -963,7 +962,7 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
if (realpath(dir, root) == NULL)
LOG(LL_DEBUG, ("realpath(%s): %d", dir, errno));
if (!mg_is_dir(root)) {
mg_http_reply(c, 400, "Bad web root [%s]\n", root);
mg_http_reply(c, 400, "", "Bad web root [%s]\n", root);
} else {
// NOTE(lsm): Xilinx snprintf does not 0-terminate the detination for
// the %.*s specifier, if the length is zero. Make sure hm->uri.len > 0
@ -979,7 +978,7 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
is_index = true;
}
if (strlen(real) < strlen(root) || memcmp(real, root, strlen(root)) != 0) {
mg_http_reply(c, 404, "Not found %.*s\n", hm->uri.len, hm->uri.ptr);
mg_http_reply(c, 404, "", "Not found %.*s\n", hm->uri.len, hm->uri.ptr);
} else {
FILE *fp = fopen(real, "r");
#if MG_ENABLE_HTTP_DEBUG_ENDPOINT
@ -989,7 +988,7 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
#if MG_ENABLE_DIRECTORY_LISTING
listdir(c, hm, real);
#else
mg_http_reply(c, 403, "%s", "Directory listing not supported");
mg_http_reply(c, 403, "", "%s", "Directory listing not supported");
#endif
} else {
mg_http_serve_file(c, hm, real, guess_content_type(real));

View File

@ -676,7 +676,8 @@ void mg_http_serve_dir(struct mg_connection *, struct mg_http_message *hm,
const char *path);
void mg_http_serve_file(struct mg_connection *, struct mg_http_message *,
const char *, const char *mime);
void mg_http_reply(struct mg_connection *c, int code, const char *fmt, ...);
void mg_http_reply(struct mg_connection *, int status_code, const char *headers,
const char *body_fmt, ...);
struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name);
void mg_http_event_handler(struct mg_connection *c, int ev);
int mg_http_get_var(const struct mg_str *, const char *name, char *, int);

View File

@ -219,17 +219,16 @@ void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len) {
mg_send(c, "\r\n", 2);
}
void mg_http_reply(struct mg_connection *c, int code, const char *fmt, ...) {
void mg_http_reply(struct mg_connection *c, int code, const char *headers,
const char *fmt, ...) {
char mem[100], *buf = mem;
va_list ap;
int len;
va_start(ap, fmt);
len = mg_vasprintf(&buf, sizeof(mem), fmt, ap);
va_end(ap);
mg_printf(c,
"HTTP/1.1 %d OK\r\nContent-Type: text/plain\r\n"
"Content-Length: %d\r\n\r\n",
code, len);
mg_printf(c, "HTTP/1.1 %d OK\r\n%sContent-Length: %d\r\n\r\n", code,
headers == NULL ? "" : headers, len);
mg_send(c, buf, len);
if (buf != mem) free(buf);
}
@ -256,7 +255,7 @@ int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
mg_http_get_var(&hm->query, "offset", offset, sizeof(offset));
mg_http_get_var(&hm->query, "name", name, sizeof(name));
if (name[0] == '\0') {
mg_http_reply(c, 400, "%s", "name required");
mg_http_reply(c, 400, "", "%s", "name required");
return -1;
} else {
FILE *fp;
@ -265,12 +264,12 @@ int mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
LOG(LL_DEBUG,
("%p %d bytes @ %d [%s]", c->fd, (int) hm->body.len, (int) oft, name));
if ((fp = fopen(path, oft == 0 ? "wb" : "a")) == NULL) {
mg_http_reply(c, 400, "fopen(%s): %d", name, errno);
mg_http_reply(c, 400, "", "fopen(%s): %d", name, errno);
return -2;
} else {
fwrite(hm->body.ptr, 1, hm->body.len, fp);
fclose(fp);
mg_http_reply(c, 200, "");
mg_http_reply(c, 200, "", "");
return hm->body.len;
}
}
@ -363,7 +362,7 @@ void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
char etag[64];
if (fp == NULL || stat(path, &st) != 0 ||
mg_http_etag(etag, sizeof(etag), &st) != etag) {
mg_http_reply(c, 404, "%s", "Not found\n");
mg_http_reply(c, 404, "", "%s", "Not found\n");
} else if (inm != NULL && mg_vcasecmp(inm, etag) == 0) {
mg_printf(c, "HTTP/1.1 304 Not Modified\r\nContent-Length: 0\r\n\r\n");
} else {
@ -583,7 +582,7 @@ static void listdir(struct mg_connection *c, struct mg_http_message *hm,
MG_VERSION);
mg_http_write_chunk(c, "", 0);
} else {
mg_http_reply(c, 400, "Cannot open dir");
mg_http_reply(c, 400, "", "Cannot open dir");
LOG(LL_DEBUG, ("%p opendir(%s) -> %d", c->fd, dir, errno));
}
}
@ -596,7 +595,7 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
if (realpath(dir, root) == NULL)
LOG(LL_DEBUG, ("realpath(%s): %d", dir, errno));
if (!mg_is_dir(root)) {
mg_http_reply(c, 400, "Bad web root [%s]\n", root);
mg_http_reply(c, 400, "", "Bad web root [%s]\n", root);
} else {
// NOTE(lsm): Xilinx snprintf does not 0-terminate the detination for
// the %.*s specifier, if the length is zero. Make sure hm->uri.len > 0
@ -612,7 +611,7 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
is_index = true;
}
if (strlen(real) < strlen(root) || memcmp(real, root, strlen(root)) != 0) {
mg_http_reply(c, 404, "Not found %.*s\n", hm->uri.len, hm->uri.ptr);
mg_http_reply(c, 404, "", "Not found %.*s\n", hm->uri.len, hm->uri.ptr);
} else {
FILE *fp = fopen(real, "r");
#if MG_ENABLE_HTTP_DEBUG_ENDPOINT
@ -622,7 +621,7 @@ void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
#if MG_ENABLE_DIRECTORY_LISTING
listdir(c, hm, real);
#else
mg_http_reply(c, 403, "%s", "Directory listing not supported");
mg_http_reply(c, 403, "", "%s", "Directory listing not supported");
#endif
} else {
mg_http_serve_file(c, hm, real, guess_content_type(real));

View File

@ -32,7 +32,8 @@ void mg_http_serve_dir(struct mg_connection *, struct mg_http_message *hm,
const char *path);
void mg_http_serve_file(struct mg_connection *, struct mg_http_message *,
const char *, const char *mime);
void mg_http_reply(struct mg_connection *c, int code, const char *fmt, ...);
void mg_http_reply(struct mg_connection *, int status_code, const char *headers,
const char *body_fmt, ...);
struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name);
void mg_http_event_handler(struct mg_connection *c, int ev);
int mg_http_get_var(const struct mg_str *, const char *name, char *, int);

View File

@ -323,19 +323,19 @@ static void eh1(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
("[%.*s %.*s] message len %d", (int) hm->method.len, hm->method.ptr,
(int) hm->uri.len, hm->uri.ptr, (int) hm->message.len));
if (mg_http_match_uri(hm, "/foo/*")) {
mg_http_reply(c, 200, "uri: %.*s", hm->uri.len - 5, hm->uri.ptr + 5);
mg_http_reply(c, 200, "", "uri: %.*s", hm->uri.len - 5, hm->uri.ptr + 5);
} else if (mg_http_match_uri(hm, "/ws")) {
mg_ws_upgrade(c, hm);
} else if (mg_http_match_uri(hm, "/body")) {
mg_http_reply(c, 200, "%.*s", (int) hm->body.len, hm->body.ptr);
mg_http_reply(c, 200, "", "%.*s", (int) hm->body.len, hm->body.ptr);
} else if (mg_http_match_uri(hm, "/bar")) {
mg_http_reply(c, 404, "not found");
mg_http_reply(c, 404, "", "not found");
} else if (mg_http_match_uri(hm, "/badroot")) {
mg_http_serve_dir(c, hm, "/BAAADDD!");
} else if (mg_http_match_uri(hm, "/creds")) {
char user[100], pass[100];
mg_http_creds(hm, user, sizeof(user), pass, sizeof(pass));
mg_http_reply(c, 200, "[%s]:[%s]", user, pass);
mg_http_reply(c, 200, "", "[%s]:[%s]", user, pass);
} else if (mg_http_match_uri(hm, "/upload")) {
mg_http_upload(c, hm, ".");
} else if (mg_http_match_uri(hm, "/test/")) {
@ -470,10 +470,10 @@ static void test_http_server(void) {
ASSERT(cmpbody(buf, "kuku") == 0);
ASSERT(fetch(&mgr, buf, url, "GET /badroot HTTP/1.0\r\n\n") == 400);
// LOG(LL_INFO, ("--> [%s]", buf));
#if MG_ARCH == MG_ARCH_WIN32
ASSERT(cmpbody(buf, "Bad web root [Z:\\BAAADDD!]\n") == 0);
#else
LOG(LL_INFO, ("--> [%s]", buf));
ASSERT(cmpbody(buf, "Bad web root [/BAAADDD!]\n") == 0);
#endif