Jelajahi Sumber

Add example POST handler

bel 8 tahun lalu
induk
melakukan
47929c3f75
4 mengubah file dengan 225 tambahan dan 1 penghapusan
  1. 29 0
      docs/api/mg_get_request_link.md
  2. 101 0
      examples/embedded_c/embedded_c.c
  3. 14 1
      include/civetweb.h
  4. 81 0
      src/civetweb.c

+ 29 - 0
docs/api/mg_get_request_link.md

@@ -0,0 +1,29 @@
+# Civetweb API Reference
+
+### `mg_get_request_link( conn, buf, buflen );`
+
+### Parameters
+
+| Parameter | Type | Description |
+| :--- | :--- | :--- |
+|**`conn`**|`struct mg_connection *`| A pointer referencing the connection |
+|**`buf`**|`char *`| A buffer to store the link |
+|**`buflen`**|`size_t`| Size of the buffer |
+
+### Return Value
+
+| Type | Description |
+| :--- | :--- |
+|`int`| Return code: <0 for error, >=0 for success |
+
+### Description
+
+Store a formatted link corresponding to the current request.
+
+E.g., returns
+`http://mydomain.com:8080/path/to/callback.ext`
+or 
+`http://127.0.0.1:8080/path/to/callback.ext`
+depending on the auth check settings.
+
+### See Also

+ 101 - 0
examples/embedded_c/embedded_c.c

@@ -77,6 +77,9 @@ ExampleHandler(struct mg_connection *conn, void *cbdata)
 	          "<p>To see a page from the CookieHandler handler <a "
 	          "<p>To see a page from the CookieHandler handler <a "
 	          "href=\"cookie\">click cookie</a></p>");
 	          "href=\"cookie\">click cookie</a></p>");
 	mg_printf(conn,
 	mg_printf(conn,
+	          "<p>To see a page from the PostResponser handler <a "
+	          "href=\"postresponse\">click post response</a></p>");
+	mg_printf(conn,
 	          "<p>To see an example for parsing files on the fly <a "
 	          "<p>To see an example for parsing files on the fly <a "
 	          "href=\"on_the_fly_form\">click form</a> (form for "
 	          "href=\"on_the_fly_form\">click form</a> (form for "
 	          "uploading files)</p>");
 	          "uploading files)</p>");
@@ -459,6 +462,99 @@ CookieHandler(struct mg_connection *conn, void *cbdata)
 }
 }
 
 
 
 
+static int
+send_chunk(struct mg_connection *conn,
+           const char *chunk,
+           unsigned int chunk_len)
+{
+	char lenbuf[16];
+	size_t lenbuf_len;
+	int ret;
+	int t;
+
+	/* First store the length information in a text buffer. */
+	sprintf(lenbuf, "%x\r\n", chunk_len);
+	lenbuf_len = strlen(lenbuf);
+
+	/* Then send length information, chunk and terminating \r\n. */
+	ret = mg_write(conn, lenbuf, lenbuf_len);
+	if (ret != (int)lenbuf_len) {
+		return -1;
+	}
+	t = ret;
+
+	ret = mg_write(conn, chunk, chunk_len);
+	if (ret != (int)chunk_len) {
+		return -1;
+	}
+	t += ret;
+
+	ret = mg_write(conn, "\r\n", 2);
+	if (ret != 2) {
+		return -1;
+	}
+	t += ret;
+
+	return t;
+}
+
+
+int
+PostResponser(struct mg_connection *conn, void *cbdata)
+{
+	long long r_total = 0;
+	int r, s;
+
+	char buf[2048];
+
+	const struct mg_request_info *ri = mg_get_request_info(conn);
+
+	if (strcmp(ri->request_method, "POST")) {
+		char buf[1024];
+		int ret = mg_get_request_link(conn, buf, sizeof(buf));
+
+		mg_printf(conn,
+		          "HTTP/1.1 405 Method Not Allowed\r\nConnection: close\r\n");
+		mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
+		mg_printf(conn,
+		          "%s method not allowed in the POST handler\n",
+		          ri->request_method);
+		if (ret >= 0) {
+			mg_printf(conn,
+			          "use a web tool to send a POST request to %s\n",
+			          buf);
+		}
+		return 1;
+	}
+
+	if (ri->content_length >= 0) {
+		/* We know the content length in advance */
+	} else {
+		/* We must read until we find the end (chunked encoding
+		 * or connection close), indicated my mg_read returning 0 */
+	}
+
+	mg_printf(conn,
+	          "HTTP/1.1 200 OK\r\nConnection: "
+	          "close\r\nTransfer-Encoding: chunked\r\n");
+	mg_printf(conn, "Content-Type: text/plain\r\n\r\n");
+
+	r = mg_read(conn, buf, sizeof(buf));
+	while (r > 0) {
+		r_total += r;
+		s = send_chunk(conn, buf, r);
+		if (r != s) {
+			/* Send error */
+			break;
+		}
+		r = mg_read(conn, buf, sizeof(buf));
+	}
+	mg_printf(conn, "0\r\n");
+
+	return 1;
+}
+
+
 int
 int
 WebSocketStartHandler(struct mg_connection *conn, void *cbdata)
 WebSocketStartHandler(struct mg_connection *conn, void *cbdata)
 {
 {
@@ -754,6 +850,8 @@ main(int argc, char *argv[])
 	    "DES-CBC3-SHA:AES128-SHA:AES128-GCM-SHA256",
 	    "DES-CBC3-SHA:AES128-SHA:AES128-GCM-SHA256",
 #endif
 #endif
 #endif
 #endif
+	    "enable_auth_domain_check",
+	    "no",
 	    0};
 	    0};
 	struct mg_callbacks callbacks;
 	struct mg_callbacks callbacks;
 	struct mg_context *ctx;
 	struct mg_context *ctx;
@@ -849,6 +947,9 @@ main(int argc, char *argv[])
 	/* Add handler for /cookie example */
 	/* Add handler for /cookie example */
 	mg_set_request_handler(ctx, "/cookie", CookieHandler, 0);
 	mg_set_request_handler(ctx, "/cookie", CookieHandler, 0);
 
 
+	/* Add handler for /postresponse example */
+	mg_set_request_handler(ctx, "/postresponse", PostResponser, 0);
+
 	/* Add HTTP site to open a websocket connection */
 	/* Add HTTP site to open a websocket connection */
 	mg_set_request_handler(ctx, "/websocket", WebSocketStartHandler, 0);
 	mg_set_request_handler(ctx, "/websocket", WebSocketStartHandler, 0);
 
 

+ 14 - 1
include/civetweb.h

@@ -432,7 +432,7 @@ CIVETWEB_API void mg_set_websocket_handler_with_subprotocols(
 
 
 /* mg_authorization_handler
 /* mg_authorization_handler
 
 
-   Some description here
+   Callback function definition for mg_set_auth_handler
 
 
    Parameters:
    Parameters:
       conn: current connection information.
       conn: current connection information.
@@ -484,6 +484,19 @@ CIVETWEB_API void *
 mg_get_user_connection_data(const struct mg_connection *conn);
 mg_get_user_connection_data(const struct mg_connection *conn);
 
 
 
 
+/* Get a formatted link corresponding to the current request
+
+   Parameters:
+      conn: current connection information.
+      buf: string buffer (out)
+      buflen: length of the string buffer
+   Returns:
+      <0: error
+      >=0: ok */
+CIVETWEB_API int
+mg_get_request_link(const struct mg_connection *conn, char *buf, size_t buflen);
+
+
 #if defined(MG_LEGACY_INTERFACE)
 #if defined(MG_LEGACY_INTERFACE)
 /* Return array of strings that represent valid configuration options.
 /* Return array of strings that represent valid configuration options.
    For each option, option name and default value is returned, i.e. the
    For each option, option name and default value is returned, i.e. the

+ 81 - 0
src/civetweb.c

@@ -2870,6 +2870,87 @@ mg_get_request_info(const struct mg_connection *conn)
 }
 }
 
 
 
 
+int
+mg_get_request_link(const struct mg_connection *conn, char *buf, size_t buflen)
+{
+	if ((buflen < 1) || (buf == 0) || (conn == 0)) {
+		return -1;
+	} else {
+
+		int truncated = 0;
+		const struct mg_request_info *ri = &conn->request_info;
+
+		if (ri->local_uri == NULL) {
+			return -1;
+		}
+
+		if ((ri->request_uri != NULL)
+		    && strcmp(ri->local_uri, ri->request_uri)) {
+			mg_snprintf(conn,
+			            &truncated,
+			            buf,
+			            buflen,
+			            "%s%s://%s",
+			            (is_websocket_protocol(conn) ? "ws" : "http"),
+			            (ri->is_ssl ? "s" : ""),
+			            ri->request_uri);
+			if (truncated) {
+				return -1;
+			}
+			return 0;
+		} else {
+
+#if USE_IPV6
+			int is_ipv6 = (conn->client.lsa.sa.sa_family == AF_INET6);
+			int port = is_ipv6 ? htons(conn->client.lsa.sin6.sin6_port)
+			                   : htons(conn->client.lsa.sin.sin_port);
+#else
+			int port = htons(conn->client.lsa.sin.sin_port);
+#endif
+			int def_port = ri->is_ssl ? 443 : 80;
+			int auth_domain_check_enabled =
+			    conn->ctx->config[ENABLE_AUTH_DOMAIN_CHECK]
+			    && (!strcmp(conn->ctx->config[ENABLE_AUTH_DOMAIN_CHECK],
+			                "yes"));
+			const char *server_domain =
+			    conn->ctx->config[AUTHENTICATION_DOMAIN];
+
+			char portstr[16];
+			char server_ip[48];
+
+			if (port != def_port) {
+				sprintf(portstr, ":%u", (unsigned)port);
+			} else {
+				portstr[0] = 0;
+			}
+
+			if (!auth_domain_check_enabled || !server_domain) {
+
+				sockaddr_to_string(server_ip,
+				                   sizeof(server_ip),
+				                   &conn->client.lsa);
+
+				server_domain = server_ip;
+			}
+
+			mg_snprintf(conn,
+			            &truncated,
+			            buf,
+			            buflen,
+			            "%s%s://%s%s%s",
+			            (is_websocket_protocol(conn) ? "ws" : "http"),
+			            (ri->is_ssl ? "s" : ""),
+			            server_domain,
+			            portstr,
+			            ri->local_uri);
+			if (truncated) {
+				return -1;
+			}
+			return 0;
+		}
+	}
+}
+
 /* Skip the characters until one of the delimiters characters found.
 /* Skip the characters until one of the delimiters characters found.
  * 0-terminate resulting word. Skip the delimiter and following whitespaces.
  * 0-terminate resulting word. Skip the delimiter and following whitespaces.
  * Advance pointer to buffer to the next word. Return found 0-terminated word.
  * Advance pointer to buffer to the next word. Return found 0-terminated word.