Add Content-Length to HTTP requests
This commit is contained in:
@@ -3945,6 +3945,22 @@ void http_request_builder_target(HTTP_RequestBuilder builder,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HTTP_String s;
|
||||||
|
|
||||||
|
s = HTTP_STR("Connection: Close\r\n");
|
||||||
|
byte_queue_write(&conn->output, s.ptr, s.len);
|
||||||
|
|
||||||
|
s = HTTP_STR("Content-Length: ");
|
||||||
|
byte_queue_write(&conn->output, s.ptr, s.len);
|
||||||
|
|
||||||
|
conn->content_length_value_offset = byte_queue_offset(&conn->output);
|
||||||
|
|
||||||
|
#define TEN_SPACES " "
|
||||||
|
_Static_assert(sizeof(TEN_SPACES) == 10+1);
|
||||||
|
|
||||||
|
s = HTTP_STR(TEN_SPACES "\r\n");
|
||||||
|
byte_queue_write(&conn->output, s.ptr, s.len);
|
||||||
|
|
||||||
conn->state = HTTP_CLIENT_CONN_WAIT_HEADER;
|
conn->state = HTTP_CLIENT_CONN_WAIT_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3984,9 +4000,8 @@ void http_request_builder_body(HTTP_RequestBuilder builder,
|
|||||||
|
|
||||||
// Transition from WAIT_HEADER to WAIT_BODY if needed
|
// Transition from WAIT_HEADER to WAIT_BODY if needed
|
||||||
if (conn->state == HTTP_CLIENT_CONN_WAIT_HEADER) {
|
if (conn->state == HTTP_CLIENT_CONN_WAIT_HEADER) {
|
||||||
// End headers section
|
|
||||||
// TODO: add Content-Length header
|
|
||||||
byte_queue_write(&conn->output, "\r\n", 2);
|
byte_queue_write(&conn->output, "\r\n", 2);
|
||||||
|
conn->content_length_offset = byte_queue_offset(&conn->output);
|
||||||
conn->state = HTTP_CLIENT_CONN_WAIT_BODY;
|
conn->state = HTTP_CLIENT_CONN_WAIT_BODY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4040,8 +4055,8 @@ int http_request_builder_send(HTTP_RequestBuilder builder)
|
|||||||
goto error; // Early completion due to an error
|
goto error; // Early completion due to an error
|
||||||
|
|
||||||
if (conn->state == HTTP_CLIENT_CONN_WAIT_HEADER) {
|
if (conn->state == HTTP_CLIENT_CONN_WAIT_HEADER) {
|
||||||
// No body, just end headers
|
|
||||||
byte_queue_write(&conn->output, "\r\n", 2);
|
byte_queue_write(&conn->output, "\r\n", 2);
|
||||||
|
conn->content_length_offset = byte_queue_offset(&conn->output);
|
||||||
conn->state = HTTP_CLIENT_CONN_WAIT_BODY;
|
conn->state = HTTP_CLIENT_CONN_WAIT_BODY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4051,6 +4066,14 @@ int http_request_builder_send(HTTP_RequestBuilder builder)
|
|||||||
if (byte_queue_error(&conn->output))
|
if (byte_queue_error(&conn->output))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
int content_length = byte_queue_size_from_offset(&conn->output, conn->content_length_offset);
|
||||||
|
|
||||||
|
char tmp[11];
|
||||||
|
int len = snprintf(tmp, sizeof(tmp), "%d", content_length);
|
||||||
|
assert(len > 0 && len < 11);
|
||||||
|
|
||||||
|
byte_queue_patch(&conn->output, conn->content_length_value_offset, tmp, len);
|
||||||
|
|
||||||
ConnectTarget target = url_to_connect_target(conn->url);
|
ConnectTarget target = url_to_connect_target(conn->url);
|
||||||
bool secure = http_streq(conn->url.scheme, HTTP_STR("https"));
|
bool secure = http_streq(conn->url.scheme, HTTP_STR("https"));
|
||||||
if (socket_connect(&client->sockets, 1, &target, secure, conn->dont_verify_cert, conn) < 0)
|
if (socket_connect(&client->sockets, 1, &target, secure, conn->dont_verify_cert, conn) < 0)
|
||||||
@@ -4263,6 +4286,7 @@ void http_client_process_events(HTTP_Client *client,
|
|||||||
|
|
||||||
// Decouple from the socket
|
// Decouple from the socket
|
||||||
socket_set_user(&client->sockets, events[i].handle, NULL);
|
socket_set_user(&client->sockets, events[i].handle, NULL);
|
||||||
|
socket_close(&client->sockets, events[i].handle);
|
||||||
|
|
||||||
// Push to the ready queue
|
// Push to the ready queue
|
||||||
assert(client->num_ready < HTTP_CLIENT_CAPACITY);
|
assert(client->num_ready < HTTP_CLIENT_CAPACITY);
|
||||||
|
|||||||
@@ -943,6 +943,16 @@ typedef struct {
|
|||||||
|
|
||||||
// Parsed response once complete
|
// Parsed response once complete
|
||||||
HTTP_Response response;
|
HTTP_Response response;
|
||||||
|
|
||||||
|
// This offset points to the first byte that comes
|
||||||
|
// after the string "Content-Length: ".
|
||||||
|
ByteQueueOffset content_length_value_offset;
|
||||||
|
|
||||||
|
// This one points to the first byte of the body.
|
||||||
|
// This allows calculating the length of the request
|
||||||
|
// content byte subtracting it from the offset reached
|
||||||
|
// when the request is marked as done.
|
||||||
|
ByteQueueOffset content_length_offset;
|
||||||
} HTTP_ClientConn;
|
} HTTP_ClientConn;
|
||||||
|
|
||||||
// Fields of this struct are private
|
// Fields of this struct are private
|
||||||
|
|||||||
+26
-3
@@ -316,6 +316,22 @@ void http_request_builder_target(HTTP_RequestBuilder builder,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HTTP_String s;
|
||||||
|
|
||||||
|
s = HTTP_STR("Connection: Close\r\n");
|
||||||
|
byte_queue_write(&conn->output, s.ptr, s.len);
|
||||||
|
|
||||||
|
s = HTTP_STR("Content-Length: ");
|
||||||
|
byte_queue_write(&conn->output, s.ptr, s.len);
|
||||||
|
|
||||||
|
conn->content_length_value_offset = byte_queue_offset(&conn->output);
|
||||||
|
|
||||||
|
#define TEN_SPACES " "
|
||||||
|
_Static_assert(sizeof(TEN_SPACES) == 10+1);
|
||||||
|
|
||||||
|
s = HTTP_STR(TEN_SPACES "\r\n");
|
||||||
|
byte_queue_write(&conn->output, s.ptr, s.len);
|
||||||
|
|
||||||
conn->state = HTTP_CLIENT_CONN_WAIT_HEADER;
|
conn->state = HTTP_CLIENT_CONN_WAIT_HEADER;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,9 +371,8 @@ void http_request_builder_body(HTTP_RequestBuilder builder,
|
|||||||
|
|
||||||
// Transition from WAIT_HEADER to WAIT_BODY if needed
|
// Transition from WAIT_HEADER to WAIT_BODY if needed
|
||||||
if (conn->state == HTTP_CLIENT_CONN_WAIT_HEADER) {
|
if (conn->state == HTTP_CLIENT_CONN_WAIT_HEADER) {
|
||||||
// End headers section
|
|
||||||
// TODO: add Content-Length header
|
|
||||||
byte_queue_write(&conn->output, "\r\n", 2);
|
byte_queue_write(&conn->output, "\r\n", 2);
|
||||||
|
conn->content_length_offset = byte_queue_offset(&conn->output);
|
||||||
conn->state = HTTP_CLIENT_CONN_WAIT_BODY;
|
conn->state = HTTP_CLIENT_CONN_WAIT_BODY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,8 +426,8 @@ int http_request_builder_send(HTTP_RequestBuilder builder)
|
|||||||
goto error; // Early completion due to an error
|
goto error; // Early completion due to an error
|
||||||
|
|
||||||
if (conn->state == HTTP_CLIENT_CONN_WAIT_HEADER) {
|
if (conn->state == HTTP_CLIENT_CONN_WAIT_HEADER) {
|
||||||
// No body, just end headers
|
|
||||||
byte_queue_write(&conn->output, "\r\n", 2);
|
byte_queue_write(&conn->output, "\r\n", 2);
|
||||||
|
conn->content_length_offset = byte_queue_offset(&conn->output);
|
||||||
conn->state = HTTP_CLIENT_CONN_WAIT_BODY;
|
conn->state = HTTP_CLIENT_CONN_WAIT_BODY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -422,6 +437,14 @@ int http_request_builder_send(HTTP_RequestBuilder builder)
|
|||||||
if (byte_queue_error(&conn->output))
|
if (byte_queue_error(&conn->output))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
int content_length = byte_queue_size_from_offset(&conn->output, conn->content_length_offset);
|
||||||
|
|
||||||
|
char tmp[11];
|
||||||
|
int len = snprintf(tmp, sizeof(tmp), "%d", content_length);
|
||||||
|
assert(len > 0 && len < 11);
|
||||||
|
|
||||||
|
byte_queue_patch(&conn->output, conn->content_length_value_offset, tmp, len);
|
||||||
|
|
||||||
ConnectTarget target = url_to_connect_target(conn->url);
|
ConnectTarget target = url_to_connect_target(conn->url);
|
||||||
bool secure = http_streq(conn->url.scheme, HTTP_STR("https"));
|
bool secure = http_streq(conn->url.scheme, HTTP_STR("https"));
|
||||||
if (socket_connect(&client->sockets, 1, &target, secure, conn->dont_verify_cert, conn) < 0)
|
if (socket_connect(&client->sockets, 1, &target, secure, conn->dont_verify_cert, conn) < 0)
|
||||||
|
|||||||
@@ -105,6 +105,16 @@ typedef struct {
|
|||||||
|
|
||||||
// Parsed response once complete
|
// Parsed response once complete
|
||||||
HTTP_Response response;
|
HTTP_Response response;
|
||||||
|
|
||||||
|
// This offset points to the first byte that comes
|
||||||
|
// after the string "Content-Length: ".
|
||||||
|
ByteQueueOffset content_length_value_offset;
|
||||||
|
|
||||||
|
// This one points to the first byte of the body.
|
||||||
|
// This allows calculating the length of the request
|
||||||
|
// content byte subtracting it from the offset reached
|
||||||
|
// when the request is marked as done.
|
||||||
|
ByteQueueOffset content_length_offset;
|
||||||
} HTTP_ClientConn;
|
} HTTP_ClientConn;
|
||||||
|
|
||||||
// Fields of this struct are private
|
// Fields of this struct are private
|
||||||
|
|||||||
Reference in New Issue
Block a user