diff --git a/src/libmongoc/src/mongoc/mcd-azure.c b/src/libmongoc/src/mongoc/mcd-azure.c index b7cdb69270b..76d1b093811 100644 --- a/src/libmongoc/src/mongoc/mcd-azure.c +++ b/src/libmongoc/src/mongoc/mcd-azure.c @@ -32,6 +32,7 @@ mcd_azure_imds_request_init (mcd_azure_imds_request *req) _mongoc_http_request_init (&req->req); // The HTTP host of the IMDS server req->req.host = "169.254.169.254"; + req->req.port = 80; // No body req->req.body = ""; // We GET diff --git a/src/libmongoc/src/mongoc/mongoc-http.c b/src/libmongoc/src/mongoc/mongoc-http.c index 7c24c1c2566..39c4f7e01a8 100644 --- a/src/libmongoc/src/mongoc/mongoc-http.c +++ b/src/libmongoc/src/mongoc/mongoc-http.c @@ -69,7 +69,7 @@ _mongoc_http_render_request_head (const mongoc_http_request_t *req) bson_free (path); /* Always add Host header. */ - bson_string_append_printf (string, "Host: %s\r\n", req->host); + bson_string_append_printf (string, "Host: %s:%d\r\n", req->host, req->port); /* Always add Connection: close header to ensure server closes connection. */ bson_string_append_printf (string, "Connection: close\r\n"); /* Add Content-Length if body is included. */ @@ -175,7 +175,7 @@ _mongoc_http_send (const mongoc_http_request_t *req, goto fail; } - if (req->body) { + if (req->body && req->body_len) { iovec.iov_base = (void *) req->body; iovec.iov_len = req->body_len; if (!_mongoc_stream_writev_full (stream, &iovec, 1, timeout_ms, error)) { @@ -206,6 +206,42 @@ _mongoc_http_send (const mongoc_http_request_t *req, } http_response_str = (char *) http_response_buf.data; + const char *const resp_end_ptr = + http_response_str + http_response_buf.datalen; + + const char *proto_leader = "HTTP/1.0 "; + ptr = strstr (http_response_str, proto_leader); + if (!ptr) { + bson_set_error (error, + MONGOC_ERROR_STREAM, + MONGOC_ERROR_STREAM_SOCKET, + "No HTTP version leader in HTTP response"); + goto fail; + } + + ptr += strlen (proto_leader); + ssize_t remain = resp_end_ptr - ptr; + if (remain < 4) { + bson_set_error (error, + MONGOC_ERROR_STREAM, + MONGOC_ERROR_STREAM_SOCKET, + "Short read in HTTP response"); + goto fail; + } + + char status_buf[4] = {0}; + memcpy (status_buf, ptr, 3); + char *status_endptr; + res->status = strtol (status_buf, &status_endptr, 10); + if (status_endptr != status_buf + 3) { + bson_set_error (error, + MONGOC_ERROR_STREAM, + MONGOC_ERROR_STREAM_SOCKET, + "Invalid HTTP response status string %*.s", + 4, + status_buf); + goto fail; + } /* Find the end of the headers. */ ptr = strstr (http_response_str, header_delimiter); diff --git a/src/libmongoc/tests/test-mcd-azure-imds.c b/src/libmongoc/tests/test-mcd-azure-imds.c index 9d1dee73cb7..52bc0f38352 100644 --- a/src/libmongoc/tests/test-mcd-azure-imds.c +++ b/src/libmongoc/tests/test-mcd-azure-imds.c @@ -53,7 +53,7 @@ _test_http_req (void) "/metadata/identity/oauth2/" "token?api-version=2018-02-01&resource=https%3A%2F%2Fvault." "azure.net HTTP/1.0\r\n" - "Host: 169.254.169.254\r\n" + "Host: 169.254.169.254:80\r\n" "Connection: close\r\n" "Metadata: true\r\n" "Accept: application/json\r\n" diff --git a/src/libmongoc/tests/test-mongoc-http.c b/src/libmongoc/tests/test-mongoc-http.c index 62cbbabb379..b827d3ff590 100644 --- a/src/libmongoc/tests/test-mongoc-http.c +++ b/src/libmongoc/tests/test-mongoc-http.c @@ -36,8 +36,13 @@ test_mongoc_http (void *unused) req.method = "GET"; req.host = "example.com"; req.port = 80; + // Empty body is okay + req.body = ""; + req.body_len = 0; r = _mongoc_http_send (&req, 10000, false, NULL, &res, &error); + ASSERT_CMPINT (res.status, ==, 200); ASSERT_OR_PRINT (r, error); + ASSERT_CMPINT (res.body_len, >, 0); _mongoc_http_response_cleanup (&res); /* Basic POST request with a body. */ @@ -46,7 +51,9 @@ test_mongoc_http (void *unused) req.body_len = 4; req.port = 80; r = _mongoc_http_send (&req, 10000, false, NULL, &res, &error); + ASSERT_CMPINT (res.status, ==, 200); ASSERT_OR_PRINT (r, error); + ASSERT_CMPINT (res.body_len, >, 0); _mongoc_http_response_cleanup (&res); }