From 7b4f90b2919c85fcafa663c96c754eb10c3595b8 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Thu, 21 Aug 2014 15:28:54 +0100 Subject: [PATCH] Add URL parsing utility. --- src/libutil/http.c | 68 ++++++++++++++++++++++++++++++++++++++++------ src/libutil/http.h | 15 ++++++++-- 2 files changed, 72 insertions(+), 11 deletions(-) diff --git a/src/libutil/http.c b/src/libutil/http.c index 7146a33c11..85e3e8540d 100644 --- a/src/libutil/http.c +++ b/src/libutil/http.c @@ -916,18 +916,20 @@ rspamd_http_connection_write_message (struct rspamd_http_connection *conn, } else { /* Format request */ - if (host != NULL) { + if (host == NULL && msg->host == NULL) { + /* Fallback to HTTP/1.0 */ + rspamd_printf_gstring (priv->buf, "%s %v HTTP/1.0\r\n" + "Content-Length: %z\r\n", + http_method_str (msg->method), msg->url, bodylen); + } + else { rspamd_printf_gstring (priv->buf, "%s %v HTTP/1.1\r\n" "Connection: close\r\n" "Host: %s\r\n" "Content-Length: %z\r\n", - http_method_str (msg->method), msg->url, host, bodylen); - } - else { - /* Fallback to HTTP/1.0 */ - rspamd_printf_gstring (priv->buf, "%s %v HTTP/1.0\r\n" - "Content-Length: %z\r\n", - http_method_str (msg->method), msg->url, bodylen); + http_method_str (msg->method), msg->url, + host != NULL ? host : msg->host->str, + bodylen); } } /* Allocate iov */ @@ -993,12 +995,62 @@ rspamd_http_new_message (enum http_parser_type type) new->date = 0; new->body = NULL; new->status = NULL; + new->host = NULL; + new->port = 80; new->type = type; new->method = HTTP_GET; return new; } +struct rspamd_http_message* +rspamd_http_message_from_url (const gchar *url) +{ + struct http_parser_url pu; + struct rspamd_http_message *msg; + const gchar *host, *path; + size_t pathlen; + + if (url == NULL) { + return NULL; + } + + memset (&pu, 0, sizeof (pu)); + if (http_parser_parse_url (url, strlen (url), TRUE, &pu) != 0) { + msg_warn ("cannot parse URL: %s", url); + return NULL; + } + + if ((pu.field_set & (1 << UF_HOST)) == 0) { + msg_warn ("no host argument in URL: %s", url); + return NULL; + } + if ((pu.field_set & (1 << UF_PATH)) == 0) { + path = "/"; + pathlen = 1; + } + else { + path = url + pu.field_data[UF_PATH].off; + pathlen = pu.field_data[UF_PATH].len; + } + + msg = rspamd_http_new_message (HTTP_REQUEST); + host = url + pu.field_data[UF_HOST].off; + + if ((pu.field_set & (1 << UF_PORT)) != 0) { + msg->port = pu.port; + } + else { + /* XXX: magic constant */ + msg->port = 80; + } + + msg->host = g_string_new_len (host, pu.field_data[UF_HOST].len); + g_string_append_len (msg->url, path, pathlen); + + return msg; +} + void rspamd_http_message_free (struct rspamd_http_message *msg) { diff --git a/src/libutil/http.h b/src/libutil/http.h index eefadee18f..c6fcf0b83f 100644 --- a/src/libutil/http.h +++ b/src/libutil/http.h @@ -53,6 +53,8 @@ struct rspamd_http_header { */ struct rspamd_http_message { GString *url; + GString *host; + unsigned port; GString *status; struct rspamd_http_header *headers; GString *body; @@ -211,12 +213,19 @@ rspamd_http_connection_unref (struct rspamd_http_connection *conn) void rspamd_http_connection_reset (struct rspamd_http_connection *conn); /** - * Create new HTTP reply - * @param code code to pass - * @return new reply object + * Create new HTTP message + * @param type request or response + * @return new http message */ struct rspamd_http_message * rspamd_http_new_message (enum http_parser_type type); +/** + * Create HTTP message from URL + * @param url + * @return new message or NULL + */ +struct rspamd_http_message* rspamd_http_message_from_url (const gchar *url); + /** * Append a header to reply * @param rep -- 2.47.3