HTTP
struct mg_http_header
struct mg_http_header {
struct mg_str name; // Header name
struct mg_str value; // Header value
};
Structure represents HTTP header, like Content-Type: text/html.
Content-Type is a header name and text/html is a header value.
struct mg_http_message
struct mg_http_message {
struct mg_str method, uri, query, proto; // Request/response line
struct mg_http_header headers[MG_MAX_HTTP_HEADERS]; // Headers
struct mg_str body; // Body
struct mg_str message; // Request line + headers + body
};
Structure represents the HTTP message.
mg_http_listen()
struct mg_connection *mg_http_listen(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fn_data);
Create HTTP listener.
Parameters:
mgr- An event managerurl- A URL, specifies local IP address and port to listen on, e.g.http://0.0.0.0:8000. If this URL is 'https', theis_tlsflag will be setfn- An event handler functionfn_data- an arbitrary pointer, which will be stored in the connection structure asc->fn_data, so the event handler can use it when called.
Return value: Pointer to created connection or NULL in case of error
Usage example:
struct mg_connection *c = mg_http_listen(&mgr, "0.0.0.0:8000", fn, arg);
if (c == NULL) fatal_error("Cannot create listener");
mg_http_connect()
struct mg_connection *mg_http_connect(struct mg_mgr *, const char *url,
mg_event_handler_t fn, void *fn_data);
Create HTTP client connection.
Parameters:
mgr- An event managerurl- A URL, specifies remote URL, e.g.http://google.com. If this URL is 'https', theis_tlsflag will be setfn- An event handler functionfn_data- an arbitrary pointer, which will be stored in the connection structure asc->fn_data, so the event handler can use it when called.
Return value: created connection, or NULL on error. Possible errors are: not enough memory, a NULL URL, or, in the case of our built-in TCP/IP stack, the network not being ready.
Note: This function does not connect to the requested peer, it allocates required resources and starts the connection process. Once our peer is really connected, an MG_EV_CONNECT event is sent
to the connection event handler.
Usage example:
struct mg_connection *c = mg_http_connect(&mgr, "http://google.com", fn, NULL);
if (c == NULL) fatal_error("Cannot create connection");
mg_http_status()
int mg_http_status(const struct mg_http_message *hm);
Get status code of the HTTP response. Parameters:
hm- Parsed HTTP response
Return value: status code, e.g. 200 for success.
mg_http_get_request_len()
int mg_http_get_request_len(const unsigned char *buf, size_t buf_len);
Get length of request.
The length of request is a number of bytes till the end of HTTP headers. It does not include length of HTTP body.
Parameters:
buf- A pointer to a buffer with requestbuf_len- Buffer length
Return value: -1 on error, 0 if a message is incomplete, or the length of request
Usage example:
const char *buf = "GET /test \n\nGET /foo\n\n";
int req_len = mg_http_get_request_len(buf, strlen(buf)); // req_len == 12
mg_http_parse()
int mg_http_parse(const char *s, size_t len, struct mg_http_message *hm);
Parse string request into mg_http_message structure
Parameters:
s- A request stringlen- A request string lengthhm- A pointer to a structure to store parsed request
Return value: request length (see mg_http_get_request_len())
Usage example:
struct mg_http_message hm;
const char *buf = "GET / HTTP/1.0\n\n";
if (mg_http_parse(buf, strlen(buf), &hm) > 0) { /* success */ }
mg_http_printf_chunk()
void mg_http_printf_chunk(struct mg_connection *c, const char *fmt, ...);
Write a chunk of data in chunked encoding format, using printf() semantic.
Parameters:
c- A connection pointerfmt- A string, format specified inprintfsemantics
Return value: None
Usage example:
mg_http_printf_chunk(c, "Hello, %s!", "world");
mg_http_write_chunk()
void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len);
Write a chunk of data in chunked encoding format.
Parameters:
c- A connection pointerbuf- Data to writelen- Data length
Return value: None
Usage example:
mg_http_write_chunk(c, "hi", 2);
struct mg_http_serve_opts
struct mg_http_serve_opts {
const char *root_dir; // Web root directory, must be non-NULL
const char *ssi_pattern; // SSI file name pattern, e.g. #.shtml
const char *extra_headers; // Extra HTTP headers to add in responses
const char *mime_types; // Extra mime types, ext1=type1,ext2=type2,..
const char *page404; // Path to the 404 page, or NULL by default
struct mg_fs *fs; // Filesystem implementation. Use NULL for POSIX
};
A structure passed to mg_http_serve_dir() and mg_http_serve_file(), which
drives the behavior of those two functions.
In addition to overwriting autodetection based on an extension, you can also use * as an extension in mime_types to force a particular MIME type for unknown extensions:
sopts.mime_types = "*=preferred/default,txt=override/text"
mg_http_serve_dir()
void mg_http_serve_dir(struct mg_connection *c, struct mg_http_message *hm,
const struct mg_http_serve_opts *opts);
Serve static files according to the given options. Files can also be gzip compressed, including the directory index. All compressed files must end in .gz and there must not exist a file with the same name without the extension, otherwise it will take precedence; see mg_http_serve_file()
NOTE: In order to enable SSI, you need to set the
-DMG_ENABLE_SSI=1build flag.
NOTE: Avoid double dots
..in theroot_dir. If you need to reference an upper-level directory, use an absolute path.
Parameters:
c- Connection to usehm- HTTP message, that should be servedopts- Serve options. Note thatopts.root_dircan optionally accept extra comma-separateduri=pathpairs, see example below
Return value: None
Usage example:
// Mongoose events handler
void fn(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
struct mg_http_serve_opts opts;
memset(&opts, 0, sizeof(opts));
opts.root_dir = "/var/www,/conf=/etc"; // Serve /var/www. URIs starting with /conf are served from /etc
mg_http_serve_dir(c, hm, &opts);
}
}
mg_http_serve_file()
void mg_http_serve_file(struct mg_connection *c, struct mg_http_message *hm,
const char *path, struct mg_http_serve_opts *opts);
Serve a static file. If a file with the filename specified in path does not exist, Mongoose tries appending .gz; and if such a file exists, it will serve it with a Content-Encoding: gzip header
NOTE:
opts->root_dirsettings is ignored by this function.
NOTE:
opts->extra_headers, if not NULL, must end with\r\n.
Parameters:
c- Connection to usehm- HTTP message to servepath- Path to file to serveopts- Serve options
Return value: None
Usage example:
// Mongoose events handler
void fn(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
struct mg_http_serve_opts opts = {
.mime_types = "png=image/png",
.extra_headers = "AA: bb\r\nCC: dd\r\n"
};
mg_http_serve_file(c, hm, "a.png", &opts);
}
}
mg_http_reply()
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. 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.
Parameters:
c- Connection to usestatus_code- An HTTP response codeheaders- Extra headers, default NULL. If not NULL, must end with\r\nfmt- A format string for the HTTP body, in a printf semantics
Return value: None
Usage examples:
Send a simple JSON response:
mg_http_reply(c, 200, "Content-Type: application/json\r\n", "{\"result\": %d}", 123);
Send JSON response:
char *json = mg_mprintf("{%m:%d}", MG_ESC("name"), 123);
mg_http_reply(c, 200, "Content-Type: application/json\r\n", "%s\n", json);
mg_free(json);
Send a 302 redirect:
mg_http_reply(c, 302, "Location: /\r\n", "");
Send error:
mg_http_reply(c, 403, "", "%s", "Not Authorized\n");
mg_http_get_header()
struct mg_str *mg_http_get_header(struct mg_http_message *hm, const char *name);
Get HTTP header value
Parameters:
hm- HTTP message to look for headername- Header name
Return value: HTTP header value or NULL if not found
Usage example:
// Mongoose event handler
void fn(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
struct mg_str *s = mg_http_get_header(hm, "X-Extra-Header");
if (s != NULL) {
mg_http_reply(c, 200, "", "Holly molly! Header value: %.*s", (int) s->len, s->buf);
} else {
mg_http_reply(c, 200, "", "Oh no, header is not set...");
}
}
}
mg_http_get_header_var()
struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v);
Parse HTTP header (e.g. Cookie header) which has form
name1=value1; name2=value2; ... and fetch a given variable.
Parameters:
s- HTTP headername- variable name name
Return value: a requested variable, or an empty string.
Usage example:
struct mg_str *cookie = mg_http_get_header(hm, "Cookie");
struct mg_str token = mg_str("");
if (cookie != NULL) {
token = mg_http_get_header_var(*cookie, mg_str("access_token"));
}
mg_http_var()
struct mg_str mg_http_var(struct mg_str buf, struct mg_str name);
Fetch an undecoded HTTP variable. Parameters:
buf- a url-encoded string: HTTP request body or query stringname- a variable name to fetch
Return value: variable's value. If not found, it is a NULL string.
// We have received a request to /my/uri?a=b&c=d%20
// The hm->query points to "a=b&c=d%20"
struct mg_str v = mg_http_var(hm->query, mg_str("c")); // v = "d%20"
mg_http_get_var()
int mg_http_get_var(const struct mg_str *var, const char *name, char *buf, int len);
Fetch and decode an HTTP variable
Parameters:
var- HTTP request bodyname- Variable namebuf- Buffer to write decoded variablelen- Buffer size
Return value: Length of decoded variable. A zero or negative value means error
Usage example:
char buf[100] = "";
mg_http_get_var(&hm->body, "key1", buf, sizeof(buf)) {
...
}
mg_http_creds()
void mg_http_creds(struct mg_http_message *hm, char *user, size_t userlen,
char *pass, size_t passlen);
Fetch authentication credential from the request, and store into the
user, userlen and pass, passlen buffers. The credentials are looked
up in the following order:
- from the
AuthorizationHTTP header,- Basic auth fills both user and pass
- Bearer auth fills only pass
- from the
access_tokencookie, fills pass - from the
?access_token=...query string parameter, fills pass
If none is found, then both user and pass are set to empty nul-terminated strings.
Parameters:
hm- HTTP message to look for credentialsuser- buffer to receive user nameuserlen- size ofuserbufferpass- buffer to receive passwordpasslen- size ofpassbuffer
Return value: None
Usage example:
// Mongoose events handler
void fn(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
char user[100], pass[100];
mg_http_creds(hm, user, sizeof(user), pass, sizeof(pass)); // "user" is now user name and "pass" is now password from request
}
}
mg_http_bauth()
void mg_http_bauth(struct mg_connection *c, const char *user, const char *pass);
Write a Basic Authorization header to the output buffer.
Parameters:
c- Connection to useuser- User namepass- Password
Return value: None
Usage example which uses Basic auth to create Stripe subscription:
mg_printf(c, "POST /v1/subscriptions HTTP/1.1\r\n"
"Host: api.stripe.com\r\n"
"Transfer-Encoding: chunked\r\n");
mg_http_bauth(c, stripe_private_key, NULL); // Add Basic auth header
mg_printf(c, "%s", "\r\n"); // End HTTP headers
mg_http_printf_chunk(c, "&customer=%s", customer_id); // Set customer
mg_http_printf_chunk(c, "&items[0][price]=%s", price); // And price
mg_http_printf_chunk(c, ""); // End request
struct mg_http_part
// Parameter for mg_http_next_multipart
struct mg_http_part {
struct mg_str name; // Form field name
struct mg_str filename; // Filename for file uploads
struct mg_str body; // Part contents
};
Structure that describes a single part of a HTTP multipart message.
mg_http_next_multipart()
size_t mg_http_next_multipart(struct mg_str body, size_t offset, struct mg_http_part *part);
Parse the multipart chunk in the body at a given offset. An initial
offset should be 0. Fill up parameters in the provided part, which could be
NULL. Return offset to the next chunk, or 0 if there are no more chunks.
Parameters:
body- Message bodyoffset- Start offsetpart- Pointer tostruct mg_http_partto fill
Return value: offset to the next chunk, or 0 if there are no more chunks.
Usage example (or see form upload tutorial ):
struct mg_http_part part;
size_t pos = 0;
while ((pos = mg_http_next_multipart(body, pos, &part)) != 0) {
MG_INFO(("Chunk name: [%.*s] filename: [%.*s] length: %lu bytes",
part.name.len, part.name.buf,
part.filename.len, part.filename.buf, part.body.len));
// Use this chunk ....
}
A diagram below shows how mg_http_next_multipart() in action:
mg_http_upload()
long mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
struct mg_fs *fs, const char *dir, size_t max_size);
This is a helper utility function that is used to upload large files by small chunks.
Append HTTP POST data to a file in a specified directory. A file name and
file offset are specified by the query string parameters:
POST /upload?file=firmware.bin&offset=2048 HTTP/1.1. If the offset is 0, then the
file is truncated. It is the client's responsibility to divide files into
smaller chunks and send a sequence of POST requests that will be handled by
this function. The full path will be checked for sanity
Parameters:
c- a connectionhm- a parsed HTTP messagefs- a filesystem where to write the files, e.g.&mg_fs_posixdir- a directory path where to write the filesmax_size- maximum allowed file size
Return value: file size after write, or negative number on error
Usage example:
static void fn(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_MSG) {
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
if (mg_match(hm->uri, mg_str("/upload"), NULL)) {
mg_http_upload(c, hm, &mg_fs_posix, "/tmp", 99999);
} else {
struct mg_http_serve_opts opts = {.root_dir = "."}; // Serve
mg_http_serve_dir(c, ev_data, &opts); // static content
}
}
}