| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 | /* * Copyright (c) 2018 the CivetWeb developers * MIT License *//* Simple demo of a REST callback. */#ifdef _WIN32#include <windows.h>#else#include <unistd.h>#endif#include <stdlib.h>#include <string.h>#include <time.h>#include "cJSON.h"#include "civetweb.h"#ifdef NO_SSL#define PORT "8089"#define HOST_INFO "http://localhost:8089"#else#define PORT "8089r,8843s"#define HOST_INFO "https://localhost:8843"#endif#define EXAMPLE_URI "/example"#define EXIT_URI "/exit"int exitNow = 0;static intSendJSON(struct mg_connection *conn, cJSON *json_obj){	char *json_str = cJSON_PrintUnformatted(json_obj);	size_t json_str_len = strlen(json_str);	/* Send HTTP message header */	mg_send_http_ok(conn, "application/json; charset=utf-8", json_str_len);	/* Send HTTP message content */	mg_write(conn, json_str, json_str_len);	/* Free string allocated by cJSON_Print* */	cJSON_free(json_str);	return (int)json_str_len;}static unsigned request = 0; /* demo data: request counter */static intExampleGET(struct mg_connection *conn){	cJSON *obj = cJSON_CreateObject();	if (!obj) {		/* insufficient memory? */		mg_send_http_error(conn, 500, "Server error");		return 500;	}	cJSON_AddStringToObject(obj, "version", CIVETWEB_VERSION);	cJSON_AddNumberToObject(obj, "request", ++request);	SendJSON(conn, obj);	cJSON_Delete(obj);	return 200;}static intExampleDELETE(struct mg_connection *conn){	request = 0;	mg_send_http_error(conn,	                   204,	                   "%s",	                   ""); /* Return "deleted" = "204 No Content" */	return 204;}static intExamplePUT(struct mg_connection *conn){	char buffer[1024];	int dlen = mg_read(conn, buffer, sizeof(buffer) - 1);	cJSON *obj, *elem;	unsigned newvalue;	if ((dlen < 1) || (dlen >= sizeof(buffer))) {		mg_send_http_error(conn, 400, "%s", "No request body data");		return 400;	}	buffer[dlen] = 0;	obj = cJSON_Parse(buffer);	if (obj == NULL) {		mg_send_http_error(conn, 400, "%s", "Invalid request body data");		return 400;	}	elem = cJSON_GetObjectItemCaseSensitive(obj, "request");	if (!cJSON_IsNumber(elem)) {		cJSON_Delete(obj);		mg_send_http_error(conn,		                   400,		                   "%s",		                   "No \"request\" number in body data");		return 400;	}	newvalue = (unsigned)elem->valuedouble;	if ((double)newvalue != elem->valuedouble) {		cJSON_Delete(obj);		mg_send_http_error(conn,		                   400,		                   "%s",		                   "Invalid \"request\" number in body data");		return 400;	}	request = newvalue;	cJSON_Delete(obj);	mg_send_http_error(conn, 201, "%s", ""); /* Return "201 Created" */	return 201;}static intExamplePOST(struct mg_connection *conn){	/* In this example, do the same for PUT and POST */	return ExamplePUT(conn);}static intExamplePATCH(struct mg_connection *conn){	/* In this example, do the same for PUT and PATCH */	return ExamplePUT(conn);}static intExampleHandler(struct mg_connection *conn, void *cbdata){	const struct mg_request_info *ri = mg_get_request_info(conn);	(void)cbdata; /* currently unused */	if (0 == strcmp(ri->request_method, "GET")) {		return ExampleGET(conn);	}	if (0 == strcmp(ri->request_method, "PUT")) {		return ExamplePUT(conn);	}	if (0 == strcmp(ri->request_method, "POST")) {		return ExamplePOST(conn);	}	if (0 == strcmp(ri->request_method, "DELETE")) {		return ExampleDELETE(conn);	}	if (0 == strcmp(ri->request_method, "PATCH")) {		return ExamplePATCH(conn);	}	/* this is not a GET request */	mg_send_http_error(	    conn, 405, "Only GET, PUT, POST, DELETE and PATCH method supported");	return 405;}intExitHandler(struct mg_connection *conn, void *cbdata){	mg_printf(conn,	          "HTTP/1.1 200 OK\r\nContent-Type: "	          "text/plain\r\nConnection: close\r\n\r\n");	mg_printf(conn, "Server will shut down.\n");	mg_printf(conn, "Bye!\n");	exitNow = 1;	return 1;}intlog_message(const struct mg_connection *conn, const char *message){	puts(message);	return 1;}intmain(int argc, char *argv[]){	const char *options[] = {"listening_ports",	                         PORT,	                         "request_timeout_ms",	                         "10000",	                         "error_log_file",	                         "error.log",#ifndef NO_SSL	                         "ssl_certificate",	                         "../../resources/cert/server.pem",	                         "ssl_protocol_version",	                         "3",	                         "ssl_cipher_list",	                         "DES-CBC3-SHA:AES128-SHA:AES128-GCM-SHA256",#endif	                         "enable_auth_domain_check",	                         "no",	                         0};	struct mg_callbacks callbacks;	struct mg_context *ctx;	int err = 0;/* Check if libcivetweb has been built with all required features. */#ifndef NO_SSL	if (!mg_check_feature(2)) {		fprintf(stderr,		        "Error: Embedded example built with SSL support, "		        "but civetweb library build without.\n");		err = 1;	}	mg_init_library(MG_FEATURES_SSL);#else	mg_init_library(0);#endif	if (err) {		fprintf(stderr, "Cannot start CivetWeb - inconsistent build.\n");		return EXIT_FAILURE;	}	/* Callback will print error messages to console */	memset(&callbacks, 0, sizeof(callbacks));	callbacks.log_message = log_message;	/* Start CivetWeb web server */	ctx = mg_start(&callbacks, 0, options);	/* Check return value: */	if (ctx == NULL) {		fprintf(stderr, "Cannot start CivetWeb - mg_start failed.\n");		return EXIT_FAILURE;	}	/* Add handler EXAMPLE_URI, to explain the example */	mg_set_request_handler(ctx, EXAMPLE_URI, ExampleHandler, 0);	mg_set_request_handler(ctx, EXIT_URI, ExitHandler, 0);	/* Show sone info */	printf("Start example: %s%s\n", HOST_INFO, EXAMPLE_URI);	printf("Exit example:  %s%s\n", HOST_INFO, EXIT_URI);	/* Wait until the server should be closed */	while (!exitNow) {#ifdef _WIN32		Sleep(1000);#else		sleep(1);#endif	}	/* Stop the server */	mg_stop(ctx);	printf("Server stopped.\n");	printf("Bye!\n");	return EXIT_SUCCESS;}
 |