// Copyright (c) 2020 Cesanta Software Limited // All rights reserved // // Example HTTP client that uses a proxy server. Usage: // make // ./example PROXY:PORT http://www.ladyada.net // // To enable SSL/TLS, see https://mongoose.ws/tutorials/tls/#how-to-build // #include "mongoose.h" // Print HTTP response and signal that we're done static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) { const char *url = fn_data; static bool connected; if (ev == MG_EV_HTTP_MSG) { struct mg_http_message *hm = (struct mg_http_message *) ev_data; printf("%.*s", (int) hm->message.len, hm->message.ptr); exit(EXIT_SUCCESS); } else if (ev == MG_EV_CONNECT) { // Proxy TCP connection established. Send CONNECT request struct mg_str host = mg_url_host(url); if (mg_url_is_ssl(url)) { struct mg_tls_opts opts = {.ca = mg_unpacked("/certs/ca.pem"), .name = host}; mg_tls_init(c, &opts); } // c->is_hexdumping = 1; mg_printf(c, "CONNECT %.*s:%hu HTTP/1.1\r\nHost: %.*s:%hu\r\n\r\n", (int) host.len, host.ptr, mg_url_port(url), (int) host.len, host.ptr, mg_url_port(url)); } else if (!connected && ev == MG_EV_READ) { struct mg_http_message hm; int n = mg_http_parse((char *) c->recv.buf, c->recv.len, &hm); if (n > 0) { struct mg_str host = mg_url_host(url); // CONNECT response - tunnel is established connected = true; MG_DEBUG( ("Connected to proxy, status: %.*s", (int) hm.uri.len, hm.uri.ptr)); mg_iobuf_del(&c->recv, 0, n); // Send request to the target server mg_printf(c, "GET %s HTTP/1.0\r\n" "Host: %.*s\r\n" "\r\n", mg_url_uri(url), (int) host.len, host.ptr); } } } int main(int argc, char *argv[]) { struct mg_mgr mgr; if (argc != 3) { fprintf(stderr, "Usage: %s PROXY_URL URL\n", argv[0]); return EXIT_FAILURE; } mg_mgr_init(&mgr); // Initialise event manager mg_http_connect(&mgr, argv[1], fn, argv[2]); // Connect to the proxy for (;;) mg_mgr_poll(&mgr, 1000); // Event loop mg_mgr_free(&mgr); return 0; }