Browse Source

[core] connection_check_expect_100()

isolate code to check for Expect: 100-continue
(separate out from code to read request body)
master
Glenn Strauss 9 months ago
parent
commit
7a3098398c
  1. 64
      src/connections.c

64
src/connections.c

@ -1796,6 +1796,40 @@ connection_handle_read_body_unknown (request_st * const r, chunkqueue * const cq
}
__attribute_cold__
static int
connection_check_expect_100 (request_st * const r, connection * const con)
{
if (!con->is_writable)
return 1;
const buffer * const vb =
http_header_request_get(r, HTTP_HEADER_EXPECT,
CONST_STR_LEN("Expect"));
if (NULL == vb)
return 1;
/* (always unset Expect header so that check is not repeated for request */
int rc = buffer_eq_icase_slen(vb, CONST_STR_LEN("100-continue"));
http_header_request_unset(r, HTTP_HEADER_EXPECT,
CONST_STR_LEN("Expect"));
if (!rc
|| 0 != r->reqbody_queue->bytes_in
|| !chunkqueue_is_empty(r->read_queue)
|| !chunkqueue_is_empty(r->write_queue))
return 1;
/* send 100 Continue only if no request body data received yet
* and response has not yet started (checked above) */
if (r->http_version > HTTP_VERSION_1_1)
h2_send_100_continue(r, con);
else if (r->http_version == HTTP_VERSION_1_1)
return connection_write_100_continue(r, con);
return 1;
}
static handler_t
connection_handle_read_post_state (request_st * const r)
{
@ -1823,29 +1857,15 @@ connection_handle_read_post_state (request_st * const r)
default:
break;
}
}
chunkqueue_remove_finished_chunks(cq);
/* Check for Expect: 100-continue in request headers
* if no request body received yet */
if (chunkqueue_is_empty(cq) && 0 == dst_cq->bytes_in
&& r->http_version != HTTP_VERSION_1_0
&& chunkqueue_is_empty(r->write_queue) && con->is_writable) {
const buffer *vb =
http_header_request_get(r, HTTP_HEADER_EXPECT,
CONST_STR_LEN("Expect"));
if (NULL != vb
&& buffer_eq_icase_slen(vb, CONST_STR_LEN("100-continue"))) {
http_header_request_unset(r, HTTP_HEADER_EXPECT,
CONST_STR_LEN("Expect"));
if (r->http_version > HTTP_VERSION_1_1)
h2_send_100_continue(r, con);
else if (!connection_write_100_continue(r, con))
return HANDLER_ERROR;
}
chunkqueue_remove_finished_chunks(cq);
}
/* Check for Expect: 100-continue in request headers */
if (light_btst(r->rqst_htags, HTTP_HEADER_EXPECT)
&& !connection_check_expect_100(r, con))
return HANDLER_ERROR;
if (r->http_version > HTTP_VERSION_1_1) {
/* h2_recv_data() places frame payload directly into r->reqbody_queue */
}
@ -1855,6 +1875,7 @@ connection_handle_read_post_state (request_st * const r)
? connection_handle_read_post_chunked(r, cq, dst_cq)
: connection_handle_read_body_unknown(r, cq, dst_cq);
if (HANDLER_GO_ON != rc) return rc;
chunkqueue_remove_finished_chunks(cq);
}
else {
off_t len = (off_t)r->reqbody_length - dst_cq->bytes_in;
@ -1867,10 +1888,9 @@ connection_handle_read_post_state (request_st * const r)
/* writing to temp file failed */ /* Internal Server Error */
return http_response_reqbody_read_error(r, 500);
}
chunkqueue_remove_finished_chunks(cq);
}
chunkqueue_remove_finished_chunks(cq);
if (dst_cq->bytes_in == (off_t)r->reqbody_length) {
/* Content is ready */
r->conf.stream_request_body &= ~FDEVENT_STREAM_REQUEST_POLLIN;

Loading…
Cancel
Save