Commit 5a0817d1 authored by Nils Goroll's avatar Nils Goroll

Move minimal reponses to the transport level and use them for H1 100/400/417

Also log such resposenses
parent 917773a3
......@@ -42,6 +42,7 @@ typedef void vtr_sess_panic_f (struct vsb *, const struct sess *);
typedef void vtr_req_panic_f (struct vsb *, const struct req *);
typedef void vtr_req_fail_f (struct req *, enum sess_close);
typedef void vtr_reembark_f (struct worker *, struct req *);
typedef int vtr_minimal_response_f (struct req *, uint16_t status);
struct transport {
unsigned magic;
......@@ -60,6 +61,7 @@ struct transport {
vtr_sess_panic_f *sess_panic;
vtr_req_panic_f *req_panic;
vtr_reembark_f *reembark;
vtr_minimal_response_f *minimal_response;
VTAILQ_ENTRY(transport) list;
};
......
......@@ -202,6 +202,41 @@ http1_reembark(struct worker *wrk, struct req *req)
usleep(10000);
}
static int __match_proto__(vtr_minimal_response_f)
http1_minimal_response(struct req *req, uint16_t status)
{
size_t wl, l, spc = 80;
char buf[spc];
const char *reason;
assert(status >= 100);
assert(status < 1000);
reason = http_Status2Reason(status, NULL);
l = snprintf(buf, spc,
"HTTP/1.1 %03d %s\r\n\r\n", status, reason);
assert (l < spc);
VSLb(req->vsl, SLT_RespProtocol, "HTTP/1.1");
VSLb(req->vsl, SLT_RespStatus, "%03d", status);
VSLb(req->vsl, SLT_RespReason, "%s", reason);
if (status >= 400)
req->err_code = status;
wl = write(req->sp->fd, buf, l);
if (wl > 0)
req->acct.resp_hdrbytes += wl;
if (wl != l) {
VTCP_Assert(1);
if (! req->doclose)
req->doclose = SC_REM_CLOSE;
return (-1);
}
return (0);
}
struct transport HTTP1_transport = {
.name = "HTTP/1",
.magic = TRANSPORT_MAGIC,
......@@ -213,19 +248,25 @@ struct transport HTTP1_transport = {
.sess_panic = http1_sess_panic,
.req_panic = http1_req_panic,
.reembark = http1_reembark,
.minimal_response = http1_minimal_response,
};
/*----------------------------------------------------------------------
*/
static inline void
http1_abort(struct req *req, unsigned status)
{
AN(req->doclose);
assert(status >= 400);
(void) http1_minimal_response(req, status);
return;
}
static int
http1_dissect(struct worker *wrk, struct req *req)
{
const char *r_100 = "HTTP/1.1 100 Continue\r\n\r\n";
const char *r_400 = "HTTP/1.1 400 Bad Request\r\n\r\n";
const char *r_417 = "HTTP/1.1 417 Expectation Failed\r\n\r\n";
const char *p;
ssize_t r;
CHECK_OBJ_NOTNULL(wrk, WORKER_MAGIC);
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
......@@ -256,10 +297,8 @@ http1_dissect(struct worker *wrk, struct req *req)
(int)(req->htc->rxbuf_e - req->htc->rxbuf_b),
req->htc->rxbuf_b);
wrk->stats->client_req_400++;
r = write(req->sp->fd, r_400, strlen(r_400));
if (r > 0)
req->acct.resp_hdrbytes += r;
req->doclose = SC_RX_JUNK;
http1_abort(req, 400);
return (-1);
}
......@@ -284,21 +323,14 @@ http1_dissect(struct worker *wrk, struct req *req)
if (http_GetHdr(req->http, H_Expect, &p)) {
if (strcasecmp(p, "100-continue")) {
wrk->stats->client_req_417++;
req->err_code = 417;
r = write(req->sp->fd, r_417, strlen(r_417));
if (r > 0)
req->acct.resp_hdrbytes += r;
req->doclose = SC_RX_JUNK;
http1_abort(req, 417);
wrk->stats->client_req_417++;
return (-1);
}
r = write(req->sp->fd, r_100, strlen(r_100));
if (r > 0)
req->acct.resp_hdrbytes += r;
if (r != strlen(r_100)) {
req->doclose = SC_REM_CLOSE;
http1_simple_response(req, R_100);
if (req->doclose)
return (-1);
}
http_Unset(req->http, H_Expect);
}
......@@ -310,9 +342,7 @@ http1_dissect(struct worker *wrk, struct req *req)
req->doclose = http_DoConnection(req->http);
if (req->doclose == SC_RX_BAD) {
r = write(req->sp->fd, r_400, strlen(r_400));
if (r > 0)
req->acct.resp_hdrbytes += r;
http1_abort(req, 400);
return (-1);
}
......
......@@ -125,6 +125,7 @@ vtr_sess_panic_f h2_sess_panic;
/* http2/cache_http2_deliver.c */
#ifdef TRANSPORT_MAGIC
vtr_deliver_f h2_deliver;
vtr_minimal_response_f h2_minimal_response;
#endif /* TRANSPORT_MAGIC */
/* http2/cache_http2_hpack.c */
......
......@@ -92,6 +92,61 @@ h2_bytes(struct req *req, enum vdp_action act, void **priv,
return (0);
}
static inline size_t
h2_status(uint8_t *p, uint16_t status) {
size_t l = 1;
switch (status) {
case 200: *p = 0x80 | 8; break;
case 204: *p = 0x80 | 9; break;
case 206: *p = 0x80 | 10; break;
case 304: *p = 0x80 | 11; break;
case 400: *p = 0x80 | 12; break;
case 404: *p = 0x80 | 13; break;
case 500: *p = 0x80 | 14; break;
default:
*p++ = 0x18;
*p++ = 0x03;
l = 2;
l += snprintf((char*)p, 4, "%03d", status);
assert(l == 5);
break;
}
return (l);
}
int __match_proto__(vtr_minimal_response_f)
h2_minimal_response(struct req *req, uint16_t status)
{
struct h2_req *r2;
const size_t spc = 6;
size_t l;
uint8_t buf[spc];
CHECK_OBJ_NOTNULL(req, REQ_MAGIC);
CAST_OBJ_NOTNULL(r2, req->transport_priv, H2_REQ_MAGIC);
assert(status >= 100);
assert(status < 1000);
l = h2_status(buf, status);
assert(l < spc);
VSLb(req->vsl, SLT_RespProtocol, "HTTP/2.0");
VSLb(req->vsl, SLT_RespStatus, "%03d", status);
VSLb(req->vsl, SLT_RespReason, "%s", http_Status2Reason(status, NULL));
if (status >= 400)
req->err_code = status;
H2_Send(req->wrk, r2, 1,
H2_FRAME_HEADERS, H2FF_HEADERS_END_HEADERS,
l, buf);
return (0);
}
void __match_proto__(vtr_deliver_f)
h2_deliver(struct req *req, struct boc *boc, int sendbody)
{
......@@ -118,22 +173,7 @@ h2_deliver(struct req *req, struct boc *boc, int sendbody)
(void)WS_Reserve(req->ws, 0);
p = (void*)req->ws->f;
switch (req->resp->status) {
case 200: *p++ = 0x80 | 8; break;
case 204: *p++ = 0x80 | 9; break;
case 206: *p++ = 0x80 | 10; break;
case 304: *p++ = 0x80 | 11; break;
case 400: *p++ = 0x80 | 12; break;
case 404: *p++ = 0x80 | 13; break;
case 500: *p++ = 0x80 | 14; break;
default:
*p++ = 0x18;
*p++ = 0x03;
assert(snprintf((char*)p, 4, "%03d", req->resp->status) == 3);
p += 3;
break;
}
p += h2_status(p, req->resp->status);
hp = req->resp;
for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
......
......@@ -831,4 +831,5 @@ struct transport H2_transport = {
.new_session = h2_new_session,
.sess_panic = h2_sess_panic,
.deliver = h2_deliver,
.minimal_response = h2_minimal_response,
};
......@@ -30,6 +30,7 @@
/*lint -save -e525 -e539 */
HTTP_RESP(100, "Continue")
HTTP_RESP(101, "Switching Protocols")
HTTP_RESP(200, "OK")
HTTP_RESP(201, "Created")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment