Commit 12437fd7 authored by Sergey Lyubka's avatar Sergey Lyubka Committed by Cesanta Bot

Refactor Mongoose documentation

PUBLISHED_FROM=e9a4e5c7b4a1d03b93a2a79e29de19e60e919929
parent 4120f953
---
title: "CoAP"
title: "CoAP API reference"
symbol_kind: "intro"
decl_name: "coap.h"
items:
- { type: file, name: mg_set_protocol_coap.md }
- { type: file, name: mg_coap_add_option.md }
- { type: file, name: mg_coap_free_options.md }
- { type: file, name: mg_coap_send_message.md }
- { type: file, name: mg_coap_send_ack.md }
- { type: file, name: mg_coap_parse.md }
- { type: file, name: mg_coap_compose.md }
- { type: file, name: struct_mg_coap_option.md }
- { type: file, name: struct_mg_coap_message.md }
- { name: mg_set_protocol_coap.md }
- { name: mg_coap_add_option.md }
- { name: mg_coap_free_options.md }
- { name: mg_coap_send_message.md }
- { name: mg_coap_send_ack.md }
- { name: mg_coap_parse.md }
- { name: mg_coap_compose.md }
- { name: struct_mg_coap_option.md }
- { name: struct_mg_coap_message.md }
---
CoAP message format:
......
---
title: "DNS"
title: "DNS API reference"
symbol_kind: "intro"
decl_name: "dns.h"
items:
- { type: file, name: mg_dns_parse_record_data.md }
- { type: file, name: mg_send_dns_query.md }
- { type: file, name: mg_dns_insert_header.md }
- { type: file, name: mg_dns_copy_questions.md }
- { type: file, name: mg_dns_encode_record.md }
- { type: file, name: mg_parse_dns.md }
- { type: file, name: mg_dns_uncompress_name.md }
- { type: file, name: mg_set_protocol_dns.md }
- { type: file, name: struct_mg_dns_resource_record.md }
- { type: file, name: struct_mg_dns_message.md }
- { name: mg_dns_parse_record_data.md }
- { name: mg_send_dns_query.md }
- { name: mg_dns_insert_header.md }
- { name: mg_dns_copy_questions.md }
- { name: mg_dns_encode_record.md }
- { name: mg_parse_dns.md }
- { name: mg_dns_uncompress_name.md }
- { name: mg_set_protocol_dns.md }
- { name: struct_mg_dns_resource_record.md }
- { name: struct_mg_dns_message.md }
---
......
---
title: "DNS server"
title: "DNS server API reference"
symbol_kind: "intro"
decl_name: "dns-server.h"
decl_name: "dns_server.h"
items:
- { type: file, name: mg_dns_create_reply.md }
- { type: file, name: mg_dns_reply_record.md }
- { type: file, name: mg_dns_send_reply.md }
- { name: mg_dns_create_reply.md }
- { name: mg_dns_reply_record.md }
- { name: mg_dns_send_reply.md }
---
Disabled by default; enable with `-DMG_ENABLE_DNS_SERVER`.
......
---
title: "HTTP + Websocket"
title: "Common API reference"
symbol_kind: "intro"
decl_name: "http.h"
items:
- { type: file, name: mg_set_protocol_http_websocket.md }
- { type: file, name: mg_send_websocket_handshake.md }
- { type: file, name: mg_send_websocket_handshake2.md }
- { type: file, name: mg_connect_ws.md }
- { type: file, name: mg_connect_ws_opt.md }
- { type: file, name: mg_send_websocket_frame.md }
- { type: file, name: mg_send_websocket_framev.md }
- { type: file, name: mg_printf_websocket_frame.md }
- { type: file, name: mg_send_http_chunk.md }
- { type: file, name: mg_printf_http_chunk.md }
- { type: file, name: mg_send_response_line.md }
- { type: file, name: mg_send_head.md }
- { type: file, name: mg_printf_html_escape.md }
- { type: file, name: mg_parse_http.md }
- { type: file, name: mg_get_http_header.md }
- { type: file, name: mg_http_parse_header.md }
- { type: file, name: mg_parse_multipart.md }
- { type: file, name: mg_get_http_var.md }
- { type: file, name: mg_url_decode.md }
- { type: file, name: mg_http_create_digest_auth_header.md }
- { 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 }
- { type: file, name: mg_fu_fname_fn.md }
- { type: file, name: struct_http_message.md }
- { type: file, name: struct_websocket_message.md }
- { type: file, name: struct_mg_http_multipart_part.md }
- { type: file, name: struct_mg_serve_http_opts.md }
- { name: mg_set_protocol_http_websocket.md }
- { name: mg_send_websocket_handshake.md }
- { name: mg_send_websocket_handshake2.md }
- { name: mg_connect_ws.md }
- { name: mg_connect_ws_opt.md }
- { name: mg_send_websocket_frame.md }
- { name: mg_send_websocket_framev.md }
- { name: mg_printf_websocket_frame.md }
- { name: mg_url_decode.md }
- { name: struct_http_message.md }
- { name: struct_websocket_message.md }
- { name: struct_mg_http_multipart_part.md }
---
......
......@@ -7,12 +7,12 @@ signature: |
int is_form_url_encoded);
---
Decodes URL-encoded string.
Decodes a URL-encoded string.
Source string is specified by (`src`, `src_len`), and destination is
(`dst`, `dst_len`). If `is_form_url_encoded` is non-zero, then
`+` character is decoded as a blank space character. This function
guarantees to `\0`-terminate the destination. If destination is too small,
guarantees to NUL-terminate the destination. If destination is too small,
then the source string is partially decoded and `-1` is returned. Otherwise,
a length of decoded string is returned, not counting final `\0`.
a length of the decoded string is returned, not counting final NUL.
---
title: "Client API reference"
symbol_kind: "intro"
decl_name: "http_client.h"
items:
- { name: mg_connect_http.md }
- { name: mg_connect_http_opt.md }
- { name: mg_http_create_digest_auth_header.md }
---
......@@ -12,7 +12,7 @@ signature: |
Helper function that creates an outbound HTTP connection.
`url` is a URL to fetch. It must be properly URL-encoded, e.g. have
`url` is the URL to fetch. It must be properly URL-encoded, e.g. have
no spaces, etc. By default, `mg_connect_http()` sends the Connection and
Host headers. `extra_headers` is an extra HTTP header to send, e.g.
`"User-Agent: my-app\r\n"`.
......
---
title: "Server API reference"
symbol_kind: "intro"
decl_name: "http_server.h"
items:
- { name: mg_parse_http.md }
- { name: mg_get_http_header.md }
- { name: mg_http_parse_header.md }
- { name: mg_parse_multipart.md }
- { name: mg_get_http_var.md }
- { name: mg_serve_http.md }
- { name: mg_http_serve_file.md }
- { name: mg_register_http_endpoint.md }
- { name: mg_file_upload_handler.md }
- { name: mg_http_check_digest_auth.md }
- { name: mg_send_http_chunk.md }
- { name: mg_printf_http_chunk.md }
- { name: mg_send_response_line.md }
- { name: mg_send_head.md }
- { name: mg_printf_html_escape.md }
- { name: mg_fu_fname_fn.md }
- { name: struct_mg_serve_http_opts.md }
---
......@@ -7,8 +7,9 @@ signature: |
int64_t content_length, const char *extra_headers);
---
Sends a response line and headers.
This function sends a response line with the `status_code`, and automatically
Sends the response line and headers.
This function sends the response line with the `status_code`, and
automatically
sends one header: either "Content-Length" or "Transfer-Encoding".
If `content_length` is negative, then "Transfer-Encoding: chunked" header
is sent, otherwise, "Content-Length" header is sent.
......
......@@ -9,9 +9,8 @@ signature: |
Sends buffer `buf` of size `len` to the client using chunked HTTP encoding.
This function sends the buffer size as hex number + newline first, then
the buffer itself, then the newline. For example,
`mg_send_http_chunk(nc, "foo", 3)` whill append the `3\r\nfoo\r\n` string
*to
the `nc->send_mbuf` output IO buffer.
`mg_send_http_chunk(nc, "foo", 3)` whill append the `3\r\nfoo\r\n` string
to the `nc->send_mbuf` output IO buffer.
NOTE: The HTTP header "Transfer-Encoding: chunked" should be sent prior to
using this function.
......
......@@ -7,7 +7,7 @@ signature: |
const char *extra_headers);
---
Sends a response status line.
Sends the response status line.
If `extra_headers` is not NULL, then `extra_headers` are also sent
after the reponse line. `extra_headers` must NOT end end with new line.
Example:
......
---
items:
- { type: dir, name: mbuf.h }
- { type: dir, name: net.h }
- { type: dir, name: http.h }
- { type: dir, name: dns.h }
- { type: dir, name: dns-server.h }
- { type: dir, name: mqtt.h }
- { type: dir, name: mqtt-broker.h }
- { type: dir, name: coap.h }
- { type: dir, name: util.h }
- { name: mbuf.h }
- { name: net.h }
- { name: http.h }
- { name: http_server.h }
- { name: http_client.h }
- { name: dns.h }
- { name: dns_server.h }
- { name: resolv.h }
- { name: mqtt.h }
- { name: mqtt_server.h }
- { name: coap.h }
- { name: util.h }
- { name: uri.h }
---
......@@ -3,14 +3,14 @@ title: "Memory Buffers"
symbol_kind: "intro"
decl_name: "mbuf.h"
items:
- { type: file, name: mbuf_init.md }
- { type: file, name: mbuf_free.md }
- { type: file, name: mbuf_append.md }
- { type: file, name: mbuf_insert.md }
- { type: file, name: mbuf_remove.md }
- { type: file, name: mbuf_resize.md }
- { type: file, name: mbuf_trim.md }
- { type: file, name: struct_mbuf.md }
- { name: mbuf_init.md }
- { name: mbuf_free.md }
- { name: mbuf_append.md }
- { name: mbuf_insert.md }
- { name: mbuf_remove.md }
- { name: mbuf_resize.md }
- { name: mbuf_trim.md }
- { name: struct_mbuf.md }
---
Mbufs are mutable/growing memory buffers, like C++ strings.
......
---
title: "MQTT Broker"
symbol_kind: "intro"
decl_name: "mqtt-broker.h"
items:
- { type: file, name: mg_mqtt_broker_init.md }
- { type: file, name: mg_mqtt_broker.md }
- { type: file, name: mg_mqtt_next.md }
- { type: file, name: struct_mg_mqtt_session.md }
- { type: file, name: struct_mg_mqtt_broker.md }
---
---
title: "MQTT"
title: "MQTT API reference"
symbol_kind: "intro"
decl_name: "mqtt.h"
items:
- { type: file, name: mg_set_protocol_mqtt.md }
- { type: file, name: mg_send_mqtt_handshake.md }
- { type: file, name: mg_send_mqtt_handshake_opt.md }
- { type: file, name: mg_mqtt_publish.md }
- { type: file, name: mg_mqtt_subscribe.md }
- { type: file, name: mg_mqtt_unsubscribe.md }
- { type: file, name: mg_mqtt_disconnect.md }
- { type: file, name: mg_mqtt_connack.md }
- { type: file, name: mg_mqtt_puback.md }
- { type: file, name: mg_mqtt_pubrec.md }
- { type: file, name: mg_mqtt_pubrel.md }
- { type: file, name: mg_mqtt_pubcomp.md }
- { type: file, name: mg_mqtt_suback.md }
- { type: file, name: mg_mqtt_unsuback.md }
- { type: file, name: mg_mqtt_ping.md }
- { type: file, name: mg_mqtt_pong.md }
- { type: file, name: mg_mqtt_next_subscribe_topic.md }
- { type: file, name: struct_mg_mqtt_topic_expression.md }
- { name: mg_set_protocol_mqtt.md }
- { name: mg_send_mqtt_handshake.md }
- { name: mg_send_mqtt_handshake_opt.md }
- { name: mg_mqtt_publish.md }
- { name: mg_mqtt_subscribe.md }
- { name: mg_mqtt_unsubscribe.md }
- { name: mg_mqtt_disconnect.md }
- { name: mg_mqtt_connack.md }
- { name: mg_mqtt_puback.md }
- { name: mg_mqtt_pubrec.md }
- { name: mg_mqtt_pubrel.md }
- { name: mg_mqtt_pubcomp.md }
- { name: mg_mqtt_suback.md }
- { name: mg_mqtt_unsuback.md }
- { name: mg_mqtt_ping.md }
- { name: mg_mqtt_pong.md }
- { name: mg_mqtt_next_subscribe_topic.md }
- { name: struct_mg_mqtt_topic_expression.md }
---
......
---
title: "MQTT Server API reference"
symbol_kind: "intro"
decl_name: "mqtt_server.h"
items:
- { name: mg_mqtt_broker_init.md }
- { name: mg_mqtt_broker.md }
- { name: mg_mqtt_next.md }
- { name: struct_mg_mqtt_session.md }
- { name: struct_mg_mqtt_broker.md }
---
---
title: "Core: TCP/UDP/SSL"
title: "Core API: TCP/UDP/SSL"
symbol_kind: "intro"
decl_name: "net.h"
items:
- { type: file, name: mg_mgr_init.md }
- { type: file, name: mg_mgr_free.md }
- { type: file, name: mg_mgr_poll.md }
- { type: file, name: mg_broadcast.md }
- { type: file, name: mg_next.md }
- { type: file, name: mg_add_sock.md }
- { type: file, name: mg_add_sock_opt.md }
- { type: file, name: mg_bind.md }
- { type: file, name: mg_bind_opt.md }
- { type: file, name: mg_connect.md }
- { type: file, name: mg_connect_opt.md }
- { type: file, name: mg_set_ssl.md }
- { type: file, name: mg_send.md }
- { type: file, name: mg_printf.md }
- { type: file, name: mg_vprintf.md }
- { type: file, name: mg_socketpair.md }
- { type: file, name: mg_check_ip_acl.md }
- { type: file, name: mg_enable_multithreading.md }
- { type: file, name: mg_enable_javascript.md }
- { type: file, name: mg_set_timer.md }
- { type: file, name: mg_time.md }
- { type: file, name: mg_event_handler_t.md }
- { type: file, name: struct_mg_mgr.md }
- { type: file, name: struct_mg_connection.md }
- { type: file, name: struct_mg_add_sock_opts.md }
- { type: file, name: struct_mg_bind_opts.md }
- { type: file, name: struct_mg_connect_opts.md }
- { name: mg_mgr_init.md }
- { name: mg_mgr_free.md }
- { name: mg_mgr_poll.md }
- { name: mg_broadcast.md }
- { name: mg_next.md }
- { name: mg_add_sock.md }
- { name: mg_add_sock_opt.md }
- { name: mg_bind.md }
- { name: mg_bind_opt.md }
- { name: mg_connect.md }
- { name: mg_connect_opt.md }
- { name: mg_set_ssl.md }
- { name: mg_send.md }
- { name: mg_printf.md }
- { name: mg_vprintf.md }
- { name: mg_socketpair.md }
- { name: mg_check_ip_acl.md }
- { name: mg_enable_multithreading.md }
- { name: mg_enable_javascript.md }
- { name: mg_set_timer.md }
- { name: mg_time.md }
- { name: mg_event_handler_t.md }
- { name: struct_mg_mgr.md }
- { name: struct_mg_connection.md }
- { name: struct_mg_add_sock_opts.md }
- { name: struct_mg_bind_opts.md }
- { name: struct_mg_connect_opts.md }
---
NOTE: Mongoose manager is single threaded. It does not protect
......
---
title: "API reference"
symbol_kind: "intro"
decl_name: "resolv.h"
items:
- { name: mg_resolve_async.md }
- { name: mg_resolve_async_opt.md }
- { name: mg_resolve_from_hosts_file.md }
- { name: struct_mg_resolve_async_opts.md }
---
---
title: "mg_resolve_async()"
decl_name: "mg_resolve_async"
symbol_kind: "func"
signature: |
int mg_resolve_async(struct mg_mgr *mgr, const char *name, int query,
mg_resolve_callback_t cb, void *data);
---
See `mg_resolve_async_opt()`
---
title: "mg_resolve_async_opt()"
decl_name: "mg_resolve_async_opt"
symbol_kind: "func"
signature: |
int mg_resolve_async_opt(struct mg_mgr *mgr, const char *name, int query,
mg_resolve_callback_t cb, void *data,
struct mg_resolve_async_opts opts);
---
Resolved a DNS name asynchronously.
Upon successful resolution, the user callback will be invoked
with the full DNS response message and a pointer to the user's
context `data`.
In case of timeout while performing the resolution the callback
will receive a NULL `msg`.
The DNS answers can be extracted with `mg_next_record` and
`mg_dns_parse_record_data`:
[source,c]
----
struct in_addr ina;
struct mg_dns_resource_record *rr = mg_next_record(msg, MG_DNS_A_RECORD,
NULL);
mg_dns_parse_record_data(msg, rr, &ina, sizeof(ina));
----
---
title: "mg_resolve_from_hosts_file()"
decl_name: "mg_resolve_from_hosts_file"
symbol_kind: "func"
signature: |
int mg_resolve_from_hosts_file(const char *host, union socket_address *usa);
---
Resolve a name from `/etc/hosts`.
Returns 0 on success, -1 on failure.
---
title: "struct mg_resolve_async_opts"
decl_name: "struct mg_resolve_async_opts"
symbol_kind: "struct"
signature: |
struct mg_resolve_async_opts {
const char *nameserver_url;
int max_retries; /* defaults to 2 if zero */
int timeout; /* in seconds; defaults to 5 if zero */
int accept_literal; /* pseudo-resolve literal ipv4 and ipv6 addrs */
int only_literal; /* only resolves literal addrs; sync cb invocation */
struct mg_connection **dns_conn; /* return DNS connection */
};
---
Options for `mg_resolve_async_opt`.
---
title: "URI"
symbol_kind: "intro"
decl_name: "uri.h"
items:
- { name: mg_parse_uri.md }
---
---
title: "mg_parse_uri()"
decl_name: "mg_parse_uri"
symbol_kind: "func"
signature: |
int mg_parse_uri(struct mg_str uri, struct mg_str *scheme,
struct mg_str *user_info, struct mg_str *host,
unsigned int *port, struct mg_str *path, struct mg_str *query,
struct mg_str *fragment);
---
Parses an URI and fills string chunks with locations of the respective
uri components within the input uri string. NULL pointers will be
ignored.
General syntax:
[scheme://[user_info@]]host[:port][/path][?query][#fragment]
Example:
foo.com:80
tcp://foo.com:1234
http://foo.com:80/bar?baz=1
https://user:pw@foo.com:443/blah
`path` will include the leading slash. `query` won't include the leading `?`.
`host` can contain embedded colons if surrounded by square brackets in order
to support IPv6 literal addresses.
Returns 0 on success, -1 on error.
---
title: "Utilities"
title: "Utility API"
symbol_kind: "intro"
decl_name: "util.h"
items:
- { type: file, name: mg_skip.md }
- { type: file, name: mg_ncasecmp.md }
- { type: file, name: mg_casecmp.md }
- { type: file, name: mg_base64_decode.md }
- { type: file, name: mg_base64_encode.md }
- { type: file, name: mg_stat.md }
- { type: file, name: mg_fopen.md }
- { type: file, name: mg_open.md }
- { type: file, name: mg_start_thread.md }
- { type: file, name: mg_conn_addr_to_str.md }
- { type: file, name: mg_sock_to_str.md }
- { type: file, name: mg_sock_addr_to_str.md }
- { type: file, name: mg_hexdump.md }
- { type: file, name: mg_hexdump_connection.md }
- { type: file, name: mg_avprintf.md }
- { type: file, name: mg_is_big_endian.md }
- { type: file, name: mg_next_comma_list_entry.md }
- { type: file, name: mg_match_prefix.md }
- { name: mg_skip.md }
- { name: mg_ncasecmp.md }
- { name: mg_casecmp.md }
- { name: mg_base64_decode.md }
- { name: mg_base64_encode.md }
- { name: mg_stat.md }
- { name: mg_fopen.md }
- { name: mg_open.md }
- { name: mg_start_thread.md }
- { name: mg_conn_addr_to_str.md }
- { name: mg_sock_to_str.md }
- { name: mg_sock_addr_to_str.md }
- { name: mg_hexdump.md }
- { name: mg_hexdump_connection.md }
- { name: mg_avprintf.md }
- { name: mg_is_big_endian.md }
- { name: mg_next_comma_list_entry.md }
- { name: mg_match_prefix.md }
---
......
---
title: CoAP client example
---
TBD
---
title: CoAP
items:
- { name: server_example.md }
- { name: client_example.md }
- { name: ../c-api/coap.h/ }
---
---
title: CoAP server example
---
TBD
---
title: Misc API
items:
- { name: ../c-api/net.h }
- { name: ../c-api/util.h }
- { name: ../c-api/uri.h }
- { name: ../c-api/mbuf.h }
---
---
title: DNS client example
---
TBD
---
title: DNS
items:
- { name: server_example.md }
- { name: client_example.md }
- { name: ../c-api/dns.h/ }
- { name: ../c-api/dns_server.h/ }
---
---
title: DNS server example
---
TBD
---
title: Async DNS resolver
items:
- { name: overview.md }
- { name: ../c-api/resolv.h/ }
---
---
title: Overview
---
TBD
---
title: CGI
---
[CGI](https://en.wikipedia.org/wiki/Common_Gateway_Interface)
is a simple mechanism to generate dynamic content.
In order to use CGI, call `mg_serve_http()` function and use
`.cgi` file extension for the CGI files. To be more precise,
all files that match `cgi_file_pattern` setting in the
`struct mg_serve_http_opts` are treated as CGI.
If `cgi_file_pattern` is NULL, `**.cgi$|**.php$` is used.
If Mongoose recognises a file as CGI, it executes it, and sends the output
back to the client. Therefore,
CGI file must be executable. Mongoose honours the shebang line - see
http://en.wikipedia.org/wiki/Shebang_(Unix).
For example, if both PHP and Perl CGIs are used, then
``#!/path/to/php-cgi.exe` and ``#!/path/to/perl.exe` must be the first lines
of the respective CGI scripts.
It is possible to hardcode the path to the CGI interpreter for all
CGI scripts and disregard the shebang line. To do that, set the
`cgi_interpreter` setting in the `struct mg_serve_http_opts`.
NOTE: PHP scripts must use `php-cgi.exe` as CGI interpreter, not `php.exe`.
Example:
```c
opts.cgi_interpreter = "C:\\ruby\\ruby.exe";
```
---
title: HTTP client example
---
To create an HTTP client, follow this pattern:
1. Create an outbound connection by calling `mg_connect_http()`
2. Create an event handler function that handles `MG_EV_HTTP_REPLY` event
Here's an example of the simplest HTTP client.
Error checking is omitted for the sake of clarity:
```c
#include "mongoose.h"
static const char *url = "http://www.google.com";
static int exit_flag = 0;
static void ev_handler(struct mg_connection *c, int ev, void *p) {
if (ev == MG_EV_HTTP_REPLY) {
c->flags |= MG_F_CLOSE_IMMEDIATELY;
fwrite(hm->message.p, 1, hm->message.len, stdout);
putchar('\n');
exit_flag = 1;
}
}
int main(void) {
struct mg_mgr mgr;
mg_mgr_init(&mgr, NULL);
mg_connect_http(mgr, ev_handler, url, NULL, NULL);
while (exit_flag == 0) {
mg_mgr_poll(&mgr, 1000);
}
mg_mgr_free(&mgr);
return 0;
}
```
See full source code at [HTTP client example](https://github.com/cesanta/dev/tree/master/mongoose/examples/http_client).
---
title: Digest Authentication
---
TBD
---
title: HTTP events
---
As discussed in the overview, `mg_set_protocol_http_websocket()` function
parses incoming data, treats it as HTTP or WebSocket, and triggers high-level
HTTP or WebSocket events. Here is a list of events specific to HTTP.
- MG_EV_HTTP_REQUEST: An HTTP request has arrived. Parsed request
is passed as
`struct http_message` through the handler's `void *ev_data` pointer.
- MG_EV_HTTP_REPLY: An HTTP reply has arrived. Parsed reply is
passed as `struct http_message` through the handler's `void *ev_data`
pointer.
- MG_EV_HTTP_MULTIPART_REQUEST: A multipart POST request has arrived.
This event is sent before body is parsed. After this, the user
should expect a sequence of MG_EV_HTTP_PART_BEGIN/DATA/END requests.
This is also the last time when headers and other request fields are
accessible.
- MG_EV_HTTP_CHUNK: An HTTP chunked-encoding chunk has arrived.
The parsed HTTP reply is passed as `struct http_message` through the
handler's `void *ev_data` pointer. `http_message::body` would contain
incomplete, reassembled HTTP body.
It will grow with every new chunk that arrives, and it can
potentially consume a lot of memory. The event handler may process
the body as chunks are coming, and signal Mongoose to delete processed
body by setting `MG_F_DELETE_CHUNK` in `mg_connection::flags`. When
the last zero chunk is received,
Mongoose sends `MG_EV_HTTP_REPLY` event with
full reassembled body (if handler did not signal to delete chunks) or
with empty body (if handler did signal to delete chunks).
- MG_EV_HTTP_PART_BEGIN: a new part of multipart message is started,
extra parameters are passed in mg_http_multipart_part
- MG_EV_HTTP_PART_DATA: a new portion of data from the multiparted message
no additional headers are available, only data and data size
- MG_EV_HTTP_PART_END: a final boundary received, analogue to maybe used to
find the end of packet
Note: Mongoose should be compiled with MG_ENABLE_HTTP_STREAMING_MULTIPART
to enable multipart events.
---
title: Serving files
---
API function `mg_serve_http()` makes it easy to serve files from a filesystem.
Generally speaking, that function is an implementation of the HTTP server
that serves static files, CGI and SSI. It's behavior is driven by a list
of options that are consolidated into the `struct mg_serve_http_opts`
structure. See [struct mg_serve_http_opts](#) definition for the full list
of capabilities of `mg_serve_http()`.
For example, in order to create a web server that serves static files
from the current directory, implement event handler function as follows:
```c
static void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_HTTP_REQUEST) {
struct mg_serve_http_opts opts;
memset(&opts, 0, sizeof(opts); // Reset all options to defaults
opts.document_root = "."; // Serve files from the current directory
mg_serve_http(c, (struct http_message *) ev_data, s_http_server_opts);
}
}
```
See working example at [simplest web server](https://github.com/cesanta/mongoose/tree/master/examples/simplest_web_server).
Sometimes there is no need to implement a full static web server, for example
if one works on a RESTful server. If certain endpoints must return the contents
of a static file, a simpler `mg_http_serve_file()` function can be used:
```c
static void ev_handler(struct mg_connection *c, 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(c, hm, "file.txt",
mg_mk_str("text/plain"), mg_mk_str(""));
break;
}
...
}
}
```
---
title: HTTP
items:
- { name: server_example.md }
- { name: client_example.md }
- { name: events.md }
- { name: files.md }
- { name: cgi.md }
- { name: ssi.md }
- { name: upload.md }
- { name: ssl.md }
- { name: digest_auth.md }
- { name: ../c-api/http.h/ }
- { name: ../c-api/http_server.h/ }
- { name: ../c-api/http_client.h/ }
---
---
title: HTTP server example
---
To create an HTTP server, follow this pattern:
1. Create a listening connection by calling `mg_bind()` or `mg_bind_opt()`
2. Call `mg_set_protocol_http_websocket()` for that listening connection.
That attaches a built-in HTTP event handler which parses incoming
data and triggers HTTP-specific events. For example, when an HTTP request
is fully buffered, a built-in HTTP handler parses the request and
calls user-defined event handler with `MG_EV_HTTP_REQUEST` event and
parsed HTTP request as an event data.
3. Create event handler function. Note that event handler receives all
events - low level TCP events like `MG_EV_RECV` and high-level HTTP
events like `MG_EV_HTTP_REQUEST`. Normally, an event handler function
should only handle `MG_EV_HTTP_REQUEST` event.
Here's an example of the simplest HTTP server. Error checking is omitted for
the sake of clarity:
```c
#include "mongoose.h"
static const char *s_http_port = "8000";
static void ev_handler(struct mg_connection *c, int ev, void *p) {
if (ev == MG_EV_HTTP_REQUEST) {
struct http_message *hm = (struct http_message *) p;
// We have received an HTTP request. Parsed request is contained in `hm`.
// Send HTTP reply to the client which shows full original request.
mg_send_head(c, 200, hm.message.len, "Content-Type: text/plain");
mg_printf(c, "%.*s", hm.message.len, hm.message.p);
}
}
int main(void) {
struct mg_mgr mgr;
struct mg_connection *c;
mg_mgr_init(&mgr, NULL);
c = mg_bind(&mgr, s_http_port, ev_handler);
mg_set_protocol_http_websocket(c);
for (;;) {
mg_mgr_poll(&mgr, 1000);
}
mg_mgr_free(&mgr);
return 0;
}
```
---
title: SSI
---
Server Side Includes (SSI) is a simple interpreted server-side scripting
language which is most commonly used to include the contents of a file
into a web page. It can be useful when it is desirable to include a common
piece of code throughout a website, for example, headers and footers.
In order to use SSI, call `mg_serve_http()` function and use
`.shtml` file extension for the SSI files. To be more precise,
all files that match `ssi_pattern` setting in the
`struct mg_serve_http_opts` are treated as SSI.
If `ssi_pattern` is NULL, `**.shtml$|**.shtm$` is used.
Unknown SSI directives are silently ignored by Mongoose. Currently,
the following SSI directives are supported:
- `<!--#include FILE_TO_INCLUDE -->` - inject the content of some other file
- `<!--#exec "COMMAND_TO_EXECUTE" -->` - runs a command and inject the output
- `<!--#call COMMAND -->` - triggers `MG_EV_SSI_CALL` event
Note that `<!--#include ... -->` directive supports three path specifications:
- `<!--#include virtual="path" -->` Path is relative to web server root
- `<!--#include abspath="path" -->` Path is absolute or relative to the
web server working dir
- `<!--#include file="path" -->`, `<!--#include "path" -->`
Path is relative to current document
The include directive may be used to include the contents of a file or
the result of running a CGI script.
The exec directive is used to execute a command on a server,
and show command's output. Example: `<!--#exec "ls -l" -->`
The call directive is a way to invoke a C handler from the HTML page.
On each occurence of `<!--#call PARAMS -->` directive,
Mongoose calls a registered event handler with `MG_EV_SSI_CALL` event.
Event parameter will point to the `PARAMS` string.
An event handler can output any text, for example by calling
`mg_printf()`. This is a flexible way of generating a web page on
server side by calling a C event handler. Example:
`<!--#call foo --> <!--#call bar -->`
In the event handler:
```c
case MG_EV_SSI_CALL: {
const char *param = (const char *) ev_data;
if (strcmp(param, "foo") == 0) {
mg_printf(c, "hello from foo");
} else if (strcmp(param, "bar") == 0) {
mg_printf(c, "hello from bar");
}
break;
}
```
---
title: Enabling HTTPS
---
To enable SSL on the server side, please follow these steps:
- Obtain SSL certificate file and private key file
- Declare `struct mg_bind_opts`, initialize `ssl_cert` and `ssl_key`
- Use `mg_bind_opt()` to create listening socket
Example:
```c
int main(void) {
struct mg_mgr mgr;
struct mg_connection *c;
struct mg_bind_opts bind_opts;
mg_mgr_init(&mgr, NULL);
memset(&bind_opts, 0, sizeof(bind_opts));
bind_opts.ssl_cert = "server.pem";
bind_opts.ssl_key = "key.pem";
// Use bind_opts to specify SSL certificate & key file
c = mg_bind_opt(&mgr, "443", ev_handler, bind_opts);
mg_set_protocol_http_websocket(c);
...
}
```
For the full example, please see the [Simplest HTTPS server example](https://github.com/cesanta/dev/tree/master/mongoose/examples/simplest_web_server_ssl).
---
title: Handling file uploads
---
In order to handle file uploads, use the following HTML snippet:
```HTML
&lt;form method="POST" action="/upload" enctype="multipart/form-data"&gt;
&lt;input type="file" name="file"&gt;
&lt;input type="submit" value="Upload"&gt;
&lt;/form&gt;
```
Uploaded files will be sent to the `/upload` endpoint via the `POST` request.
HTTP body will contain multipart-encoded buffer with the file contents.
To save the uploaded file, use this code snippet:
```c
struct mg_str cb(struct mg_connection *c, struct mg_str file_name) {
// Return the same filename. Do not actually do this except in test!
// fname is user-controlled and needs to be sanitized.
return file_name;
}
void ev_handler(struct mg_connection *c, int ev, void *ev_data) {
switch (ev) {
...
case MG_EV_HTTP_PART_BEGIN:
case MG_EV_HTTP_PART_DATA:
case MG_EV_HTTP_PART_END:
mg_file_upload_handler(c, ev, ev_data, cb);
break;
}
}
```
......@@ -3,9 +3,11 @@ title: Mongoose - a networking library
color: '#1D6482'
repo: https://github.com/cesanta/mongoose
items:
- { type: file, name: overview.md }
- { type: dir, name: usage-example }
- { type: dir, name: design-concept }
- { type: dir, name: build-options }
- { type: flat, name: c-api }
- { name: overview }
- { name: http }
- { name: mqtt }
- { name: dns }
- { name: coap }
- { name: dns_resolver }
- { name: core }
---
---
title: MQTT client example
---
TBD
---
title: MQTT
items:
- { name: server_example.md }
- { name: client_example.md }
- { name: ../c-api/mqtt.h/ }
- { name: ../c-api/mqtt_server.h/ }
---
---
title: MQTT server example
---
TBD
---
title: Design Concept
items:
- { type: file, name: memory-buffers.md }
- { type: file, name: event-handler.md }
- { type: file, name: events.md }
- { type: file, name: conn-flags.md }
---
Mongoose is a multi-protocol networking library that implements non-blocking,
asyncronous IO and provides event-based APIs. It has three basic data
structures:
Mongoose has three basic data structures:
- `struct mg_mgr` is an event manager that holds all active connections
- `struct mg_connection` describes a connection
......@@ -22,8 +15,33 @@ listening connection. Each connection is described by the `struct mg_connection`
structure, which has a number of fields like socket, event handler function,
send/receive buffer, flags, etc.
Mongoose's usage pattern is to declare and initialise event manager, create
connections and create an event loop by calling `mg_mgr_poll()` in a loop.
An application that uses mongoose should follow a standard pattern of
event-driven application:
1. declare and initialise event manager:
```c
struct mg_mgr mgr;
mg_mgr_init(&mgr, NULL);
```
2. Create connections. For example, a server application should create
listening connections:
```c
struct mg_connection *c = mg_bind(&mgr, "80", ev_handler_function);
mg_set_protocol_http_websocket(c);
```
3. create an event loop by calling `mg_mgr_poll()` in a loop:
```c
for (;;) {
mg_mgr_poll(&mgr, 1000);
}
```
`mg_mgr_poll()` iterates over all sockets, accepts new connections, sends and
receives data, closes connections and calls event handler functions for the
respective events.
respective events. For the full example, see
[Usage Example](#/overview/usage-example.md/)
which implements TCP echo server.
---
title: Overview
items:
# - { name: usage-example.md }
- { name: concept.md }
- { name: mbufs.md }
- { name: event-handler.md }
- { name: events.md }
- { name: conn-flags.md }
- { name: build-options }
- { name: usage-example.md }
---
Mongoose is a swiss army knife for embedded network programming.
Mongoose is a networking library written in C.
It is a swiss army knife for embedded network programming.
It implements event-driven non-blocking APIs for TCP, UDP, HTTP,
WebSocket, CoAP, MQTT for client and server mode.
Features include:
- Cross-platform: works on Linux/UNIX, MacOS, QNX, eCos, Windows, Android,
iPhone, FreeRTOS (TI CC3200, ESP8266) and more
- Single-threaded, asynchronous, non-blocking core with simple event-based API
iPhone, FreeRTOS
- Native support for [PicoTCP embedded TCP/IP stack](http://www.picotcp.com),
[LWIP embedded TCP/IP stack](https://en.wikipedia.org/wiki/LwIP)
- Works on a variety of embedded boards: TI CC3200, TI MSP430, STM32, ESP8266;
on all Linux-based boards like Raspberry PI, BeagleBone, etc
- Single-threaded, asynchronous, non-blocking core with simple event-based API
- Built-in protocols:
- plain TCP, plain UDP, SSL/TLS (over TCP, one-way or two-way)
- plain TCP, plain UDP, SSL/TLS (one-way or two-way), client and server
- HTTP client and server
- WebSocket client and server
- MQTT client and server
......
---
title: Usage Example
title: Example - TCP echo server
---
- Copy `mongoose.c` and `mongoose.h` to your build tree
......
......@@ -8148,7 +8148,7 @@ void mg_mqtt_disconnect(struct mg_connection *nc) {
#endif /* MG_DISABLE_MQTT */
#ifdef MG_MODULE_LINES
#line 1 "./src/mqtt-broker.c"
#line 1 "./src/mqtt_server.c"
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
......@@ -8693,7 +8693,7 @@ void mg_set_protocol_dns(struct mg_connection *nc) {
#endif /* MG_DISABLE_DNS */
#ifdef MG_MODULE_LINES
#line 1 "./src/dns-server.c"
#line 1 "./src/dns_server.c"
#endif
/*
* Copyright (c) 2014 Cesanta Software Limited
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment