source: bin/varnishd/cache_http.c @ b1692e

Revision b1692e, 22.0 KB checked in by Dag Erling Smørgrav <des@…>, 7 years ago (diff)

Use strlen() directly.

git-svn-id:  http://www.varnish-cache.org/svn/trunk@1749 d4fa192b-c00b-0410-8231-f00ffab90ce4

  • Property mode set to 100644
Line 
1/*-
2 * Copyright (c) 2006 Verdens Gang AS
3 * Copyright (c) 2006-2007 Linpro AS
4 * All rights reserved.
5 *
6 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $Id$
30 *
31 * HTTP request storage and manipulation
32 */
33
34#include <stdio.h>
35#include <errno.h>
36#include <unistd.h>
37#include <stdarg.h>
38#include <stdlib.h>
39#include <string.h>
40#include <ctype.h>
41
42#include "heritage.h"
43#include "shmlog.h"
44#include "cache.h"
45
46#ifndef HAVE_STRLCPY
47#include <compat/strlcpy.h>
48#endif
49
50#define HTTPH(a, b, c, d, e, f, g) char b[] = "*" a ":";
51#include "http_headers.h"
52#undef HTTPH
53
54enum httptag {
55        HTTP_T_Request,
56        HTTP_T_Response,
57        HTTP_T_Status,
58        HTTP_T_URL,
59        HTTP_T_Protocol,
60        HTTP_T_Header,
61};
62
63#define LOGMTX2(ax, bx)         \
64        [HTTP_T_##bx] = SLT_##ax##bx
65
66#define LOGMTX1(ax) {           \
67        LOGMTX2(ax, Request),   \
68        LOGMTX2(ax, Response),  \
69        LOGMTX2(ax, Status),    \
70        LOGMTX2(ax, URL),       \
71        LOGMTX2(ax, Protocol),  \
72        LOGMTX2(ax, Header),    \
73        }
74
75static enum shmlogtag logmtx[3][7] = {
76        [HTTP_Rx] = LOGMTX1(Rx),
77        [HTTP_Tx] = LOGMTX1(Tx),
78        [HTTP_Obj] = LOGMTX1(Obj)
79};
80
81static enum shmlogtag
82http2shmlog(struct http *hp, enum httptag t)
83{
84
85        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
86        assert(/* hp->logtag >= HTTP_Rx && */hp->logtag <= HTTP_Obj);
87        assert(/* t >= HTTP_T_Request && */t <= HTTP_T_Header);
88        return (logmtx[hp->logtag][t]);
89}
90
91static void
92WSLH(struct worker *w, enum httptag t, unsigned fd, struct http *hp, int hdr)
93{
94
95        WSLR(w, http2shmlog(hp, t), fd, hp->hd[hdr].b, hp->hd[hdr].e);
96}
97
98/*--------------------------------------------------------------------*/
99/* List of canonical HTTP response code names from RFC2616 */
100
101static struct http_msg {
102        unsigned        nbr;
103        const char      *txt;
104} http_msg[] = {
105        { 101, "Switching Protocols" },
106        { 200, "OK" },
107        { 201, "Created" },
108        { 202, "Accepted" },
109        { 203, "Non-Authoritative Information" },
110        { 204, "No Content" },
111        { 205, "Reset Content" },
112        { 206, "Partial Content" },
113        { 300, "Multiple Choices" },
114        { 301, "Moved Permanently" },
115        { 302, "Found" },
116        { 303, "See Other" },
117        { 304, "Not Modified" },
118        { 305, "Use Proxy" },
119        { 306, "(Unused)" },
120        { 307, "Temporary Redirect" },
121        { 400, "Bad Request" },
122        { 401, "Unauthorized" },
123        { 402, "Payment Required" },
124        { 403, "Forbidden" },
125        { 404, "Not Found" },
126        { 405, "Method Not Allowed" },
127        { 406, "Not Acceptable" },
128        { 407, "Proxy Authentication Required" },
129        { 408, "Request Timeout" },
130        { 409, "Conflict" },
131        { 410, "Gone" },
132        { 411, "Length Required" },
133        { 412, "Precondition Failed" },
134        { 413, "Request Entity Too Large" },
135        { 414, "Request-URI Too Long" },
136        { 415, "Unsupported Media Type" },
137        { 416, "Requested Range Not Satisfiable" },
138        { 417, "Expectation Failed" },
139        { 500, "Internal Server Error" },
140        { 501, "Not Implemented" },
141        { 502, "Bad Gateway" },
142        { 503, "Service Unavailable" },
143        { 504, "Gateway Timeout" },
144        { 505, "HTTP Version Not Supported" },
145        { 0, NULL }
146};
147
148const char *
149http_StatusMessage(int status)
150{
151        struct http_msg *mp;
152
153        assert(status >= 100 && status <= 999);
154        for (mp = http_msg; mp->nbr != 0 && mp->nbr <= status; mp++)
155                if (mp->nbr == status)
156                        return (mp->txt);
157        return ("Unknown Error");
158}
159
160/*--------------------------------------------------------------------*/
161
162void
163http_Setup(struct http *hp, void *space, unsigned len)
164{
165
166        assert(len > 0);
167        memset(hp, 0, sizeof *hp);
168        hp->magic = HTTP_MAGIC;
169        WS_Init(hp->ws, space, len);
170        hp->nhd = HTTP_HDR_FIRST;
171}
172
173/*--------------------------------------------------------------------*/
174
175
176static int
177http_IsHdr(struct http_hdr *hh, const char *hdr)
178{
179        unsigned l;
180
181        AN(hh->b);
182        AN(hh->e);
183        AN(hdr);
184        l = hdr[0];
185        assert(l == strlen(hdr + 1));
186        assert(hdr[l] == ':');
187        hdr++;
188        return (!strncasecmp(hdr, hh->b, l));
189}
190
191/*--------------------------------------------------------------------*/
192
193static unsigned
194http_findhdr(struct http *hp, unsigned l, const char *hdr)
195{
196        unsigned u;
197
198        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
199                AN(hp->hd[u].b);
200                AN(hp->hd[u].e);
201                if (hp->hd[u].e < hp->hd[u].b + l + 1)
202                        continue;
203                if (hp->hd[u].b[l] != ':')
204                        continue;
205                if (strncasecmp(hdr, hp->hd[u].b, l))
206                        continue;
207                return (u);
208        }
209        return (0);
210}
211
212int
213http_GetHdr(struct http *hp, const char *hdr, char **ptr)
214{
215        unsigned u, l;
216        char *p;
217
218        l = hdr[0];
219        assert(l == strlen(hdr + 1));
220        assert(hdr[l] == ':');
221        hdr++;
222        u = http_findhdr(hp, l - 1, hdr);
223        if (u == 0) {
224                *ptr = NULL;
225                return (0);
226        }
227        p = hp->hd[u].b + l;
228        while (isspace(*p))
229                p++;
230        *ptr = p;
231        return (1);
232}
233
234/*--------------------------------------------------------------------*/
235
236int
237http_GetHdrField(struct http *hp, const char *hdr, const char *field, char **ptr)
238{
239        char *h;
240        int fl;
241
242        if (!http_GetHdr(hp, hdr, &h))
243                return (0);
244        fl = strlen(field);
245        while (*h) {
246                if (isspace(*h)) {
247                        h++;
248                        continue;
249                }
250                if (*h == ',') {
251                        h++;
252                        continue;
253                }
254                if (memcmp(h, field, fl) ||
255                    isalpha(h[fl]) || h[fl] == '-') {
256                        while (*h && !(isspace(*h) || *h == ','))
257                                h++;
258                        continue;
259                }
260                if (h[fl] == '=')
261                        *ptr = &h[fl + 1];
262                else
263                        *ptr = NULL;
264                return (1);
265        }
266        return (0);
267}
268
269/*--------------------------------------------------------------------*/
270
271void
272http_DoConnection(struct sess *sp)
273{
274        struct http *hp = sp->http;
275        char *p, *q;
276        int i;
277        unsigned u;
278
279        if (!http_GetHdr(hp, H_Connection, &p)) {
280                if (strcmp(hp->hd[HTTP_HDR_PROTO].b, "HTTP/1.1"))
281                        sp->doclose = "not HTTP/1.1";
282                return;
283        }
284        for (; *p; p++) {
285                if (isspace(*p))
286                        continue;
287                if (*p == ',')
288                        continue;
289                for (q = p + 1; *q; q++)
290                        if (*q == ',' || isspace(*q))
291                                break;
292                i = q - p;
293                if (i == 5 && !strncasecmp(p, "close", i))
294                        sp->doclose = "Connection: close";
295                u = http_findhdr(hp, i, p);
296                if (u != 0)
297                        hp->hdf[u] |= HDF_FILTER;
298                if (!*q)
299                        break;
300                p = q;
301        }
302}
303
304/*--------------------------------------------------------------------*/
305
306int
307http_HdrIs(struct http *hp, const char *hdr, const char *val)
308{
309        char *p;
310
311        if (!http_GetHdr(hp, hdr, &p))
312                return (0);
313        AN(p);
314        if (!strcasecmp(p, val))
315                return (1);
316        return (0);
317}
318
319/*--------------------------------------------------------------------*/
320
321int
322http_GetTail(struct http *hp, unsigned len, char **b, char **e)
323{
324
325        if (hp->pl_s >= hp->pl_e)
326                return (0);
327
328        if (len == 0)
329                len = hp->pl_e - hp->pl_e;
330
331        if (hp->pl_s + len > hp->pl_e)
332                len = hp->pl_e - hp->pl_s;
333        if (len == 0)
334                return (0);
335        *b = hp->pl_s;
336        *e = hp->pl_s + len;
337        hp->pl_s += len;
338        assert(hp->pl_s <= hp->pl_e);
339        return (1);
340}
341
342/*--------------------------------------------------------------------*/
343/* Read from fd, but soak up any tail first */
344
345int
346http_Read(struct http *hp, int fd, void *p, unsigned len)
347{
348        int i;
349        int u;
350        char *b = p;
351
352        u = 0;
353        if (hp->pl_s < hp->pl_e) {
354                u = hp->pl_e - hp->pl_s;
355                if (u > len)
356                        u = len;
357                memcpy(b, hp->pl_s, u);
358                hp->pl_s += u;
359                b += u;
360                len -= u;
361        }
362        if (hp->pl_e == hp->pl_s)
363                hp->pl_s = hp->pl_e = NULL;
364        if (len > 0) {
365                i = read(fd, b, len);
366                if (i < 0)
367                        return (i);
368                u += i;
369        }
370        return (u);
371}
372
373/*--------------------------------------------------------------------*/
374
375int
376http_GetStatus(struct http *hp)
377{
378
379        AN(hp->hd[HTTP_HDR_STATUS].b);
380        return (strtoul(hp->hd[HTTP_HDR_STATUS].b,
381            NULL /* XXX */, 10));
382}
383
384/*--------------------------------------------------------------------
385 * Dissect the headers of the HTTP protocol message.
386 * Detect conditionals (headers which start with '^[Ii][Ff]-')
387 */
388
389static int
390http_dissect_hdrs(struct worker *w, struct http *hp, int fd, char *p)
391{
392        char *q, *r;
393
394        if (*p == '\r')
395                p++;
396
397        hp->nhd = HTTP_HDR_FIRST;
398        hp->conds = 0;
399        r = NULL;               /* For FlexeLint */
400        assert(p < hp->rx_e);   /* http_header_complete() guarantees this */
401        for (; p < hp->rx_e; p = r) {
402                /* XXX: handle continuation lines */
403                q = strchr(p, '\n');
404                assert(q != NULL);
405                r = q + 1;
406                if (q > p && q[-1] == '\r')
407                        q--;
408                *q = '\0';
409                if (p == q)
410                        break;
411
412                if ((p[0] == 'i' || p[0] == 'I') &&
413                    (p[1] == 'f' || p[1] == 'F') &&
414                    p[2] == '-')
415                        hp->conds = 1;
416
417                if (hp->nhd < HTTP_HDR_MAX) {
418                        hp->hdf[hp->nhd] = 0;
419                        hp->hd[hp->nhd].b = p;
420                        hp->hd[hp->nhd].e = q;
421                        WSLH(w, HTTP_T_Header, fd, hp, hp->nhd);
422                        hp->nhd++;
423                } else {
424                        VSL_stats->losthdr++;
425                        WSLR(w, SLT_LostHeader, fd, p, q);
426                }
427        }
428        return (0);
429}
430
431/*--------------------------------------------------------------------*/
432
433int
434http_DissectRequest(struct worker *w, struct http *hp, int fd)
435{
436        char *p;
437
438        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
439        /* Assert a NUL at rx_e */
440        assert(hp->rx_s < hp->rx_e);
441        hp->logtag = HTTP_Rx;
442
443        for (p = hp->rx_s ; isspace(*p); p++)
444                continue;
445
446        /* First, the request type (GET/HEAD etc) */
447        hp->hd[HTTP_HDR_REQ].b = p;
448        for (; isalpha(*p); p++)
449                ;
450        hp->hd[HTTP_HDR_REQ].e = p;
451        WSLH(w, HTTP_T_Request, fd, hp, HTTP_HDR_REQ);
452        *p++ = '\0';
453
454        /* Next find the URI */
455        while (isspace(*p) && *p != '\n')
456                p++;
457        if (*p == '\n') {
458                WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
459                return (400);
460        }
461        hp->hd[HTTP_HDR_URL].b = p;
462        while (!isspace(*p))
463                p++;
464        hp->hd[HTTP_HDR_URL].e = p;
465        WSLH(w, HTTP_T_URL, fd, hp, HTTP_HDR_URL);
466        if (*p == '\n') {
467                WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
468                return (400);
469        }
470        *p++ = '\0';
471
472        /* Finally, look for protocol */
473        while (isspace(*p) && *p != '\n')
474                p++;
475        if (*p == '\n') {
476                WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
477                return (400);
478        }
479        hp->hd[HTTP_HDR_PROTO].b = p;
480        while (!isspace(*p))
481                p++;
482        hp->hd[HTTP_HDR_PROTO].e = p;
483        WSLH(w, HTTP_T_Protocol, fd, hp, HTTP_HDR_PROTO);
484        if (*p != '\n')
485                *p++ = '\0';
486        while (isspace(*p) && *p != '\n')
487                p++;
488        if (*p != '\n') {
489                WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
490                return (400);
491        }
492        *p++ = '\0';
493
494        return (http_dissect_hdrs(w, hp, fd, p));
495}
496
497/*--------------------------------------------------------------------*/
498
499int
500http_DissectResponse(struct worker *w, struct http *hp, int fd)
501{
502        char *p, *q;
503
504        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
505        /* Assert a NUL at rx_e */
506        assert(hp->rx_s < hp->rx_e);
507        hp->logtag = HTTP_Rx;
508
509        for (p = hp->rx_s ; isspace(*p); p++)
510                continue;
511
512        if (memcmp(p, "HTTP/1.", 7)) {
513                WSLR(w, SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
514                return (400);
515        }
516        /* First, protocol */
517        hp->hd[HTTP_HDR_PROTO].b = p;
518        while (!isspace(*p))
519                p++;
520        hp->hd[HTTP_HDR_PROTO].e = p;
521        WSLH(w, HTTP_T_Protocol, fd, hp, HTTP_HDR_PROTO);
522        *p++ = '\0';
523
524        /* Next find the status */
525        while (isspace(*p))
526                p++;
527        hp->hd[HTTP_HDR_STATUS].b = p;
528        while (!isspace(*p))
529                p++;
530        hp->hd[HTTP_HDR_STATUS].e = p;
531        WSLH(w, HTTP_T_Status, fd, hp, HTTP_HDR_STATUS);
532        *p++ = '\0';
533
534        /* Next find the response */
535        while (isspace(*p))
536                p++;
537        hp->hd[HTTP_HDR_RESPONSE].b = p;
538        while (*p != '\n')
539                p++;
540        for (q = p; q > hp->hd[HTTP_HDR_RESPONSE].b &&
541            isspace(q[-1]); q--)
542                continue;
543        *q = '\0';
544        hp->hd[HTTP_HDR_RESPONSE].e = q;
545        WSLH(w, HTTP_T_Response, fd, hp, HTTP_HDR_RESPONSE);
546        p++;
547
548        return (http_dissect_hdrs(w, hp, fd, p));
549}
550
551/*--------------------------------------------------------------------
552 * Return nonzero if we have a complete HTTP request.
553 */
554
555static int
556http_header_complete(struct http *hp)
557{
558        char *p;
559
560        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
561        assert(*hp->rx_e == '\0');
562        /* Skip any leading white space */
563        for (p = hp->rx_s ; p < hp->rx_e && isspace(*p); p++)
564                continue;
565        if (p >= hp->rx_e) {
566                hp->rx_e = hp->rx_s;
567                return (0);
568        }
569        while (1) {
570                /* XXX: we could save location of all linebreaks for later */
571                p = strchr(p, '\n');
572                if (p == NULL)
573                        return (0);     /* XXX: Could cache p */
574                p++;
575                if (*p == '\r')
576                        p++;
577                if (*p == '\n')
578                        break;
579        }
580        p++;
581        WS_ReleaseP(hp->ws, hp->rx_e);
582        if (p != hp->rx_e) {
583                hp->pl_s = p;
584                hp->pl_e = hp->rx_e;
585                hp->rx_e = p;
586        }
587        /* XXX: Check this stuff... */
588        return (1);
589}
590
591/*--------------------------------------------------------------------*/
592
593void
594http_RecvPrep(struct http *hp)
595{
596        unsigned l;
597
598        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
599        WS_Assert(hp->ws);
600        WS_Reset(hp->ws);
601        WS_Reserve(hp->ws, 0);
602        hp->rx_s = hp->ws->f;
603        hp->rx_e = hp->rx_s;
604        if (hp->pl_s != NULL) {
605                assert(hp->pl_s < hp->pl_e);
606                l = hp->pl_e - hp->pl_s;
607                memmove(hp->rx_s, hp->pl_s, l);
608                hp->rx_e = hp->rx_s + l;
609                hp->pl_s = hp->pl_e = NULL;
610        }
611        *hp->rx_e = '\0';
612}
613
614int
615http_RecvPrepAgain(struct http *hp)
616{
617        http_RecvPrep(hp);
618        if (hp->rx_s == hp->rx_e)
619                return (0);
620        return (http_header_complete(hp));
621}
622
623/*--------------------------------------------------------------------*/
624
625int
626http_RecvSome(int fd, struct http *hp)
627{
628        unsigned l;
629        int i;
630
631        l = (hp->ws->e - hp->rx_e) - 1;
632        l /= 2;         /* Don't fill all of workspace with read-ahead */
633        if (l <= 1) {
634                VSL(SLT_HttpError, fd, "Received too much");
635                VSLR(SLT_HttpGarbage, fd, hp->rx_s, hp->rx_e);
636                hp->rx_s = hp->rx_e = NULL;
637                WS_Release(hp->ws, 0);
638                return (1);
639        }
640        errno = 0;
641        i = read(fd, hp->rx_e, l - 1);
642        if (i > 0) {
643                hp->rx_e += i;
644                *hp->rx_e = '\0';
645                if (http_header_complete(hp))
646                        return(0);
647                return (-1);
648        }
649
650        if (hp->rx_e != hp->rx_s) {
651                VSL(SLT_HttpError, fd,
652                    "Received (only) %d bytes, errno %d",
653                    hp->rx_e - hp->rx_s, errno);
654                VSLR(SLT_Debug, fd, hp->rx_s, hp->rx_e);
655        } else if (errno == 0)
656                VSL(SLT_HttpError, fd, "Received nothing");
657        else
658                VSL(SLT_HttpError, fd, "Received errno %d", errno);
659        hp->rx_s = hp->rx_e = NULL;
660        WS_Release(hp->ws, 0);
661        return(2);
662}
663
664/*--------------------------------------------------------------------*/
665
666int
667http_RecvHead(struct http *hp, int fd)
668{
669        int i;
670
671        CHECK_OBJ_NOTNULL(hp, HTTP_MAGIC);
672        http_RecvPrep(hp);
673        do
674                i = http_RecvSome(fd, hp);
675        while (i == -1);
676        return (i);
677}
678
679/*--------------------------------------------------------------------*/
680
681void
682http_SetH(struct http *to, unsigned n, const char *fm)
683{
684
685        assert(n < HTTP_HDR_MAX);
686        AN(fm);
687        to->hd[n].b = (void*)(uintptr_t)fm;
688        to->hd[n].e = (void*)(uintptr_t)strchr(fm, '\0');
689        to->hdf[n] = 0;
690}
691
692static void
693http_copyh(struct http *to, struct http *fm, unsigned n)
694{
695
696        assert(n < HTTP_HDR_MAX);
697        AN(fm->hd[n].b);
698        to->hd[n].b = fm->hd[n].b;
699        to->hd[n].e = fm->hd[n].e;
700        to->hdf[n] = fm->hdf[n];
701}
702
703static void
704http_copyreq(struct http *to, struct http *fm, int forceget)
705{
706
707        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
708        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
709        if (forceget)
710                http_SetH(to, HTTP_HDR_REQ, "GET");
711        else
712                http_copyh(to, fm, HTTP_HDR_REQ);
713        http_copyh(to, fm, HTTP_HDR_URL);
714        http_SetH(to, HTTP_HDR_PROTO, "HTTP/1.1");
715}
716
717void
718http_CopyResp(struct http *to, struct http *fm)
719{
720
721        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
722        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
723        if (params->client_http11)
724                http_SetH(to, HTTP_HDR_PROTO, "HTTP/1.1");
725        else
726                http_copyh(to, fm, HTTP_HDR_PROTO);
727        http_copyh(to, fm, HTTP_HDR_STATUS);
728        http_copyh(to, fm, HTTP_HDR_RESPONSE);
729}
730
731void
732http_SetResp(struct http *to, const char *proto, const char *status, const char *response)
733{
734
735        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
736        http_SetH(to, HTTP_HDR_PROTO, proto);
737        http_SetH(to, HTTP_HDR_STATUS, status);
738        http_SetH(to, HTTP_HDR_RESPONSE, response);
739}
740
741static void
742http_copyheader(struct worker *w, int fd, struct http *to, struct http *fm, unsigned n)
743{
744
745        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
746        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
747        assert(n < HTTP_HDR_MAX);
748        AN(fm->hd[n].b);
749        if (to->nhd < HTTP_HDR_MAX) {
750                to->hd[to->nhd].b = fm->hd[n].b;
751                to->hd[to->nhd].e = fm->hd[n].e;
752                to->nhd++;
753        } else  {
754                VSL_stats->losthdr++;
755                WSLH(w, SLT_LostHeader, fd, fm, n);
756        }
757}
758
759/*--------------------------------------------------------------------*/
760
761void
762http_FilterFields(struct worker *w, int fd, struct http *to, struct http *fm, unsigned how)
763{
764        unsigned u;
765
766        CHECK_OBJ_NOTNULL(fm, HTTP_MAGIC);
767        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
768        to->nhd = HTTP_HDR_FIRST;
769        for (u = HTTP_HDR_FIRST; u < fm->nhd; u++) {
770                if (fm->hdf[u] & HDF_FILTER)
771                        continue;
772#define HTTPH(a, b, c, d, e, f, g) \
773                if (((e) & how) && http_IsHdr(&fm->hd[u], (b))) \
774                        continue;
775#include "http_headers.h"
776#undef HTTPH
777                http_copyheader(w, fd, to, fm, u);
778        }
779}
780
781/*--------------------------------------------------------------------*/
782
783void
784http_FilterHeader(struct sess *sp, unsigned how)
785{
786        struct bereq *bereq;
787        struct http *hp;
788        char *b;
789
790        bereq = vbe_new_bereq();
791        AN(bereq);
792        hp = bereq->http;
793        hp->logtag = HTTP_Tx;
794
795        http_copyreq(hp, sp->http, how != HTTPH_R_PIPE);
796        http_FilterFields(sp->wrk, sp->fd, hp, sp->http, how);
797        http_PrintfHeader(sp->wrk, sp->fd, hp, "X-Varnish: %u", sp->xid);
798        http_PrintfHeader(sp->wrk, sp->fd, hp,
799            "X-Forwarded-for: %s", sp->addr);
800        if (!http_GetHdr(hp, H_Host, &b)) {
801                http_PrintfHeader(sp->wrk, sp->fd, hp, "Host: %s",
802                    sp->backend->hostname);
803        }
804        sp->bereq = bereq;
805}
806
807/*--------------------------------------------------------------------
808 * This function copies any header fields which reference foreign
809 * storage into our own WS.
810 */
811
812void
813http_CopyHome(struct worker *w, int fd, struct http *hp)
814{
815        unsigned u, l;
816        enum httptag htt;
817        char *p;
818
819        for (u = 0; u < hp->nhd; u++) {
820                if (hp->hd[u].b == NULL)
821                        continue;
822                switch (u) {
823                case HTTP_HDR_PROTO:
824                        htt = HTTP_T_Protocol;
825                        break;
826                case HTTP_HDR_STATUS:
827                        htt = HTTP_T_Status;
828                        break;
829                case HTTP_HDR_RESPONSE:
830                        htt = HTTP_T_Response;
831                        break;
832                default:
833                        htt = HTTP_T_Header;
834                        break;
835                }
836                if (hp->hd[u].b >= hp->ws->s && hp->hd[u].e <= hp->ws->e) {
837                        WSLH(w, htt, fd, hp, u);
838                        continue;
839                }
840                l = hp->hd[u].e - hp->hd[u].b;
841                p = WS_Alloc(hp->ws, l + 1);
842                if (p != NULL) {
843                        WSLH(w, htt, fd, hp, u);
844                        memcpy(p, hp->hd[u].b, l + 1);
845                        hp->hd[u].b = p;
846                        hp->hd[u].e = p + l;
847                } else {
848                        WSLH(w, SLT_LostHeader, fd, hp, u);
849                        hp->hd[u].b = NULL;
850                        hp->hd[u].e = NULL;
851                }
852        }
853}
854
855/*--------------------------------------------------------------------*/
856
857void
858http_ClrHeader(struct http *to)
859{
860
861        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
862        /* XXX: don't to->f = to->v;  it would kill pipelining */
863        to->nhd = HTTP_HDR_FIRST;
864        memset(to->hd, 0, sizeof to->hd);
865}
866
867/*--------------------------------------------------------------------*/
868
869void
870http_SetHeader(struct worker *w, int fd, struct http *to, const char *hdr)
871{
872
873        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
874        if (to->nhd >= HTTP_HDR_MAX) {
875                VSL_stats->losthdr++;
876                WSL(w, SLT_LostHeader, fd, "%s", hdr);
877                return;
878        }
879        http_SetH(to, to->nhd++, hdr);
880}
881
882/*--------------------------------------------------------------------*/
883
884static void
885http_PutField(struct worker *w, int fd, struct http *to, int field, const char *string)
886{
887        char *p;
888        int l;
889
890        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
891        l = strlen(string);
892        p = WS_Alloc(to->ws, l + 1);
893        if (p == NULL) {
894                WSL(w, SLT_LostHeader, fd, "%s", string);
895                to->hd[field].b = NULL;
896                to->hd[field].e = NULL;
897        } else {
898                memcpy(p, string, l + 1);
899                to->hd[field].b = p;
900                to->hd[field].e = p + l;
901        }
902}
903
904void
905http_PutProtocol(struct worker *w, int fd, struct http *to, const char *protocol)
906{
907
908        http_PutField(w, fd, to, HTTP_HDR_PROTO, protocol);
909}
910
911void
912http_PutStatus(struct worker *w, int fd, struct http *to, int status)
913{
914        char stat[4];
915
916        assert(status >= 0 && status <= 999);
917        sprintf(stat, "%d", status);
918        http_PutField(w, fd, to, HTTP_HDR_STATUS, stat);
919}
920
921void
922http_PutResponse(struct worker *w, int fd, struct http *to, const char *response)
923{
924
925        http_PutField(w, fd, to, HTTP_HDR_RESPONSE, response);
926}
927
928void
929http_PrintfHeader(struct worker *w, int fd, struct http *to, const char *fmt, ...)
930{
931        va_list ap;
932        unsigned l, n;
933
934        CHECK_OBJ_NOTNULL(to, HTTP_MAGIC);
935        l = WS_Reserve(to->ws, 0);
936        va_start(ap, fmt);
937        n = vsnprintf(to->ws->f, l, fmt, ap);
938        va_end(ap);
939        if (n + 1 >= l || to->nhd >= HTTP_HDR_MAX) {
940                VSL_stats->losthdr++;
941                WSL(w, SLT_LostHeader, fd, "%s", to->ws->f);
942                WS_Release(to->ws, 0);
943        } else {
944                to->hd[to->nhd].b = to->ws->f;
945                to->hd[to->nhd].e = to->ws->f + n;
946                WS_Release(to->ws, n + 1);
947                to->nhd++;
948        }
949}
950/*--------------------------------------------------------------------*/
951
952void
953http_Unset(struct http *hp, const char *hdr)
954{
955        unsigned u, v;
956
957        for (v = u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
958                if (http_IsHdr(&hp->hd[u], hdr)) 
959                        continue;
960                if (v != u)
961                        memcpy(&hp->hd[v], &hp->hd[u], sizeof hp->hd[v]);
962                v++;
963        }
964        hp->nhd = v;
965}
966
967/*--------------------------------------------------------------------*/
968
969unsigned
970http_Write(struct worker *w, struct http *hp, int resp)
971{
972        unsigned u, l;
973
974        if (resp) {
975                AN(hp->hd[HTTP_HDR_STATUS].b);
976                l = WRK_WriteH(w, &hp->hd[HTTP_HDR_PROTO], " ");
977                WSLH(w, HTTP_T_Protocol, *w->wfd, hp, HTTP_HDR_PROTO);
978                l += WRK_WriteH(w, &hp->hd[HTTP_HDR_STATUS], " ");
979                WSLH(w, HTTP_T_Status, *w->wfd, hp, HTTP_HDR_STATUS);
980                l += WRK_WriteH(w, &hp->hd[HTTP_HDR_RESPONSE], "\r\n");
981                WSLH(w, HTTP_T_Response, *w->wfd, hp, HTTP_HDR_RESPONSE);
982        } else {
983                AN(hp->hd[HTTP_HDR_URL].b);
984                l = WRK_WriteH(w, &hp->hd[HTTP_HDR_REQ], " ");
985                WSLH(w, HTTP_T_Request, *w->wfd, hp, HTTP_HDR_REQ);
986                l += WRK_WriteH(w, &hp->hd[HTTP_HDR_URL], " ");
987                WSLH(w, HTTP_T_URL, *w->wfd, hp, HTTP_HDR_URL);
988                l += WRK_WriteH(w, &hp->hd[HTTP_HDR_PROTO], "\r\n");
989                WSLH(w, HTTP_T_Protocol, *w->wfd, hp, HTTP_HDR_PROTO);
990        }
991        for (u = HTTP_HDR_FIRST; u < hp->nhd; u++) {
992                AN(hp->hd[u].b);
993                AN(hp->hd[u].e);
994                l += WRK_WriteH(w, &hp->hd[u], "\r\n");
995                WSLH(w, HTTP_T_Header, *w->wfd, hp, u);
996        }
997        l += WRK_Write(w, "\r\n", -1);
998        return (l);
999}
1000
1001/*--------------------------------------------------------------------*/
1002
1003void
1004HTTP_Init(void)
1005{
1006#define HTTPH(a, b, c, d, e, f, g) b[0] = (char)strlen(b + 1);
1007#include "http_headers.h"
1008#undef HTTPH
1009}
Note: See TracBrowser for help on using the repository browser.