Commit e99e8fba authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Always set the reason headerfield when the status field is set, to

keep them in sync.  If you want a custom reason field, set status
first, then reason.

With this in place, HTTP1_Write() doesn't need to worry about them
being OK, and we can polish that code a fair bit.

Turn a couple of boolean arguments into more readable magics.
parent dbd98ce2
...@@ -857,6 +857,8 @@ void HTTP1_Session(struct worker *, struct req *); ...@@ -857,6 +857,8 @@ void HTTP1_Session(struct worker *, struct req *);
int HTTP1_DiscardReqBody(struct req *req); int HTTP1_DiscardReqBody(struct req *req);
int HTTP1_CacheReqBody(struct req *req, ssize_t maxsize); int HTTP1_CacheReqBody(struct req *req, ssize_t maxsize);
int HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv); int HTTP1_IterateReqBody(struct req *req, req_body_iter_f *func, void *priv);
extern const int HTTP1_Req[3];
extern const int HTTP1_Resp[3];
/* cache_http1_deliver.c */ /* cache_http1_deliver.c */
unsigned V1D_FlushReleaseAcct(struct req *req); unsigned V1D_FlushReleaseAcct(struct req *req);
...@@ -1030,7 +1032,7 @@ ssize_t HTTP1_Read(struct http_conn *htc, void *d, size_t len); ...@@ -1030,7 +1032,7 @@ ssize_t HTTP1_Read(struct http_conn *htc, void *d, size_t len);
enum htc_status_e HTTP1_Complete(struct http_conn *htc); enum htc_status_e HTTP1_Complete(struct http_conn *htc);
uint16_t HTTP1_DissectRequest(struct req *); uint16_t HTTP1_DissectRequest(struct req *);
uint16_t HTTP1_DissectResponse(struct http *sp, const struct http_conn *htc); uint16_t HTTP1_DissectResponse(struct http *sp, const struct http_conn *htc);
unsigned HTTP1_Write(const struct worker *w, const struct http *hp, int resp); unsigned HTTP1_Write(const struct worker *w, const struct http *hp, const int*);
#define HTTPH(a, b, c) extern char b[]; #define HTTPH(a, b, c) extern char b[];
#include "tbl/http_headers.h" #include "tbl/http_headers.h"
......
...@@ -552,7 +552,9 @@ http_GetStatus(const struct http *hp) ...@@ -552,7 +552,9 @@ http_GetStatus(const struct http *hp)
return (hp->status); return (hp->status);
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------
* Setting the status will also set the Reason appropriately
*/
void void
http_SetStatus(struct http *to, uint16_t status) http_SetStatus(struct http *to, uint16_t status)
...@@ -569,6 +571,7 @@ http_SetStatus(struct http *to, uint16_t status) ...@@ -569,6 +571,7 @@ http_SetStatus(struct http *to, uint16_t status)
assert(status >= 100); assert(status >= 100);
bprintf(buf, "%03d", status); bprintf(buf, "%03d", status);
http_PutField(to, HTTP_HDR_STATUS, buf); http_PutField(to, HTTP_HDR_STATUS, buf);
http_SetH(to, HTTP_HDR_REASON, http_Status2Reason(status));
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
......
...@@ -322,7 +322,8 @@ V1D_Deliver(struct req *req) ...@@ -322,7 +322,8 @@ V1D_Deliver(struct req *req)
* Send HTTP protocol header, unless interior ESI object * Send HTTP protocol header, unless interior ESI object
*/ */
if (!(req->res_mode & RES_ESI_CHILD)) if (!(req->res_mode & RES_ESI_CHILD))
req->resp_hdrbytes += HTTP1_Write(req->wrk, req->resp, 1); req->resp_hdrbytes +=
HTTP1_Write(req->wrk, req->resp, HTTP1_Resp);
if (req->res_mode & RES_CHUNKED) if (req->res_mode & RES_CHUNKED)
WRW_Chunked(req->wrk); WRW_Chunked(req->wrk);
...@@ -429,7 +430,8 @@ V1D_Deliver_Synth(struct req *req) ...@@ -429,7 +430,8 @@ V1D_Deliver_Synth(struct req *req)
* Send HTTP protocol header, unless interior ESI object * Send HTTP protocol header, unless interior ESI object
*/ */
if (!(req->res_mode & RES_ESI_CHILD)) if (!(req->res_mode & RES_ESI_CHILD))
req->resp_hdrbytes += HTTP1_Write(req->wrk, req->resp, 1); req->resp_hdrbytes +=
HTTP1_Write(req->wrk, req->resp, HTTP1_Resp);
if (req->res_mode & RES_CHUNKED) if (req->res_mode & RES_CHUNKED)
WRW_Chunked(req->wrk); WRW_Chunked(req->wrk);
......
...@@ -327,7 +327,7 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, struct req *req) ...@@ -327,7 +327,7 @@ V1F_fetch_hdr(struct worker *wrk, struct busyobj *bo, struct req *req)
(void)VTCP_blocking(vc->fd); /* XXX: we should timeout instead */ (void)VTCP_blocking(vc->fd); /* XXX: we should timeout instead */
WRW_Reserve(wrk, &vc->fd, bo->vsl, bo->t_prev); WRW_Reserve(wrk, &vc->fd, bo->vsl, bo->t_prev);
hdrbytes = HTTP1_Write(wrk, hp, 0); hdrbytes = HTTP1_Write(wrk, hp, HTTP1_Req);
/* Deal with any message-body the request might (still) have */ /* Deal with any message-body the request might (still) have */
i = 0; i = 0;
......
...@@ -49,6 +49,14 @@ ...@@ -49,6 +49,14 @@
#include "vct.h" #include "vct.h"
const int HTTP1_Req[3] = {
HTTP_HDR_METHOD, HTTP_HDR_URL, HTTP_HDR_PROTO
};
const int HTTP1_Resp[3] = {
HTTP_HDR_PROTO, HTTP_HDR_STATUS, HTTP_HDR_REASON
};
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
void void
...@@ -294,55 +302,46 @@ htc_dissect_hdrs(struct http *hp, char *p, const struct http_conn *htc) ...@@ -294,55 +302,46 @@ htc_dissect_hdrs(struct http *hp, char *p, const struct http_conn *htc)
*/ */
static uint16_t static uint16_t
htc_splitline(struct http *hp, const struct http_conn *htc, int req) htc_splitline(struct http *hp, const struct http_conn *htc, const int *hf)
{ {
char *p; char *p;
int h1, h2, h3;
assert(hf == HTTP1_Req || hf == HTTP1_Resp);
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
Tcheck(htc->rxbuf); Tcheck(htc->rxbuf);
if (req) { AZ(hp->hd[hf[0]].b);
h1 = HTTP_HDR_METHOD; AZ(hp->hd[hf[1]].b);
h2 = HTTP_HDR_URL; AZ(hp->hd[hf[2]].b);
h3 = HTTP_HDR_PROTO;
} else {
h1 = HTTP_HDR_PROTO;
h2 = HTTP_HDR_STATUS;
h3 = HTTP_HDR_REASON;
}
AZ(hp->hd[h1].b);
AZ(hp->hd[h2].b);
AZ(hp->hd[h3].b);
/* Skip leading LWS */ /* Skip leading LWS */
for (p = htc->rxbuf.b ; vct_islws(*p); p++) for (p = htc->rxbuf.b ; vct_islws(*p); p++)
continue; continue;
hp->hd[h1].b = p; hp->hd[hf[0]].b = p;
/* First field cannot contain SP or CTL */ /* First field cannot contain SP or CTL */
for (; !vct_issp(*p); p++) { for (; !vct_issp(*p); p++) {
if (vct_isctl(*p)) if (vct_isctl(*p))
return (400); return (400);
} }
hp->hd[h1].e = p; hp->hd[hf[0]].e = p;
assert(Tlen(hp->hd[h1])); assert(Tlen(hp->hd[hf[0]]));
/* Skip SP */ /* Skip SP */
for (; vct_issp(*p); p++) { for (; vct_issp(*p); p++) {
if (vct_isctl(*p)) if (vct_isctl(*p))
return (400); return (400);
} }
hp->hd[h2].b = p; hp->hd[hf[1]].b = p;
/* Second field cannot contain LWS or CTL */ /* Second field cannot contain LWS or CTL */
for (; !vct_islws(*p); p++) { for (; !vct_islws(*p); p++) {
if (vct_isctl(*p)) if (vct_isctl(*p))
return (400); return (400);
} }
hp->hd[h2].e = p; hp->hd[hf[1]].e = p;
if (!Tlen(hp->hd[h2])) if (!Tlen(hp->hd[hf[1]]))
return (400); return (400);
/* Skip SP */ /* Skip SP */
...@@ -350,23 +349,23 @@ htc_splitline(struct http *hp, const struct http_conn *htc, int req) ...@@ -350,23 +349,23 @@ htc_splitline(struct http *hp, const struct http_conn *htc, int req)
if (vct_isctl(*p)) if (vct_isctl(*p))
return (400); return (400);
} }
hp->hd[h3].b = p; hp->hd[hf[2]].b = p;
/* Third field is optional and cannot contain CTL except TAB */ /* Third field is optional and cannot contain CTL except TAB */
for (; !vct_iscrlf(p); p++) { for (; !vct_iscrlf(p); p++) {
if (vct_isctl(*p) && !vct_issp(*p)) { if (vct_isctl(*p) && !vct_issp(*p)) {
hp->hd[h3].b = NULL; hp->hd[hf[2]].b = NULL;
return (400); return (400);
} }
} }
hp->hd[h3].e = p; hp->hd[hf[2]].e = p;
/* Skip CRLF */ /* Skip CRLF */
p += vct_skipcrlf(p); p += vct_skipcrlf(p);
*hp->hd[h1].e = '\0'; *hp->hd[hf[0]].e = '\0';
*hp->hd[h2].e = '\0'; *hp->hd[hf[1]].e = '\0';
*hp->hd[h3].e = '\0'; *hp->hd[hf[2]].e = '\0';
return (htc_dissect_hdrs(hp, p, htc)); return (htc_dissect_hdrs(hp, p, htc));
} }
...@@ -426,7 +425,7 @@ HTTP1_DissectRequest(struct req *req) ...@@ -426,7 +425,7 @@ HTTP1_DissectRequest(struct req *req)
hp = req->http; hp = req->http;
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
retval = htc_splitline(hp, htc, 1); retval = htc_splitline(hp, htc, HTTP1_Req);
if (retval != 0) { if (retval != 0) {
VSLbt(req->vsl, SLT_HttpGarbage, htc->rxbuf); VSLbt(req->vsl, SLT_HttpGarbage, htc->rxbuf);
return (retval); return (retval);
...@@ -465,7 +464,7 @@ HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc) ...@@ -465,7 +464,7 @@ HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc)
CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC); CHECK_OBJ_NOTNULL(htc, HTTP_CONN_MAGIC);
CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC); CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
if (htc_splitline(hp, htc, 0)) if (htc_splitline(hp, htc, HTTP1_Resp))
retval = 503; retval = 503;
if (retval == 0) { if (retval == 0) {
...@@ -495,6 +494,7 @@ HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc) ...@@ -495,6 +494,7 @@ HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc)
assert(retval == 503); assert(retval == 503);
hp->status = retval; hp->status = retval;
http_SetH(hp, HTTP_HDR_STATUS, "503"); http_SetH(hp, HTTP_HDR_STATUS, "503");
http_SetH(hp, HTTP_HDR_REASON, http_Status2Reason(retval));
} }
if (hp->hd[HTTP_HDR_REASON].b == NULL || if (hp->hd[HTTP_HDR_REASON].b == NULL ||
...@@ -507,36 +507,20 @@ HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc) ...@@ -507,36 +507,20 @@ HTTP1_DissectResponse(struct http *hp, const struct http_conn *htc)
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
unsigned unsigned
HTTP1_Write(const struct worker *w, const struct http *hp, int resp) HTTP1_Write(const struct worker *w, const struct http *hp, const int *hf)
{ {
unsigned u, l; unsigned u, l;
if (resp) { assert(hf == HTTP1_Req || hf == HTTP1_Resp);
l = WRW_WriteH(w, &hp->hd[HTTP_HDR_PROTO], " "); AN(hp->hd[hf[0]].b);
AN(hp->hd[hf[1]].b);
hp->hd[HTTP_HDR_STATUS].b = WS_Alloc(hp->ws, 4); AN(hp->hd[hf[2]].b);
AN(hp->hd[HTTP_HDR_STATUS].b); l = WRW_WriteH(w, &hp->hd[hf[0]], " ");
l += WRW_WriteH(w, &hp->hd[hf[1]], " ");
l += WRW_WriteH(w, &hp->hd[hf[2]], "\r\n");
assert(hp->status >= 100 && hp->status <= 999); for (u = HTTP_HDR_FIRST; u < hp->nhd; u++)
sprintf(hp->hd[HTTP_HDR_STATUS].b, "%3d", hp->status);
hp->hd[HTTP_HDR_STATUS].e = hp->hd[HTTP_HDR_STATUS].b + 3;
l += WRW_WriteH(w, &hp->hd[HTTP_HDR_STATUS], " ");
l += WRW_WriteH(w, &hp->hd[HTTP_HDR_REASON], "\r\n");
} else {
AN(hp->hd[HTTP_HDR_URL].b);
l = WRW_WriteH(w, &hp->hd[HTTP_HDR_METHOD], " ");
l += WRW_WriteH(w, &hp->hd[HTTP_HDR_URL], " ");
l += WRW_WriteH(w, &hp->hd[HTTP_HDR_PROTO], "\r\n");
}
for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
if (hp->hd[u].b == NULL)
continue;
AN(hp->hd[u].b);
AN(hp->hd[u].e);
l += WRW_WriteH(w, &hp->hd[u], "\r\n"); l += WRW_WriteH(w, &hp->hd[u], "\r\n");
}
l += WRW_Write(w, "\r\n", -1); l += WRW_Write(w, "\r\n", -1);
return (l); return (l);
} }
...@@ -124,7 +124,7 @@ PipeRequest(struct req *req, struct busyobj *bo) ...@@ -124,7 +124,7 @@ PipeRequest(struct req *req, struct busyobj *bo)
(void)VTCP_blocking(vc->fd); (void)VTCP_blocking(vc->fd);
WRW_Reserve(wrk, &vc->fd, bo->vsl, req->t_req); WRW_Reserve(wrk, &vc->fd, bo->vsl, req->t_req);
hdrbytes = HTTP1_Write(wrk, bo->bereq, 0); hdrbytes = HTTP1_Write(wrk, bo->bereq, HTTP1_Req);
if (req->htc->pipeline.b != NULL) if (req->htc->pipeline.b != NULL)
(void)WRW_Write(wrk, req->htc->pipeline.b, (void)WRW_Write(wrk, req->htc->pipeline.b,
......
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