/* Copyright (c) 2013-2017 the Civetweb developers * Copyright (c) 2013 No Face Press, LLC * License http://opensource.org/licenses/mit-license.php MIT License */ // Simple example program on how to use Embedded C++ interface. #include "CivetServer.h" #include #ifdef _WIN32 #include #else #include #endif #define DOCUMENT_ROOT "." #define PORT "8081" #define EXAMPLE_URI "/example" #define EXIT_URI "/exit" bool exitNow = false; class ExampleHandler : public CivetHandler { public: bool handleGet(CivetServer *server, struct mg_connection *conn) { mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: " "text/html\r\nConnection: close\r\n\r\n"); mg_printf(conn, "\r\n"); mg_printf(conn, "

This is an example text from a C++ handler

\r\n"); mg_printf(conn, "

To see a page from the A handler click here

\r\n"); mg_printf(conn, "

To see a page from the A handler with a parameter " "click here

\r\n"); mg_printf(conn, "

To see a page from the A/B handler click here

\r\n"); mg_printf(conn, "

To see a page from the *.foo handler click here

\r\n"); mg_printf(conn, "

To see a page from the WebSocket handler click here

\r\n"); mg_printf(conn, "

To exit click here

\r\n", EXIT_URI); mg_printf(conn, "\r\n"); return true; } }; class ExitHandler : public CivetHandler { public: bool handleGet(CivetServer *server, struct mg_connection *conn) { mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: " "text/plain\r\nConnection: close\r\n\r\n"); mg_printf(conn, "Bye!\n"); exitNow = true; return true; } }; class AHandler : public CivetHandler { private: bool handleAll(const char *method, CivetServer *server, struct mg_connection *conn) { std::string s = ""; mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: " "text/html\r\nConnection: close\r\n\r\n"); mg_printf(conn, ""); mg_printf(conn, "

This is the A handler for \"%s\" !

", method); if (CivetServer::getParam(conn, "param", s)) { mg_printf(conn, "

param set to %s

", s.c_str()); } else { mg_printf(conn, "

param not set

"); } mg_printf(conn, "\n"); return true; } public: bool handleGet(CivetServer *server, struct mg_connection *conn) { return handleAll("GET", server, conn); } bool handlePost(CivetServer *server, struct mg_connection *conn) { return handleAll("POST", server, conn); } }; class ABHandler : public CivetHandler { public: bool handleGet(CivetServer *server, struct mg_connection *conn) { mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: " "text/html\r\nConnection: close\r\n\r\n"); mg_printf(conn, ""); mg_printf(conn, "

This is the AB handler!!!

"); mg_printf(conn, "\n"); return true; } }; class FooHandler : public CivetHandler { public: bool handleGet(CivetServer *server, struct mg_connection *conn) { /* Handler may access the request info using mg_get_request_info */ const struct mg_request_info *req_info = mg_get_request_info(conn); mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: " "text/html\r\nConnection: close\r\n\r\n"); mg_printf(conn, "\n"); mg_printf(conn, "

This is the Foo GET handler!!!

\n"); mg_printf(conn, "

The request was:

%s %s HTTP/%s

\n", req_info->request_method, req_info->request_uri, req_info->http_version); mg_printf(conn, "\n"); return true; } bool handlePost(CivetServer *server, struct mg_connection *conn) { /* Handler may access the request info using mg_get_request_info */ const struct mg_request_info *req_info = mg_get_request_info(conn); long long rlen, wlen; long long nlen = 0; long long tlen = req_info->content_length; char buf[1024]; mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: " "text/html\r\nConnection: close\r\n\r\n"); mg_printf(conn, "\n"); mg_printf(conn, "

This is the Foo POST handler!!!

\n"); mg_printf(conn, "

The request was:

%s %s HTTP/%s

\n", req_info->request_method, req_info->request_uri, req_info->http_version); mg_printf(conn, "

Content Length: %li

\n", (long)tlen); mg_printf(conn, "
\n");

		while (nlen < tlen) {
			rlen = tlen - nlen;
			if (rlen > sizeof(buf)) {
				rlen = sizeof(buf);
			}
			rlen = mg_read(conn, buf, (size_t)rlen);
			if (rlen <= 0) {
				break;
			}
			wlen = mg_write(conn, buf, (size_t)rlen);
			if (wlen != rlen) {
				break;
			}
			nlen += wlen;
		}

		mg_printf(conn, "\n
\n"); mg_printf(conn, "\n"); return true; } #define fopen_recursive fopen bool handlePut(CivetServer *server, struct mg_connection *conn) { /* Handler may access the request info using mg_get_request_info */ const struct mg_request_info *req_info = mg_get_request_info(conn); long long rlen, wlen; long long nlen = 0; long long tlen = req_info->content_length; FILE * f; char buf[1024]; int fail = 0; #ifdef _WIN32 _snprintf(buf, sizeof(buf), "D:\\somewhere\\%s\\%s", req_info->remote_user, req_info->local_uri); buf[sizeof(buf)-1] = 0; if (strlen(buf)>255) { /* Windows will not work with path > 260 (MAX_PATH), unless we use * the unicode API. However, this is just an example code: A real * code will probably never store anything to D:\\somewhere and * must be adapted to the specific needs anyhow. */ fail = 1; f = NULL; } else { f = fopen_recursive(buf, "wb"); } #else snprintf(buf, sizeof(buf), "~/somewhere/%s/%s", req_info->remote_user, req_info->local_uri); buf[sizeof(buf)-1] = 0; if (strlen(buf)>1020) { /* The string is too long and probably truncated. Make sure an * UTF-8 string is never truncated between the UTF-8 code bytes. * This example code must be adapted to the specific needs. */ fail = 1; f = NULL; } else { f = fopen_recursive(buf, "w"); } #endif if (!f) { fail = 1; } else { while (nlen < tlen) { rlen = tlen - nlen; if (rlen > sizeof(buf)) { rlen = sizeof(buf); } rlen = mg_read(conn, buf, (size_t)rlen); if (rlen <= 0) { fail = 1; break; } wlen = fwrite(buf, 1, (size_t)rlen, f); if (wlen != rlen) { fail = 1; break; } nlen += wlen; } fclose(f); } if (fail) { mg_printf(conn, "HTTP/1.1 409 Conflict\r\n" "Content-Type: text/plain\r\n" "Connection: close\r\n\r\n"); } else { mg_printf(conn, "HTTP/1.1 201 Created\r\n" "Content-Type: text/plain\r\n" "Connection: close\r\n\r\n"); } return true; } }; class WsStartHandler : public CivetHandler { public: bool handleGet(CivetServer *server, struct mg_connection *conn) { mg_printf(conn, "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: " "close\r\n\r\n"); mg_printf(conn, "\n"); mg_printf(conn, "\n\n"); mg_printf(conn, "\n"); mg_printf(conn, "Embedded websocket example\n"); #ifdef USE_WEBSOCKET /* mg_printf(conn, "\n"); ... xhtml style */ mg_printf(conn, "\n"); mg_printf(conn, "\n\n"); mg_printf( conn, "
No websocket connection yet
\n"); #else mg_printf(conn, "\n\n"); mg_printf(conn, "Example not compiled with USE_WEBSOCKET\n"); #endif mg_printf(conn, "\n\n"); return 1; } }; #ifdef USE_WEBSOCKET class WebSocketHandler : public CivetWebSocketHandler { virtual bool handleConnection(CivetServer *server, const struct mg_connection *conn) { printf("WS connected\n"); return true; } virtual void handleReadyState(CivetServer *server, struct mg_connection *conn) { printf("WS ready\n"); const char *text = "Hello from the websocket ready handler"; mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, text, strlen(text)); } virtual bool handleData(CivetServer *server, struct mg_connection *conn, int bits, char *data, size_t data_len) { printf("WS got %lu bytes: ", (long unsigned)data_len); fwrite(data, 1, data_len, stdout); printf("\n"); mg_websocket_write(conn, WEBSOCKET_OPCODE_TEXT, data, data_len); return (data_len<4); } virtual void handleClose(CivetServer *server, const struct mg_connection *conn) { printf("WS closed\n"); } }; #endif int main(int argc, char *argv[]) { const char *options[] = { "document_root", DOCUMENT_ROOT, "listening_ports", PORT, 0}; std::vector cpp_options; for (int i=0; i<(sizeof(options)/sizeof(options[0])-1); i++) { cpp_options.push_back(options[i]); } // CivetServer server(options); // <-- C style start CivetServer server(cpp_options); // <-- C++ style start ExampleHandler h_ex; server.addHandler(EXAMPLE_URI, h_ex); ExitHandler h_exit; server.addHandler(EXIT_URI, h_exit); AHandler h_a; server.addHandler("/a", h_a); ABHandler h_ab; server.addHandler("/a/b", h_ab); WsStartHandler h_ws; server.addHandler("/ws", h_ws); #ifdef NO_FILES /* This handler will handle "everything else", including * requests to files. If this handler is installed, * NO_FILES should be set. */ FooHandler h_foo; server.addHandler("", h_foo); printf("See a page from the \"all\" handler at http://localhost:%s/\n", PORT); #else FooHandler h_foo; server.addHandler("**.foo", h_foo); printf("Browse files at http://localhost:%s/\n", PORT); #endif #ifdef USE_WEBSOCKET WebSocketHandler h_websocket; server.addWebSocketHandler("/websocket", h_websocket); printf("Run websocket example at http://localhost:%s/ws\n", PORT); #endif printf("Run example at http://localhost:%s%s\n", PORT, EXAMPLE_URI); printf("Exit at http://localhost:%s%s\n", PORT, EXIT_URI); while (!exitNow) { #ifdef _WIN32 Sleep(1000); #else sleep(1); #endif } printf("Bye!\n"); return 0; }