[master] 5a0817d Move minimal reponses to the transport level and use them for H1 100/400/417
Nils Goroll
nils.goroll at uplex.de
Thu Feb 23 17:46:05 CET 2017
commit 5a0817d1446c64467745e50fb9d9ab0e791e9bec
Author: Nils Goroll <nils.goroll at uplex.de>
Date: Thu Feb 23 17:44:26 2017 +0100
Move minimal reponses to the transport level and use them for H1 100/400/417
Also log such resposenses
diff --git a/bin/varnishd/cache/cache_transport.h b/bin/varnishd/cache/cache_transport.h
index 2633cfe..447c427 100644
--- a/bin/varnishd/cache/cache_transport.h
+++ b/bin/varnishd/cache/cache_transport.h
@@ -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;
};
diff --git a/bin/varnishd/http1/cache_http1_fsm.c b/bin/varnishd/http1/cache_http1_fsm.c
index 06eb34b..1dfe146 100644
--- a/bin/varnishd/http1/cache_http1_fsm.c
+++ b/bin/varnishd/http1/cache_http1_fsm.c
@@ -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);
}
diff --git a/bin/varnishd/http2/cache_http2.h b/bin/varnishd/http2/cache_http2.h
index bf9604c..a9a44ef 100644
--- a/bin/varnishd/http2/cache_http2.h
+++ b/bin/varnishd/http2/cache_http2.h
@@ -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 */
diff --git a/bin/varnishd/http2/cache_http2_deliver.c b/bin/varnishd/http2/cache_http2_deliver.c
index f21631c..a589428 100644
--- a/bin/varnishd/http2/cache_http2_deliver.c
+++ b/bin/varnishd/http2/cache_http2_deliver.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++) {
diff --git a/bin/varnishd/http2/cache_http2_proto.c b/bin/varnishd/http2/cache_http2_proto.c
index 00fda7c..26a0347 100644
--- a/bin/varnishd/http2/cache_http2_proto.c
+++ b/bin/varnishd/http2/cache_http2_proto.c
@@ -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,
};
diff --git a/include/tbl/http_response.h b/include/tbl/http_response.h
index eaa74c4..0e21d00 100644
--- a/include/tbl/http_response.h
+++ b/include/tbl/http_response.h
@@ -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")
More information about the varnish-commit
mailing list