]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-http: Adjusted response and request parsers to accept a request/response object...
authorStephan Bosch <stephan@rename-it.nl>
Sun, 15 Sep 2013 00:36:18 +0000 (03:36 +0300)
committerStephan Bosch <stephan@rename-it.nl>
Sun, 15 Sep 2013 00:36:18 +0000 (03:36 +0300)
src/lib-http/http-client-connection.c
src/lib-http/http-request-parser.c
src/lib-http/http-request-parser.h
src/lib-http/http-response-parser.c
src/lib-http/http-response-parser.h
src/lib-http/test-http-response-parser.c
src/lib-http/test-http-server.c

index 8f4ad1707b92348db2e54f885633e80c1cd8413b..d59235d2f48d534af55fd379c6e83b590aaf1554 100644 (file)
@@ -488,7 +488,7 @@ static void http_client_connection_input(struct connection *_conn)
 {
        struct http_client_connection *conn =
                (struct http_client_connection *)_conn;
-       struct http_response *response;
+       struct http_response response;
        struct http_client_request *const *req_idx;
        struct http_client_request *req = NULL;
        int finished = 0, ret;
@@ -547,7 +547,7 @@ static void http_client_connection_input(struct connection *_conn)
                   (Continue) status message.  Unexpected 1xx status responses MAY be
                   ignored by a user agent.
                 */
-               if (req->payload_sync && response->status == 100) {
+               if (req->payload_sync && response.status == 100) {
                        if (conn->payload_continue) {
                                http_client_connection_debug(conn,
                                        "Got 100-continue response after timeout");
@@ -564,16 +564,16 @@ static void http_client_connection_input(struct connection *_conn)
                                        t_strdup_printf("Failed to send request: %s", error));
                        }
                        return;
-               } else if (response->status / 100 == 1) {
+               } else if (response.status / 100 == 1) {
                        /* ignore them for now */
                        http_client_connection_debug(conn,
-                               "Got unexpected %u response; ignoring", response->status);
+                               "Got unexpected %u response; ignoring", response.status);
                        continue;
                } 
 
                http_client_connection_debug(conn,
                        "Got %u response for request %s",
-                       response->status, http_client_request_label(req));
+                       response.status, http_client_request_label(req));
 
                /* remove request from queue */
                array_delete(&conn->request_wait_list, 0, 1);
@@ -581,25 +581,25 @@ static void http_client_connection_input(struct connection *_conn)
                i_assert(req->refcount > 1 || aborted);
                http_client_request_unref(&req);
                
-               conn->close_indicated = response->connection_close;
+               conn->close_indicated = response.connection_close;
                if (req->payload_sync && !conn->payload_continue)
                        conn->output_locked = FALSE;    
 
                if (!aborted) {
-                       if (response->status == 417 && req->payload_sync) {
+                       if (response.status == 417 && req->payload_sync) {
                                /* drop Expect: continue */
                                req->payload_sync = FALSE;
                                conn->output_locked = FALSE;
                                conn->peer->no_payload_sync = TRUE;
-                               http_client_request_retry(req, response->status, response->reason);
+                               http_client_request_retry(req, response.status, response.reason);
        
-                       } else if (response->status / 100 == 3 && response->status != 304 &&
-                               response->location != NULL) {
+                       } else if (response.status / 100 == 3 && response.status != 304 &&
+                               response.location != NULL) {
                                /* redirect */
-                               http_client_request_redirect(req, response->status, response->location);
+                               http_client_request_redirect(req, response.status, response.location);
                        } else {
                                /* response for application */
-                               if (!http_client_connection_return_response(conn, req, response))
+                               if (!http_client_connection_return_response(conn, req, &response))
                                        return;
                        }
 
index 7151edec24f79f57aab1ace11d039d4ea05428ad..0664ee44a438bd221197ab224ae084992604f292 100644 (file)
@@ -23,7 +23,8 @@ struct http_request_parser {
        struct http_message_parser parser;
        enum http_request_parser_state state;
 
-       struct http_request request;
+       const char *request_method;
+       const char *request_target;
 
        unsigned int skipping_line:1;
 };
@@ -49,7 +50,8 @@ static void
 http_request_parser_restart(struct http_request_parser *parser)
 {
        http_message_parser_restart(&parser->parser);
-       memset(&parser->request, 0, sizeof(parser->request));
+       parser->request_method = NULL;
+       parser->request_target = NULL;
 }
 
 static int http_request_parse_method(struct http_request_parser *parser)
@@ -63,7 +65,7 @@ static int http_request_parse_method(struct http_request_parser *parser)
 
        if (p == parser->parser.end)
                return 0;
-       parser->request.method =
+       parser->request_method =
                p_strdup_until(parser->parser.msg_pool, parser->parser.cur, p);
        parser->parser.cur = p;
        return 1;
@@ -82,7 +84,7 @@ static int http_request_parse_target(struct http_request_parser *parser)
 
        if (p == parser->parser.end)
                return 0;
-       parser->request.target =
+       parser->request_target =
                p_strdup_until(parser->parser.msg_pool, parser->parser.cur, p);
        parser->parser.cur = p;
        return 1;
@@ -246,7 +248,7 @@ static int http_request_parse_request_line(struct http_request_parser *parser,
 }
 
 int http_request_parse_next(struct http_request_parser *parser,
-                           struct http_request **request_r,
+                           struct http_request *request,
                            const char **error_r)
 {
        int ret;
@@ -271,13 +273,14 @@ int http_request_parse_next(struct http_request_parser *parser,
                return -1;
        parser->state = HTTP_REQUEST_PARSE_STATE_INIT;
 
-       parser->request.version_major = parser->parser.msg.version_major;
-       parser->request.version_minor = parser->parser.msg.version_minor;
-       parser->request.date = parser->parser.msg.date;
-       parser->request.payload = parser->parser.payload;
-       parser->request.headers = parser->parser.msg.headers;
-       parser->request.connection_close = parser->parser.msg.connection_close;
-
-       *request_r = &parser->request;
+       memset(request, 0, sizeof(*request));
+       request->method = parser->request_method;
+       request->target = parser->request_target;
+       request->version_major = parser->parser.msg.version_major;
+       request->version_minor = parser->parser.msg.version_minor;
+       request->date = parser->parser.msg.date;
+       request->payload = parser->parser.payload;
+       request->headers = parser->parser.msg.headers;
+       request->connection_close = parser->parser.msg.connection_close;
        return 1;
 }
index 7f1cb31bc74fa7ab542227adbaacd54be66b4954..f14f341bec7dff76cd8f4214be02d080fc8d6f15 100644 (file)
@@ -23,7 +23,7 @@ http_request_parser_init(struct istream *input);
 void http_request_parser_deinit(struct http_request_parser **_parser);
 
 int http_request_parse_next(struct http_request_parser *parser,
-                           struct http_request **request_r,
+                           struct http_request *request,
                            const char **error_r);
 
 #endif
index e215b0560bc4d1b51eb43db9e098e702449357d2..f902902a21fbcc0696441fb1efc7828358830dc6 100644 (file)
@@ -24,7 +24,8 @@ struct http_response_parser {
        struct http_message_parser parser;
        enum http_response_parser_state state;
 
-       struct http_response response;
+       unsigned int response_status;
+       const char *response_reason;
 };
 
 struct http_response_parser *http_response_parser_init(struct istream *input)
@@ -48,7 +49,8 @@ static void
 http_response_parser_restart(struct http_response_parser *parser)
 {
        http_message_parser_restart(&parser->parser);
-       memset(&parser->response, 0, sizeof(parser->response));
+       parser->response_status = 0;
+       parser->response_reason = NULL;
 }
 
 static int http_response_parse_status(struct http_response_parser *parser)
@@ -62,7 +64,7 @@ static int http_response_parse_status(struct http_response_parser *parser)
                return 0;
        if (!i_isdigit(p[0]) || !i_isdigit(p[1]) || !i_isdigit(p[2]))
                return -1;
-       parser->response.status =
+       parser->response_status =
                (p[0] - '0')*100 + (p[1] - '0')*10 + (p[2] - '0');
        parser->parser.cur += 3;
        return 1;
@@ -74,12 +76,13 @@ static int http_response_parse_reason(struct http_response_parser *parser)
 
        /* reason-phrase = *( HTAB / SP / VCHAR / obs-text )
         */
+       // FIXME: limit length
        while (p < parser->parser.end && http_char_is_text(*p))
                p++;
 
        if (p == parser->parser.end)
                return 0;
-       parser->response.reason =
+       parser->response_reason =
                p_strdup_until(parser->parser.msg_pool, parser->parser.cur, p);
        parser->parser.cur = p;
        return 1;
@@ -223,7 +226,7 @@ static int http_response_parse_status_line(struct http_response_parser *parser,
 }
 
 int http_response_parse_next(struct http_response_parser *parser,
-                            bool no_payload, struct http_response **response_r,
+                            bool no_payload, struct http_response *response,
                             const char **error_r)
 {
        int ret;
@@ -251,11 +254,11 @@ int http_response_parse_next(struct http_response_parser *parser,
           A server MUST NOT send a Content-Length header field in any response
           with a status code of 1xx (Informational) or 204 (No Content). [...]
         */
-       if ((parser->response.status / 100 == 1 || parser->response.status == 204) &&
+       if ((parser->response_status / 100 == 1 || parser->response_status == 204) &&
            parser->parser.msg.content_length > 0) {
                *error_r = t_strdup_printf(
                        "Unexpected Content-Length header field for %u response "
-                       "(length=%"PRIuUOFF_T")", parser->response.status,
+                       "(length=%"PRIuUOFF_T")", parser->response_status,
                        parser->parser.msg.content_length);
                return -1;
        }
@@ -269,8 +272,8 @@ int http_response_parse_next(struct http_response_parser *parser,
           header fields, regardless of the header fields present in the
           message, and thus cannot contain a message body.
         */
-       if (parser->response.status / 100 == 1 || parser->response.status == 204
-               || parser->response.status == 304) { // HEAD is handled in caller
+       if (parser->response_status / 100 == 1 || parser->response_status == 204
+               || parser->response_status == 304) { // HEAD is handled in caller
                no_payload = TRUE;
        }
 
@@ -281,14 +284,15 @@ int http_response_parse_next(struct http_response_parser *parser,
        }
        parser->state = HTTP_RESPONSE_PARSE_STATE_INIT;
 
-       parser->response.version_major = parser->parser.msg.version_major;
-       parser->response.version_minor = parser->parser.msg.version_minor;
-       parser->response.location = parser->parser.msg.location;
-       parser->response.date = parser->parser.msg.date;
-       parser->response.payload = parser->parser.payload;
-       parser->response.headers = parser->parser.msg.headers;
-       parser->response.connection_close = parser->parser.msg.connection_close;
-
-       *response_r = &parser->response;
+       memset(response, 0, sizeof(*response));
+       response->status = parser->response_status;
+       response->reason = parser->response_reason;
+       response->version_major = parser->parser.msg.version_major;
+       response->version_minor = parser->parser.msg.version_minor;
+       response->location = parser->parser.msg.location;
+       response->date = parser->parser.msg.date;
+       response->payload = parser->parser.payload;
+       response->headers = parser->parser.msg.headers;
+       response->connection_close = parser->parser.msg.connection_close;
        return 1;
 }
index e25fad053e6f49617182f2c25b9221ca05c925e1..479bb9dfc6b40b21c19d0ab0a122fcd8344c1854 100644 (file)
@@ -10,7 +10,7 @@ http_response_parser_init(struct istream *input);
 void http_response_parser_deinit(struct http_response_parser **_parser);
 
 int http_response_parse_next(struct http_response_parser *parser,
-                            bool no_payload, struct http_response **response_r,
+                            bool no_payload, struct http_response *response,
                             const char **error_r);
 
 #endif
index 2146a59423327a5adc17de7fdd9475e16e60dd0d..faab6fe76bde9a4f88eb990a6839a59f36274a63 100644 (file)
@@ -99,7 +99,7 @@ static void test_http_response_parse_valid(void)
                struct ostream *output;
                const struct http_response_parse_test *test;
                struct http_response_parser *parser;
-               struct http_response *response = NULL;
+               struct http_response response;
                const char *response_text, *payload, *error;
                unsigned int pos, response_text_len;
                int ret = 0;
@@ -119,11 +119,11 @@ static void test_http_response_parse_valid(void)
                }
                test_istream_set_size(input, response_text_len);
                while (ret > 0) {
-                       if (response->payload != NULL) {
+                       if (response.payload != NULL) {
                                buffer_set_used_size(payload_buffer, 0);
                                output = o_stream_create_buffer(payload_buffer);
                                test_out("payload receive", 
-                                       o_stream_send_istream(output, response->payload));
+                                       o_stream_send_istream(output, response.payload));
                                o_stream_destroy(&output);
                                payload = str_c(payload_buffer);
                        } else {
@@ -136,9 +136,8 @@ static void test_http_response_parse_valid(void)
                
                if (ret == 0) {
                        /* verify last response only */
-                       i_assert(response != NULL);
                        test_out(t_strdup_printf("response->status = %d",test->status),
-                                       response->status == test->status);
+                                       response.status == test->status);
                        if (payload == NULL || test->payload == NULL) {
                                test_out(t_strdup_printf("response->payload = %s",
                                        str_sanitize(payload, 80)),
@@ -185,7 +184,7 @@ unsigned int invalid_response_parse_test_count =
 static void test_http_response_parse_invalid(void)
 {
        struct http_response_parser *parser;
-       struct http_response *response;
+       struct http_response response;
        const char *response_text, *error;
        struct istream *input;
        int ret;
index c1ccef775af175cc37373fd16ff8ceb3a90837d4..e692966422ce40192ead13ffc710ef98b5a9c673 100644 (file)
@@ -48,13 +48,14 @@ client_handle_request(struct client *client, struct http_request *request)
 static void client_input(struct connection *conn)
 {
        struct client *client = (struct client *)conn;
-       struct http_request *request;
+       struct http_request request;
        const char *error;
        int ret;
 
-       while ((ret = http_request_parse_next(client->parser, &request, &error)) > 0) {
-               if (client_handle_request(client, request) < 0 ||
-                   request->connection_close) {
+       while ((ret = http_request_parse_next
+               (client->parser, &request, &error)) > 0) {
+               if (client_handle_request(client, &request) < 0 ||
+                   request.connection_close) {
                        client_destroy(conn);
                        return;
                }