Embed.md 7.87 KB
Newer Older
1 2 3 4
# Mongoose Embedding Guide

Embedding Mongoose is done in two steps:

Sergey Lyubka's avatar
Sergey Lyubka committed
5
   1. Copy
6 7
    [mongoose.c](https://raw.github.com/cesanta/mongoose/master/mongoose.c) and
    [mongoose.h](https://raw.github.com/cesanta/mongoose/master/mongoose.h)
Sergey Lyubka's avatar
Sergey Lyubka committed
8
    to your application's source tree and include them in the build.
9 10 11 12 13 14 15
   2. Somewhere in the application code, call `mg_create_server()` to create
    a server, configure it with `mg_set_option()` and loop with
    `mg_poll_server()` until done. Call `mg_destroy_server()` to cleanup.

Here's a minimal application `app.c` that embeds mongoose:

    #include "mongoose.h"
Sergey Lyubka's avatar
Sergey Lyubka committed
16

17
    int main(void) {
18
      struct mg_server *server = mg_create_server(NULL, NULL);
Sergey Lyubka's avatar
Sergey Lyubka committed
19
      mg_set_option(server, "document_root", ".");      // Serve current directory
Sergey Lyubka's avatar
Sergey Lyubka committed
20
      mg_set_option(server, "listening_port", "8080");  // Open port 8080
Sergey Lyubka's avatar
Sergey Lyubka committed
21 22 23 24

      for (;;) {
        mg_poll_server(server, 1000);   // Infinite loop, Ctrl-C to stop
      }
25
      mg_destroy_server(&server);
Sergey Lyubka's avatar
Sergey Lyubka committed
26

27 28 29
      return 0;
    }

Sergey Lyubka's avatar
Sergey Lyubka committed
30
To compile it, put `mongoose.c`, `mongoose.h` and `app.c` into one
Sergey Lyubka's avatar
Sergey Lyubka committed
31 32
folder, start terminal on UNIX or Visual Studio command line prompt on Windows,
and run the following command:
33

Sergey Lyubka's avatar
Sergey Lyubka committed
34 35
    cc app.c mongoose.c -pthread -o app     # on Unix
    cl.exe app.c mongoose.c /TC /MD         # on Windows
36 37 38 39

When run, this simple application opens port 8080 and serves static files,
CGI files and lists directory content in the current working directory.

Sergey Lyubka's avatar
Sergey Lyubka committed
40 41
It is possible to generate HTML page content. Mongoose can call user-defined
function when certain events occur.
Sergey Lyubka's avatar
Sergey Lyubka committed
42 43 44 45 46 47 48 49 50 51 52
That function is called _an event handler_, and it is the second parameter
to `mg_create_server()` function. Here is the example event handler function:

    int event_handler(struct mg_connection *conn, enum mg_event ev) {
      switch (ev) {
        case MG_AUTH: return MG_TRUE;
        default: return MG_FALSE;
      }
    }

Event handler is called by Mongoose with `struct mg_connection *`
Sergey Lyubka's avatar
Sergey Lyubka committed
53
pointer and an event number. `struct mg_connection *conn` 
54
has all information about the request: HTTP headers, POST or websocket
Sergey Lyubka's avatar
Sergey Lyubka committed
55 56 57 58 59
data buffer, etcetera. `enum mg_event ev` tells which exactly event is sent.
For each event, an event handler returns a value which tells Mongoose how
to behave.

The sequence of events for every connection is this:
Sergey Lyubka's avatar
Sergey Lyubka committed
60

Sergey Lyubka's avatar
Sergey Lyubka committed
61 62 63 64 65
   * `MG_AUTH` - Mongoose asks whether this connection is authorized. If event
      handler returns `MG_FALSE`, then Mongoose does not serve the request but
      sends authorization request to the client. If `MG_TRUE` is returned,
      then Mongoose continues on with the request.
   * `MG_REQUEST` - Mongoose asks event handler to serve the request. If
Sergey Lyubka's avatar
Sergey Lyubka committed
66 67
      event handler serves the request by sending a reply,
      it should return `MG_TRUE`. Otherwise,
Sergey Lyubka's avatar
Sergey Lyubka committed
68 69 70 71 72 73 74
      it should return `MG_FALSE` which tells Mongoose that request is not
      served and Mongoose should serve it. For example, event handler might
      choose to serve only RESTful API requests with URIs that start with
      certain prefix, and let Mongoose serve all static files.
      If event handler decides to serve the request, but doesn't have
      all the data at the moment, it should return `MG_MORE`. That tells
      Mongoose to send `MG_POLL` events on each iteration of `mg_poll_server()`
Sergey Lyubka's avatar
Sergey Lyubka committed
75 76 77 78

      `mg_connection::connection_param` pointer is a placeholder to keep
      user-specific data. For example, handler could decide to open a DB
      connection and store DB connection handle in `connection_param`.
Sergey Lyubka's avatar
Sergey Lyubka committed
79 80
   * `MG_POLL` is sent only to those connections which returned `MG_MORE`.
      Event handler should try to complete the reply. If reply is completed,
Sergey Lyubka's avatar
Sergey Lyubka committed
81 82 83
      then event handler should return `MG_TRUE`. Otherwise, it should
      return `MG_FALSE`, and polling will continue until
      handler returns `MG_TRUE`.
Sergey Lyubka's avatar
Sergey Lyubka committed
84
   * `MG_CLOSE` is sent when the connection is closed. This event is used
Sergey Lyubka's avatar
Sergey Lyubka committed
85
      to cleanup per-connection state stored in `connection_param`
Sergey Lyubka's avatar
Sergey Lyubka committed
86
      if it was allocated.
87 88 89 90 91 92 93 94 95

Let's extend our minimal application example and
create an URI that will be served by user's C code. The app will handle
`/hello` URI by showing a hello message. So, when app is run,
http://127.0.0.1:8080/hello will say hello, and here's the code:

    #include <string.h>
    #include "mongoose.h"

96 97 98
    static int event_handler(struct mg_connection *conn, enum mg_event ev) {
      if (ev == MG_AUTH) {
        return MG_TRUE;   // Authorize all requests
Sergey Lyubka's avatar
Sergey Lyubka committed
99
      } else if (ev == MG_REQUEST && !strcmp(conn->uri, "/hello")) {
100 101 102 103 104
        mg_printf_data(conn, "%s", "Hello world");
        return MG_TRUE;   // Mark as processed
      } else {
        return MG_FALSE;  // Rest of the events are not processed
      }
105 106 107
    }

    int main(void) {
108
      struct mg_server *server = mg_create_server(NULL, event_handler);
109 110
      mg_set_option(server, "document_root", ".");
      mg_set_option(server, "listening_port", "8080");
111 112 113 114

      for (;;) {
        mg_poll_server(server, 1000);  // Infinite loop, Ctrl-C to stop
      }
115
      mg_destroy_server(&server);
116

117 118 119
      return 0;
    }

Sergey Lyubka's avatar
Sergey Lyubka committed
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
## Example code

Mongoose source code contains a well-commented example code, listed below:

   * [hello.c](https://github.com/cesanta/mongoose/blob/master/examples/hello.c)
   a minimalistic hello world example
   * [post.c](https://github.com/cesanta/mongoose/blob/master/examples/post.c)
   shows how to handle form input
   * [upload.c](https://github.com/cesanta/mongoose/blob/master/examples/post.c)
   shows how to upload files
   * [websocket.c](https://github.com/cesanta/mongoose/blob/master/examples/websocket.c) demonstrates websocket usage
   * [auth.c](https://github.com/cesanta/mongoose/blob/master/examples/websocket.c) demonstrates API-controlled Digest authorization
   * [mjpg.c](https://github.com/cesanta/mongoose/blob/master/examples/mjpg.c) demonstrates MJPEG streaming implementation

## Compilation flags

136 137 138 139
Below is the list of compilation flags that enable or disable certain
features. By default, some features are enabled, and could be disabled
by setting appropriate `NO_*` flag. Features that are disabled by default
could be enabled by setting appropriate `USE_*` flag. Bare bones Mongoose
Sergey Lyubka's avatar
Sergey Lyubka committed
140 141
is quite small, about 30 kilobytes of compiled x86 code. Each feature adds
a couple of kilobytes to the executable size, and also has some runtime penalty.
142

Sergey Lyubka's avatar
Sergey Lyubka committed
143 144 145 146 147 148
Note that some flags start with `NS_` prefix. This is because Mongoose uses
[Net Skeleton](http://github.com/cesanta/net_skeleton) as a low-level
networking engine. If user code has `#include <net_skeleton.h>`, then
all Net Skeleton functions will be available too.


149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
    -DMONGOOSE_NO_AUTH          Disable MD5 authorization support
    -DMONGOOSE_NO_CGI           Disable CGI support
    -DMONGOOSE_NO_DAV           Disable WebDAV support
                                (PUT, DELETE, MKCOL, PROPFIND methods)
    -DMONGOOSE_NO_DIRECTORY_LISTING  Disable directory listing
    -DMONGOOSE_NO_FILESYSTEM    Disables all file IO, serving from memory only
    -DMONGOOSE_NO_LOGGING       Disable access/error logging
    -DMONGOOSE_NO_THREADS
    -DMONGOOSE_NO_WEBSOCKET     Disable WebSocket support

    -DMONGOOSE_USE_IDLE_TIMEOUT_SECONDS=X Idle connection timeout, default is 30
    -DMONGOOSE_USE_LUA          Enable Lua scripting
    -DMONGOOSE_USE_LUA_SQLITE3  Enable sqlite3 binding for Lua
    -DMONGOOSE_USE_POST_SIZE_LIMIT=X      POST requests larger than X will be
                                          rejected, not set by default
    -DMONGOOSE_USE_EXTRA_HTTP_HEADERS=X   Append X to the HTTP headers
                                          for static files, empty by default
Sergey Lyubka's avatar
Sergey Lyubka committed
166 167 168 169 170 171 172 173

    -DNS_ENABLE_DEBUG         Enables debug messages on stdout, very noisy
    -DNS_ENABLE_SSL           Enable SSL
    -DNS_ENABLE_IPV6          Enable IPv6 support
    -DNS_ENABLE_HEXDUMP       Enables hexdump of sent and received traffic
    -DNS_STACK_SIZE=X         Sets stack size to X for  ns_start_thread()
    -DNS_DISABLE_THREADS      Disable threads support
    -DNS_DISABLE_SOCKETPAIR   For systems without loopback interface