Statistics
| Branch: | Tag: | Revision:

mongoose / examples / reverse_proxy / reverse_proxy.c @ eaef5bd1

History | View | Annotate | Download (3.72 KB)

1
/*
2
 * Copyright (c) 2014 Cesanta Software Limited
3
 * All rights reserved
4
 */
5

    
6
/*
7
 * This example shows how mongoose can be used as a reverse
8
 * proxy for another http server.
9
 *
10
 * A common setup is to have a frontend web server that delegates
11
 * some urls to a backend web server.
12
 *
13
 * In this example we create two webservers. The frontend listens on port
14
 * 8000 and servers a static file and forwards any call matching the /api prefix
15
 * to the backend.
16
 *
17
 * The backend listens on port 8001 and replies a simple JSON object which
18
 * shows the request URI that the backend http server receives.
19
 *
20
 * Things to try out:
21
 *
22
 * curl http://localhost:8000/
23
 * curl http://localhost:8000/api
24
 * curl http://localhost:8000/api/foo
25
 * curl http://localhost:8001/foo
26
 *
27
 * The reverse proxy functionality is enabled via the url rewrite functionality:
28
 *
29
 * ```
30
 *   s_frontend_server_opts.url_rewrites =
31
 *     "/api=http://localhost:8001,/=frontend/hello.html";
32
 * ```
33
 *
34
 * This example maps the /api to a remote http server, and / to a
35
 * specific file on the filesystem.
36
 *
37
 * Obviously you can use any http server as the backend, we spawn
38
 * another web server from the same process in order to make the example easy
39
 * to run.
40
 */
41

    
42
#include "../../mongoose.h"
43

    
44
static const char *s_frontend_port = "8000";
45
static struct mg_serve_http_opts s_frontend_server_opts;
46

    
47
static const char *s_backend_port = "8001";
48
static struct mg_serve_http_opts s_backend_server_opts;
49

    
50
static void frontend_handler(struct mg_connection *nc, int ev, void *ev_data) {
51
  struct http_message *hm = (struct http_message *) ev_data;
52
  switch (ev) {
53
    case MG_EV_HTTP_REQUEST:
54
      mg_serve_http(nc, hm, s_frontend_server_opts); /* Serve static content */
55
      break;
56
    default:
57
      break;
58
  }
59
}
60

    
61
static void backend_handler(struct mg_connection *nc, int ev, void *ev_data) {
62
  struct http_message *hm = (struct http_message *) ev_data;
63
  int i;
64

    
65
  switch (ev) {
66
    case MG_EV_HTTP_REQUEST:
67
      mg_send_response_line(nc, 200,
68
                            "Content-Type: text/html\r\n"
69
                            "Connection: close\r\n");
70
      mg_printf(nc,
71
                "{\"uri\": \"%.*s\", \"method\": \"%.*s\", \"body\": \"%.*s\", "
72
                "\"headers\": {",
73
                (int) hm->uri.len, hm->uri.p, (int) hm->method.len,
74
                hm->method.p, (int) hm->body.len, hm->body.p);
75

    
76
      for (i = 0; i < MG_MAX_HTTP_HEADERS && hm->header_names[i].len > 0; i++) {
77
        struct mg_str hn = hm->header_names[i];
78
        struct mg_str hv = hm->header_values[i];
79
        mg_printf(nc, "%s\"%.*s\": \"%.*s\"", (i != 0 ? "," : ""), (int) hn.len,
80
                  hn.p, (int) hv.len, hv.p);
81
      }
82

    
83
      mg_printf(nc, "}}");
84

    
85
      nc->flags |= MG_F_SEND_AND_CLOSE;
86
      break;
87
    default:
88
      break;
89
  }
90
}
91

    
92
int main(int argc, char *argv[]) {
93
  struct mg_mgr mgr;
94
  struct mg_connection *nc;
95
  int i;
96

    
97
  /* Open listening socket */
98
  mg_mgr_init(&mgr, NULL);
99

    
100
  /* configure frontend web server */
101
  nc = mg_bind(&mgr, s_frontend_port, frontend_handler);
102
  mg_set_protocol_http_websocket(nc);
103

    
104
  s_frontend_server_opts.document_root = "frontend";
105
  s_frontend_server_opts.url_rewrites =
106
      "/api=http://localhost:8001,/=frontend/hello.html";
107

    
108
  /* configure backend web server */
109
  nc = mg_bind(&mgr, s_backend_port, backend_handler);
110
  mg_set_protocol_http_websocket(nc);
111

    
112
  s_backend_server_opts.document_root = "backend";
113

    
114
  /* Parse command line arguments */
115
  for (i = 1; i < argc; i++) {
116
    if (strcmp(argv[i], "-D") == 0) {
117
      mgr.hexdump_file = argv[++i];
118
    } else if (strcmp(argv[i], "-r") == 0) {
119
      s_frontend_server_opts.document_root = argv[++i];
120
    }
121
  }
122

    
123
  printf("Starting web server on port %s\n", s_frontend_port);
124
  for (;;) {
125
    mg_mgr_poll(&mgr, 1000);
126
  }
127
}