mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-15 10:29:47 +00:00
232 lines
11 KiB
C
232 lines
11 KiB
C
#pragma once
|
|
|
|
#include "arch.h"
|
|
#include "config.h"
|
|
#include "fs.h"
|
|
#include "net.h"
|
|
#include "str.h"
|
|
|
|
// A single HTTP header name/value pair.
|
|
struct mg_http_header {
|
|
struct mg_str name; // Header name, e.g. "Content-Type"
|
|
struct mg_str value; // Header value, e.g. "text/html"
|
|
};
|
|
|
|
// Parsed HTTP request or response.
|
|
// Passed as ev_data in MG_EV_HTTP_MSG and MG_EV_HTTP_HDRS.
|
|
// For requests: method="GET", uri="/path", proto="a=1&b=2", proto="HTTP/1.1"
|
|
// For responses: method="HTTP/1.0", uri="200", query="", proto="OK"
|
|
struct mg_http_message {
|
|
struct mg_str method, uri, query, proto; // Request/response line
|
|
struct mg_http_header headers[MG_MAX_HTTP_HEADERS]; // Parsed headers array
|
|
struct mg_str body; // Request or response body
|
|
struct mg_str head; // Raw bytes: request/status line + headers, no body
|
|
struct mg_str message; // Raw bytes: head + body
|
|
};
|
|
|
|
// Options for mg_http_serve_dir() and mg_http_serve_file().
|
|
struct mg_http_serve_opts {
|
|
const char *root_dir; // Root directory for serving files, e.g. "/web"
|
|
const char *ssi_pattern; // Pattern for Server-Side Include files, e.g. "#.shtml". NULL disables SSI
|
|
const char *extra_headers; // Extra response headers, e.g. "A: b\r\nC: d\r\n". NULL for none
|
|
const char *mime_types; // Additional MIME types: "ext1=type1,ext2=type2". NULL for defaults only
|
|
const char *page404; // Path to a custom 404 page, e.g. "/404.html". NULL for built-in
|
|
struct mg_fs *fs; // Filesystem to use. NULL defaults to POSIX
|
|
bool allow_delete; // Allow to DELETE files
|
|
bool allow_upload; // Allow to POST/PUT files
|
|
};
|
|
|
|
// A single part of a multipart/form-data body, filled by mg_http_next_multipart().
|
|
struct mg_http_part {
|
|
struct mg_str name; // Form field name, from Content-Disposition: name="..."
|
|
struct mg_str filename; // Original filename for file uploads, empty for plain fields
|
|
struct mg_str body; // Part contents, points into the original message buffer
|
|
};
|
|
|
|
// Parses HTTP request or response in buffer s/len into hm.
|
|
// Returns number of bytes consumed, 0 if incomplete, -1 on error.
|
|
int mg_http_parse(const char *s, size_t len, struct mg_http_message *);
|
|
|
|
// Returns the byte length of HTTP headers in buf (i.e. offset of the body).
|
|
// Returns 0 if headers are incomplete, -1 on error.
|
|
int mg_http_get_request_len(const unsigned char *buf, size_t buf_len);
|
|
|
|
// Sends one chunk in HTTP chunked transfer encoding using printf-style fmt.
|
|
// Call with empty fmt ("") to send the terminating zero-length chunk.
|
|
void mg_http_printf_chunk(struct mg_connection *cnn, const char *fmt, ...);
|
|
|
|
// Sends one chunk in HTTP chunked transfer encoding from a raw buffer.
|
|
// Call with len=0 to send the terminating zero-length chunk.
|
|
void mg_http_write_chunk(struct mg_connection *c, const char *buf, size_t len);
|
|
|
|
// Creates an HTTP server on url, e.g. "http://0.0.0.0:8000".
|
|
//
|
|
// Returns:
|
|
// Listening connection, or NULL on error.
|
|
// Example:
|
|
// mg_http_listen(&mgr, "http://0.0.0.0:8000", fn, NULL);
|
|
// Full examples:
|
|
// tutorials/http/http-server, tutorials/http/*
|
|
// Related APIs:
|
|
// mg_http_reply(), mg_http_serve_dir(), mg_match()
|
|
// Notes:
|
|
// Call mg_mgr_poll() in the main loop. The user-supplied fn event handler
|
|
// receives normal connection events. It also receives MG_EV_HTTP_HDRS when
|
|
// headers are received and MG_EV_HTTP_MSG when the full request is received.
|
|
// ev_data for both HTTP events is struct mg_http_message *.
|
|
struct mg_connection *mg_http_listen(struct mg_mgr *, const char *url,
|
|
mg_event_handler_t fn, void *fn_data);
|
|
|
|
// Opens an HTTP client connection to url, e.g. "http://example.org".
|
|
//
|
|
// Returns:
|
|
// Client connection, or NULL on error.
|
|
// Example:
|
|
// mg_http_connect(&mgr, "http://example.org", fn, NULL);
|
|
// Full examples:
|
|
// tutorials/http/http-client, tutorials/http/huge-response
|
|
// Related APIs:
|
|
// mg_printf(), mg_http_status(), mg_http_get_header()
|
|
// Notes:
|
|
// In the user-supplied fn event handler, send the HTTP request on
|
|
// MG_EV_CONNECT. The handler receives normal connection events. It also
|
|
// receives MG_EV_HTTP_HDRS when headers are received and MG_EV_HTTP_MSG when
|
|
// the full response is received. ev_data for both HTTP events is struct
|
|
// mg_http_message *.
|
|
struct mg_connection *mg_http_connect(struct mg_mgr *, const char *url,
|
|
mg_event_handler_t fn, void *fn_data);
|
|
|
|
// Serves static files from a directory.
|
|
//
|
|
// Example:
|
|
// struct mg_http_serve_opts o = {.root_dir = "web_root", .fs = &mg_fs_posix};
|
|
// mg_http_serve_dir(c, hm, &o);
|
|
// Full examples:
|
|
// tutorials/http/http-server, tutorials/core/embedded-filesystem
|
|
// Related APIs:
|
|
// mg_http_listen(), mg_http_serve_file(), mg_http_reply(), mg_match()
|
|
// Notes:
|
|
// Call from an MG_EV_HTTP_MSG handler. The uri in hm is mapped under
|
|
// opts->root_dir. Directory listing depends on MG_ENABLE_DIRLIST; SSI uses
|
|
// opts->ssi_pattern when configured. opts->allow_delete enables DELETE;
|
|
// opts->allow_upload enables POST/PUT, writing the whole body to a file -
|
|
// see mg_http_serve_upload() to also stream big uploads without buffering.
|
|
void mg_http_serve_dir(struct mg_connection *, struct mg_http_message *hm,
|
|
const struct mg_http_serve_opts *);
|
|
|
|
// Serves a single file at path. Call from an MG_EV_HTTP_MSG handler.
|
|
void mg_http_serve_file(struct mg_connection *, struct mg_http_message *hm,
|
|
const char *path, const struct mg_http_serve_opts *);
|
|
|
|
// Streams a big POST/PUT upload straight to a file, instead of buffering the
|
|
// whole body. Optional companion to mg_http_serve_dir(): call this from
|
|
// MG_EV_HTTP_HDRS with the same opts, and keep calling mg_http_serve_dir()
|
|
// from MG_EV_HTTP_MSG as usual - it still handles uploads this function skips.
|
|
// Does nothing unless opts->allow_upload is set, the method is POST or PUT,
|
|
// and Content-Length is known and big enough.
|
|
void mg_http_serve_upload(struct mg_connection *, struct mg_http_message *hm,
|
|
const struct mg_http_serve_opts *);
|
|
|
|
// Sends a complete HTTP response with Content-Length.
|
|
//
|
|
// Example:
|
|
// mg_http_reply(c, 200, "Content-Type: application/json\r\n",
|
|
// "{%m:%d}", MG_ESC("temperature"), 123);
|
|
// Full examples:
|
|
// tutorials/http/http-server, tutorials/http/http-restful-server,
|
|
// tutorials/http/device-dashboard
|
|
// Related APIs:
|
|
// mg_http_listen(), mg_printf(), mg_http_printf_chunk(), MG_ESC
|
|
// Notes:
|
|
// headers must end with "\r\n"; pass "" or NULL for no extra headers.
|
|
// body_fmt is printf-style and supports %M/%m custom printers. Use MG_ESC
|
|
// when printing JSON strings.
|
|
void mg_http_reply(struct mg_connection *, int status_code, const char *headers,
|
|
const char *body_fmt, ...);
|
|
|
|
// Looks up a request header by name (case-insensitive).
|
|
// Returns a pointer to the mg_str value, or NULL if not found.
|
|
struct mg_str *mg_http_get_header(struct mg_http_message *, const char *name);
|
|
|
|
// Extracts a named variable from a query string or form-encoded body (buf).
|
|
// Returns the raw (URL-encoded) value as mg_str, or an empty mg_str if not found.
|
|
// Not NUL-terminated. Use mg_url_decode() to get a decoded string.
|
|
struct mg_str mg_http_var(struct mg_str buf, struct mg_str name);
|
|
|
|
// URL-decodes variable name from query string or form body into a NUL-terminated buffer.
|
|
// Returns the length of the decoded value, or negative if not found / buffer too small.
|
|
int mg_http_get_var(const struct mg_str *, const char *name, char *, size_t);
|
|
|
|
// URL-decodes s/n into to/to_len. Set form=1 to also decode '+' as space.
|
|
// Returns number of bytes written, or -1 if to buffer is too small.
|
|
int mg_url_decode(const char *s, size_t n, char *to, size_t to_len, int form);
|
|
|
|
// URL-encodes s/n into buf/len. Returns number of bytes written.
|
|
size_t mg_url_encode(const char *s, size_t n, char *buf, size_t len);
|
|
|
|
// Extracts HTTP credentials into caller-supplied buffers.
|
|
// For Basic auth: fills user (buf1) and password (buf2).
|
|
// For Bearer auth: fills buf1 with "" and buf2 with the token.
|
|
void mg_http_creds(struct mg_http_message *, char *, size_t, char *, size_t);
|
|
|
|
// Deprecated API, do not expose
|
|
long mg_http_upload(struct mg_connection *c, struct mg_http_message *hm,
|
|
struct mg_fs *fs, const char *dir, size_t max_size);
|
|
|
|
// Sends a 401 Unauthorized response with a Basic Auth WWW-Authenticate challenge.
|
|
void mg_http_bauth(struct mg_connection *, const char *user, const char *pass);
|
|
|
|
// Extracts a named parameter from a header value string s.
|
|
// E.g. for s="multipart/form-data; boundary=abc", v="boundary" returns "abc".
|
|
struct mg_str mg_http_get_header_var(struct mg_str s, struct mg_str v);
|
|
|
|
// Iterates over parts of a multipart/form-data body.
|
|
//
|
|
// Returns:
|
|
// Offset for the next call, or 0 when there are no more parts.
|
|
// Example:
|
|
// size_t ofs = 0;
|
|
// struct mg_http_part part;
|
|
// while ((ofs = mg_http_next_multipart(hm->body, ofs, &part)) > 0) { ... }
|
|
// Full examples:
|
|
// tutorials/http/file-upload-html-form, tutorials/http/http-server
|
|
// Related APIs:
|
|
// mg_http_listen(), mg_http_stream_body()
|
|
// Notes:
|
|
// Call from an MG_EV_HTTP_MSG handler after the full request body is
|
|
// received. part.name, part.filename, and part.body are zero-copy slices into
|
|
// hm->body and are not NUL-terminated.
|
|
size_t mg_http_next_multipart(struct mg_str, size_t, struct mg_http_part *);
|
|
|
|
// Returns the HTTP status code from a parsed response message (e.g. 200, 404).
|
|
int mg_http_status(const struct mg_http_message *hm);
|
|
|
|
// Streams a POST/PUT body to a callback as it arrives, without buffering it.
|
|
// Call it from an MG_EV_HTTP_HDRS handler, after matching the request, e.g.
|
|
// with mg_match(). Returns true if it took over the connection, false if the
|
|
// request is not POST/PUT, is chunked, or has no Content-Length.
|
|
//
|
|
// Callback upload_fn(hm, data, user_data) is called:
|
|
// - at start: hm is set. Open the file, set *user_data.
|
|
// - per chunk: data is set, 512 byte aligned except the last. Not called
|
|
// again after a failure.
|
|
// - at end: both NULL. Always called once, also when the connection drops
|
|
// early, so release resources here. A truncated body looks like a complete
|
|
// one: validate before committing.
|
|
// Return true on success, false on error.
|
|
// Example:
|
|
// if (ev == MG_EV_HTTP_HDRS && mg_match(hm->uri, mg_str("/fs/*"), NULL) {
|
|
// mg_http_stream_body(c, hm, upload, NULL));
|
|
// }
|
|
// Full example:
|
|
// tutorials/http/file-upload-single-post
|
|
// Related APIs:
|
|
// mg_http_listen(), mg_http_next_multipart()
|
|
// Notes:
|
|
// After it returns true, this function hijacks the connection. Existing event
|
|
// handler not called, hm is invalid, c->data and c->fn_data are modified
|
|
bool mg_http_stream_body(struct mg_connection *c, struct mg_http_message *hm,
|
|
bool (*upload_fn)(struct mg_http_message *,
|
|
struct mg_str *, void **user_data),
|
|
void *user_data);
|