summaryrefslogtreecommitdiffstats
path: root/aclk/https_client.c
diff options
context:
space:
mode:
authorTimotej S <6674623+underhood@users.noreply.github.com>2021-04-19 17:52:40 +0200
committerGitHub <noreply@github.com>2021-04-19 17:52:40 +0200
commita3c46ef3ec305bb2fa0e8f64e87e9ac8b99d6714 (patch)
treeceb5f17a21f61461bcb848f798076069fbbc408f /aclk/https_client.c
parentf569beac51534fb0fe5ca0e33d2b63dbdc2d5427 (diff)
implements ACLK env endpoint (#10833)
implements /env endpoint call and parsing of the response
Diffstat (limited to 'aclk/https_client.c')
-rw-r--r--aclk/https_client.c100
1 files changed, 100 insertions, 0 deletions
diff --git a/aclk/https_client.c b/aclk/https_client.c
index abe46c392c..907f512ba4 100644
--- a/aclk/https_client.c
+++ b/aclk/https_client.c
@@ -550,3 +550,103 @@ void https_req_response_init(https_req_response_t *res) {
res->payload = NULL;
res->payload_size = 0;
}
+
+static inline char *min_non_null(char *a, char *b) {
+ if (!a)
+ return b;
+ if (!b)
+ return a;
+ return (a < b ? a : b);
+}
+
+#define URI_PROTO_SEPARATOR "://"
+#define URL_PARSER_LOG_PREFIX "url_parser "
+
+static int parse_host_port(url_t *url) {
+ char *ptr = strrchr(url->host, ':');
+ if (ptr) {
+ size_t port_len = strlen(ptr + 1);
+ if (!port_len) {
+ error(URL_PARSER_LOG_PREFIX ": specified but no port number");
+ return 1;
+ }
+ if (port_len > 5 /* MAX port lenght is 5digit long in decimal */) {
+ error(URL_PARSER_LOG_PREFIX "port # is too long");
+ return 1;
+ }
+ *ptr = 0;
+ if (!strlen(url->host)) {
+ error(URL_PARSER_LOG_PREFIX "host empty after removing port");
+ return 1;
+ }
+ url->port = atoi (ptr + 1);
+ }
+ return 0;
+}
+
+static inline void port_by_proto(url_t *url) {
+ if (url->port)
+ return;
+ if (!url->proto)
+ return;
+ if (!strcmp(url->proto, "http")) {
+ url->port = 80;
+ return;
+ }
+ if (!strcmp(url->proto, "https")) {
+ url->port = 443;
+ return;
+ }
+}
+
+#define STRDUPZ_2PTR(dest, start, end) \
+ { \
+ dest = mallocz(1 + end - start); \
+ memcpy(dest, start, end - start); \
+ dest[end - start] = 0; \
+ }
+
+int url_parse(const char *url, url_t *parsed) {
+ const char *start = url;
+ const char *end = strstr(url, URI_PROTO_SEPARATOR);
+
+ if (end) {
+ if (end == start) {
+ error (URL_PARSER_LOG_PREFIX "found " URI_PROTO_SEPARATOR " without protocol specified");
+ return 1;
+ }
+
+ STRDUPZ_2PTR(parsed->proto, start, end)
+ start = end + strlen(URI_PROTO_SEPARATOR);
+ }
+
+ end = strchr(start, '/');
+ if (!end)
+ end = start + strlen(start);
+
+ if (start == end) {
+ error(URL_PARSER_LOG_PREFIX "Host empty");
+ return 1;
+ }
+
+ STRDUPZ_2PTR(parsed->host, start, end);
+
+ if (parse_host_port(parsed))
+ return 1;
+
+ if (!*end) {
+ parsed->path = strdupz("/");
+ port_by_proto(parsed);
+ return 0;
+ }
+
+ parsed->path = strdupz(end);
+ port_by_proto(parsed);
+ return 0;
+}
+
+void url_t_destroy(url_t *url) {
+ freez(url->host);
+ freez(url->path);
+ freez(url->proto);
+}