瀏覽代碼

REST example: show pattern matching

bel2125 3 年之前
父節點
當前提交
f9fd77f592
共有 1 個文件被更改,包括 80 次插入26 次删除
  1. 80 26
      examples/rest/rest.c

+ 80 - 26
examples/rest/rest.c

@@ -10,6 +10,7 @@
 #include <unistd.h>
 #include <unistd.h>
 #endif
 #endif
 
 
+#include <stdarg.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
 #include <time.h>
 #include <time.h>
@@ -20,7 +21,7 @@
 #define PORT "8089"
 #define PORT "8089"
 #define HOST_INFO "http://localhost:8089"
 #define HOST_INFO "http://localhost:8089"
 
 
-#define EXAMPLE_URI "/example"
+#define EXAMPLE_URI "/res/*/*"
 #define EXIT_URI "/exit"
 #define EXIT_URI "/exit"
 
 
 int exitNow = 0;
 int exitNow = 0;
@@ -32,12 +33,16 @@ SendJSON(struct mg_connection *conn, cJSON *json_obj)
 	char *json_str = cJSON_PrintUnformatted(json_obj);
 	char *json_str = cJSON_PrintUnformatted(json_obj);
 	size_t json_str_len = strlen(json_str);
 	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 header (+1 for \n) */
+	mg_send_http_ok(conn, "application/json; charset=utf-8", json_str_len + 1);
 
 
 	/* Send HTTP message content */
 	/* Send HTTP message content */
 	mg_write(conn, json_str, json_str_len);
 	mg_write(conn, json_str, json_str_len);
 
 
+	/* Add a newline. This is not required, but the result is more
+	 * human-readable in a debuger. */
+	mg_write(conn, "\n", 1);
+
 	/* Free string allocated by cJSON_Print* */
 	/* Free string allocated by cJSON_Print* */
 	cJSON_free(json_str);
 	cJSON_free(json_str);
 
 
@@ -49,7 +54,7 @@ static unsigned request = 0; /* demo data: request counter */
 
 
 
 
 static int
 static int
-ExampleGET(struct mg_connection *conn)
+ExampleGET(struct mg_connection *conn, const char *p1, const char *p2)
 {
 {
 	cJSON *obj = cJSON_CreateObject();
 	cJSON *obj = cJSON_CreateObject();
 
 
@@ -59,7 +64,10 @@ ExampleGET(struct mg_connection *conn)
 		return 500;
 		return 500;
 	}
 	}
 
 
+	printf("GET %s/%s\n", p1, p2);
 	cJSON_AddStringToObject(obj, "version", CIVETWEB_VERSION);
 	cJSON_AddStringToObject(obj, "version", CIVETWEB_VERSION);
+	cJSON_AddStringToObject(obj, "path1", p1);
+	cJSON_AddStringToObject(obj, "path2", p2);
 	cJSON_AddNumberToObject(obj, "request", ++request);
 	cJSON_AddNumberToObject(obj, "request", ++request);
 	SendJSON(conn, obj);
 	SendJSON(conn, obj);
 	cJSON_Delete(obj);
 	cJSON_Delete(obj);
@@ -69,9 +77,9 @@ ExampleGET(struct mg_connection *conn)
 
 
 
 
 static int
 static int
-ExampleDELETE(struct mg_connection *conn)
+ExampleDELETE(struct mg_connection *conn, const char *p1, const char *p2)
 {
 {
-	request = 0;
+	printf("DELETE %s/%s\n", p1, p2);
 	mg_send_http_error(conn,
 	mg_send_http_error(conn,
 	                   204,
 	                   204,
 	                   "%s",
 	                   "%s",
@@ -82,13 +90,14 @@ ExampleDELETE(struct mg_connection *conn)
 
 
 
 
 static int
 static int
-ExamplePUT(struct mg_connection *conn)
+ExamplePUT(struct mg_connection *conn, const char *p1, const char *p2)
 {
 {
 	char buffer[1024];
 	char buffer[1024];
 	int dlen = mg_read(conn, buffer, sizeof(buffer) - 1);
 	int dlen = mg_read(conn, buffer, sizeof(buffer) - 1);
 	cJSON *obj, *elem;
 	cJSON *obj, *elem;
 	unsigned newvalue;
 	unsigned newvalue;
 
 
+	printf("PUT %s/%s\n", p1, p2);
 	if ((dlen < 1) || (dlen >= sizeof(buffer))) {
 	if ((dlen < 1) || (dlen >= sizeof(buffer))) {
 		mg_send_http_error(conn, 400, "%s", "No request body data");
 		mg_send_http_error(conn, 400, "%s", "No request body data");
 		return 400;
 		return 400;
@@ -133,23 +142,79 @@ ExamplePUT(struct mg_connection *conn)
 
 
 
 
 static int
 static int
-ExampleHandler(struct mg_connection *conn, void *cbdata)
+mg_vsplit(const char *url, const char *pattern, va_list va)
 {
 {
+	int ret = 0;
+	while (*url && *pattern) {
+		if (*url == *pattern) {
+			url++;
+			pattern++;
+		} else if (*pattern == '*') {
+			char *p = va_arg(va, char *);
+			size_t l = va_arg(va, size_t);
+			if (p == NULL || l == 0) {
+				return 0;
+			}
+			while ((*url != '/') && (*url != 0)) {
+				if (l == 0) {
+					return 0;
+				}
+				l--;
+				*p = *url;
+				p++;
+				url++;
+			}
+			*p = 0;
+			pattern++;
+			ret++;
+		} else {
+			return 0;
+		}
+	}
+	return ret;
+}
+
 
 
+static int
+mg_split(const char *url, const char *pattern, ...)
+{
+	int ret;
+	va_list va;
+	va_start(va, pattern);
+	ret = mg_vsplit(url, pattern, va);
+	va_end(va);
+	return ret;
+}
+
+
+static int
+ExampleHandler(struct mg_connection *conn, void *cbdata)
+{
+	char path1[1024], path2[1024];
 	const struct mg_request_info *ri = mg_get_request_info(conn);
 	const struct mg_request_info *ri = mg_get_request_info(conn);
+	const char *url = ri->local_uri;
 	(void)cbdata; /* currently unused */
 	(void)cbdata; /* currently unused */
 
 
+	/* Pattern matching */
+	if (2
+	    != mg_split(
+	           url, EXAMPLE_URI, path1, sizeof(path1), path2, sizeof(path2))) {
+		mg_send_http_error(conn, 404, "Invalid path: %s\n", url);
+		return 404;
+	}
+
+	/* According to method */
 	if (0 == strcmp(ri->request_method, "GET")) {
 	if (0 == strcmp(ri->request_method, "GET")) {
-		return ExampleGET(conn);
+		return ExampleGET(conn, path1, path2);
 	}
 	}
 	if ((0 == strcmp(ri->request_method, "PUT"))
 	if ((0 == strcmp(ri->request_method, "PUT"))
 	    || (0 == strcmp(ri->request_method, "POST"))
 	    || (0 == strcmp(ri->request_method, "POST"))
 	    || (0 == strcmp(ri->request_method, "PATCH"))) {
 	    || (0 == strcmp(ri->request_method, "PATCH"))) {
 		/* In this example, do the same for PUT, POST and PATCH */
 		/* In this example, do the same for PUT, POST and PATCH */
-		return ExamplePUT(conn);
+		return ExamplePUT(conn, path1, path2);
 	}
 	}
 	if (0 == strcmp(ri->request_method, "DELETE")) {
 	if (0 == strcmp(ri->request_method, "DELETE")) {
-		return ExampleDELETE(conn);
+		return ExampleDELETE(conn, path1, path2);
 	}
 	}
 
 
 	/* this is not a GET request */
 	/* this is not a GET request */
@@ -159,7 +224,7 @@ ExampleHandler(struct mg_connection *conn, void *cbdata)
 }
 }
 
 
 
 
-int
+static int
 ExitHandler(struct mg_connection *conn, void *cbdata)
 ExitHandler(struct mg_connection *conn, void *cbdata)
 {
 {
 	mg_printf(conn,
 	mg_printf(conn,
@@ -172,7 +237,7 @@ ExitHandler(struct mg_connection *conn, void *cbdata)
 }
 }
 
 
 
 
-int
+static int
 log_message(const struct mg_connection *conn, const char *message)
 log_message(const struct mg_connection *conn, const char *message)
 {
 {
 	puts(message);
 	puts(message);
@@ -189,23 +254,13 @@ main(int argc, char *argv[])
 	                         "10000",
 	                         "10000",
 	                         "error_log_file",
 	                         "error_log_file",
 	                         "error.log",
 	                         "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};
 	                         0};
 
 
 	struct mg_callbacks callbacks;
 	struct mg_callbacks callbacks;
 	struct mg_context *ctx;
 	struct mg_context *ctx;
 	int err = 0;
 	int err = 0;
 
 
-	/* Check if libcivetweb has been built with all required features. */
+	/* Init libcivetweb. */
 	mg_init_library(0);
 	mg_init_library(0);
 
 
 	/* Callback will print error messages to console */
 	/* Callback will print error messages to console */
@@ -225,11 +280,10 @@ main(int argc, char *argv[])
 	mg_set_request_handler(ctx, EXAMPLE_URI, ExampleHandler, 0);
 	mg_set_request_handler(ctx, EXAMPLE_URI, ExampleHandler, 0);
 	mg_set_request_handler(ctx, EXIT_URI, ExitHandler, 0);
 	mg_set_request_handler(ctx, EXIT_URI, ExitHandler, 0);
 
 
-	/* Show sone info */
+	/* Show some info */
 	printf("Start example: %s%s\n", HOST_INFO, EXAMPLE_URI);
 	printf("Start example: %s%s\n", HOST_INFO, EXAMPLE_URI);
 	printf("Exit example:  %s%s\n", HOST_INFO, EXIT_URI);
 	printf("Exit example:  %s%s\n", HOST_INFO, EXIT_URI);
 
 
-
 	/* Wait until the server should be closed */
 	/* Wait until the server should be closed */
 	while (!exitNow) {
 	while (!exitNow) {
 #ifdef _WIN32
 #ifdef _WIN32