You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/05/24 14:43:02 UTC
[incubator-nuttx-apps] 03/04: webclient: Implement proxy
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx-apps.git
commit 4798f01449bf3727c62bf35a89109bd4c2254071
Author: YAMAMOTO Takashi <ya...@midokura.com>
AuthorDate: Mon May 23 14:58:34 2022 +0900
webclient: Implement proxy
Only the very basic case (http over http) for now.
---
netutils/webclient/webclient.c | 99 +++++++++++++++++++++++++++++++++++++++---
1 file changed, 94 insertions(+), 5 deletions(-)
diff --git a/netutils/webclient/webclient.c b/netutils/webclient/webclient.c
index 7da3ec258..5ba7d66c0 100644
--- a/netutils/webclient/webclient.c
+++ b/netutils/webclient/webclient.c
@@ -222,6 +222,7 @@ struct wget_s
#endif
struct wget_target_s target;
+ struct wget_target_s proxy;
bool need_conn_close;
struct conn_s conn;
@@ -1118,6 +1119,15 @@ int webclient_perform(FAR struct webclient_context *ctx)
(ctx->flags & WEBCLIENT_FLAG_NON_BLOCKING) != 0));
#endif
+#if defined(CONFIG_WEBCLIENT_NET_LOCAL)
+ if (ctx->unix_socket_path != NULL && ctx->proxy != NULL)
+ {
+ nerr("ERROR: proxy with AF_LOCAL is not implemented");
+ _SET_STATE(ctx, WEBCLIENT_CONTEXT_STATE_DONE);
+ return -ENOTSUP;
+ }
+#endif
+
/* Initialize the state structure */
if (ctx->ws == NULL)
@@ -1145,6 +1155,27 @@ int webclient_perform(FAR struct webclient_context *ctx)
return ret;
}
+ if (ctx->proxy != NULL)
+ {
+ ret = parseurl(ctx->proxy, &ws->proxy);
+ if (ret != 0)
+ {
+ nerr("ERROR: Malformed proxy setting: %s\n", ctx->proxy);
+ free(ws);
+ _SET_STATE(ctx, WEBCLIENT_CONTEXT_STATE_DONE);
+ return ret;
+ }
+
+ if (strcmp(ws->proxy.scheme, "http") ||
+ strcmp(ws->proxy.filename, "/"))
+ {
+ nerr("ERROR: Unsupported proxy setting: %s\n", ctx->proxy);
+ free(ws);
+ _SET_STATE(ctx, WEBCLIENT_CONTEXT_STATE_DONE);
+ return -ENOTSUP;
+ }
+ }
+
ws->state = WEBCLIENT_STATE_SOCKET;
ctx->ws = ws;
}
@@ -1199,6 +1230,14 @@ int webclient_perform(FAR struct webclient_context *ctx)
return -ENOTSUP;
}
#endif
+
+ if (ctx->proxy != NULL)
+ {
+ nerr("ERROR: TLS over proxy is not implemented\n");
+ free(ws);
+ _SET_STATE(ctx, WEBCLIENT_CONTEXT_STATE_DONE);
+ return -ENOTSUP;
+ }
}
else
{
@@ -1307,9 +1346,20 @@ int webclient_perform(FAR struct webclient_context *ctx)
{
/* Get the server address from the host name */
+ FAR struct wget_target_s *target;
+
+ if (ctx->proxy != NULL)
+ {
+ target = &ws->proxy;
+ }
+ else
+ {
+ target = &ws->target;
+ }
+
server_in.sin_family = AF_INET;
- server_in.sin_port = htons(ws->target.port);
- ret = wget_gethostip(ws->target.hostname,
+ server_in.sin_port = htons(target->port);
+ ret = wget_gethostip(target->hostname,
&server_in.sin_addr);
if (ret < 0)
{
@@ -1370,13 +1420,36 @@ int webclient_perform(FAR struct webclient_context *ctx)
dest = append(dest, ep, method);
dest = append(dest, ep, " ");
+ if (ctx->proxy != NULL)
+ {
+ /* Use absolute-form for a proxy
+ *
+ * https://datatracker.ietf.org/doc/html/rfc7230#section-5.3.2
+ */
+
+ char port_str[sizeof("65535")];
+
+ dest = append(dest, ep, ws->target.scheme);
+ dest = append(dest, ep, "://");
+ dest = append(dest, ep, ws->target.hostname);
+ dest = append(dest, ep, ":");
+ snprintf(port_str, sizeof(port_str), "%u", ws->target.port);
+ dest = append(dest, ep, port_str);
+ dest = append(dest, ep, "/");
+ dest = append(dest, ep, ws->target.filename);
+ }
+ else
+ {
+ /* Otherwise, use origin-form */
+
#ifndef WGET_USE_URLENCODE
- dest = append(dest, ep, ws->target.filename);
+ dest = append(dest, ep, ws->target.filename);
#else
- /* TODO: should we use wget_urlencode_strcpy? */
+ /* TODO: should we use wget_urlencode_strcpy? */
- dest = append(dest, ep, ws->target.filename);
+ dest = append(dest, ep, ws->target.filename);
#endif
+ }
dest = append(dest, ep, " ");
if (ctx->protocol_version == WEBCLIENT_PROTOCOL_VERSION_HTTP_1_0)
@@ -1395,6 +1468,22 @@ int webclient_perform(FAR struct webclient_context *ctx)
}
dest = append(dest, ep, g_httpcrnl);
+
+ /* Note about proxy and Host header:
+ *
+ * https://datatracker.ietf.org/doc/html/rfc7230#section-5.4
+ * > A client MUST send a Host header field in an HTTP/1.1
+ * > request even if the request-target is in the absolute-form,
+ * > since this allows the Host information to be forwarded
+ * > through ancient HTTP/1.0 proxies that might not have
+ * > implemented Host.
+ *
+ * > When a proxy receives a request with an absolute-form of
+ * > request-target, the proxy MUST ignore the received Host
+ * > header field (if any) and instead replace it with the host
+ * > information of the request-target.
+ */
+
dest = append(dest, ep, g_httphost);
dest = append(dest, ep, ws->target.hostname);
dest = append(dest, ep, g_httpcrnl);