]> git.ipfire.org Git - thirdparty/squid.git/blame_incremental - src/http.cc
Adding a comment that tests/testUfs will fail when 'heap' is the only
[thirdparty/squid.git] / src / http.cc
... / ...
CommitLineData
1
2/*
3 * $Id: http.cc,v 1.516 2007/04/24 23:13:25 wessels Exp $
4 *
5 * DEBUG: section 11 Hypertext Transfer Protocol (HTTP)
6 * AUTHOR: Harvest Derived
7 *
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
10 *
11 * Squid is the result of efforts by numerous individuals from
12 * the Internet community; see the CONTRIBUTORS file for full
13 * details. Many organizations have provided support for Squid's
14 * development; see the SPONSORS file for full details. Squid is
15 * Copyrighted (C) 2001 by the Regents of the University of
16 * California; see the COPYRIGHT file for full details. Squid
17 * incorporates software developed and/or copyrighted by other
18 * sources; see the CREDITS file for full details.
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 */
35
36/*
37 * Anonymizing patch by lutz@as-node.jena.thur.de
38 * have a look into http-anon.c to get more informations.
39 */
40
41#include "squid.h"
42#include "errorpage.h"
43#include "MemBuf.h"
44#include "http.h"
45#include "AuthUserRequest.h"
46#include "Store.h"
47#include "HttpReply.h"
48#include "HttpRequest.h"
49#include "MemObject.h"
50#include "HttpHdrContRange.h"
51#include "HttpHdrSc.h"
52#include "HttpHdrScTarget.h"
53#include "ACLChecklist.h"
54#include "fde.h"
55#if DELAY_POOLS
56#include "DelayPools.h"
57#endif
58#if ICAP_CLIENT
59#include "ICAP/ICAPConfig.h"
60extern ICAPConfig TheICAPConfig;
61#endif
62#include "SquidTime.h"
63
64CBDATA_CLASS_INIT(HttpStateData);
65
66static const char *const crlf = "\r\n";
67
68static PF httpStateFree;
69static PF httpTimeout;
70static void httpMaybeRemovePublic(StoreEntry *, http_status);
71static void copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, String strConnection, HttpRequest * request, HttpRequest * orig_request,
72 HttpHeader * hdr_out, int we_do_ranges, http_state_flags);
73#if ICAP_CLIENT
74static void icapAclCheckDoneWrapper(ICAPServiceRep::Pointer service, void *data);
75#endif
76
77HttpStateData::HttpStateData(FwdState *theFwdState) : ServerStateData(theFwdState),
78 header_bytes_read(0), reply_bytes_read(0)
79{
80 debugs(11,5,HERE << "HttpStateData " << this << " created");
81 ignoreCacheControl = false;
82 surrogateNoStore = false;
83 fd = fwd->server_fd;
84 readBuf = new MemBuf;
85 readBuf->init(4096, SQUID_TCP_SO_RCVBUF);
86 orig_request = HTTPMSGLOCK(fwd->request);
87
88 if (fwd->servers)
89 _peer = fwd->servers->_peer; /* might be NULL */
90
91 if (_peer) {
92 const char *url;
93
94 if (_peer->options.originserver)
95 url = orig_request->urlpath.buf();
96 else
97 url = entry->url();
98
99 HttpRequest * proxy_req = new HttpRequest(orig_request->method,
100 orig_request->protocol, url);
101
102 xstrncpy(proxy_req->host, _peer->host, SQUIDHOSTNAMELEN);
103
104 proxy_req->port = _peer->http_port;
105
106 proxy_req->flags = orig_request->flags;
107
108 proxy_req->lastmod = orig_request->lastmod;
109
110 proxy_req->flags.proxying = 1;
111
112 HTTPMSGUNLOCK(request);
113
114 request = HTTPMSGLOCK(proxy_req);
115
116 /*
117 * This NEIGHBOR_PROXY_ONLY check probably shouldn't be here.
118 * We might end up getting the object from somewhere else if,
119 * for example, the request to this neighbor fails.
120 */
121 if (_peer->options.proxy_only)
122 entry->releaseRequest();
123
124#if DELAY_POOLS
125
126 entry->setNoDelay(_peer->options.no_delay);
127
128#endif
129
130 }
131
132 /*
133 * register the handler to free HTTP state data when the FD closes
134 */
135 comm_add_close_handler(fd, httpStateFree, this);
136}
137
138HttpStateData::~HttpStateData()
139{
140 /*
141 * don't forget that ~ServerStateData() gets called automatically
142 */
143
144 if (!readBuf->isNull())
145 readBuf->clean();
146
147 delete readBuf;
148
149 HTTPMSGUNLOCK(orig_request);
150
151 debugs(11,5, HERE << "HttpStateData " << this << " destroyed; FD " << fd);
152}
153
154int
155HttpStateData::dataDescriptor() const
156{
157 return fd;
158}
159
160static void
161httpStateFree(int fd, void *data)
162{
163 HttpStateData *httpState = static_cast<HttpStateData *>(data);
164 debug(11,5)("httpStateFree: FD %d, httpState=%p\n", fd, data);
165 delete httpState;
166}
167
168int
169httpCachable(method_t method)
170{
171 /* GET and HEAD are cachable. Others are not. */
172
173 if (method != METHOD_GET && method != METHOD_HEAD)
174 return 0;
175
176 /* else cachable */
177 return 1;
178}
179
180static void
181httpTimeout(int fd, void *data)
182{
183 HttpStateData *httpState = static_cast<HttpStateData *>(data);
184 StoreEntry *entry = httpState->entry;
185 debug(11, 4) ("httpTimeout: FD %d: '%s'\n", fd, entry->url());
186
187 if (entry->store_status == STORE_PENDING) {
188 httpState->fwd->fail(errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT, httpState->fwd->request));
189 }
190
191 comm_close(fd);
192}
193
194static void
195httpMaybeRemovePublic(StoreEntry * e, http_status status)
196{
197
198 int remove
199 = 0;
200
201 int forbidden = 0;
202
203 StoreEntry *pe;
204
205 if (!EBIT_TEST(e->flags, KEY_PRIVATE))
206 return;
207
208 switch (status) {
209
210 case HTTP_OK:
211
212 case HTTP_NON_AUTHORITATIVE_INFORMATION:
213
214 case HTTP_MULTIPLE_CHOICES:
215
216 case HTTP_MOVED_PERMANENTLY:
217
218 case HTTP_MOVED_TEMPORARILY:
219
220 case HTTP_GONE:
221
222 case HTTP_NOT_FOUND:
223
224 remove
225 = 1;
226
227 break;
228
229 case HTTP_FORBIDDEN:
230
231 case HTTP_METHOD_NOT_ALLOWED:
232 forbidden = 1;
233
234 break;
235
236#if WORK_IN_PROGRESS
237
238 case HTTP_UNAUTHORIZED:
239 forbidden = 1;
240
241 break;
242
243#endif
244
245 default:
246#if QUESTIONABLE
247 /*
248 * Any 2xx response should eject previously cached entities...
249 */
250
251 if (status >= 200 && status < 300)
252 remove
253 = 1;
254
255#endif
256
257 break;
258 }
259
260 if (!remove
261 && !forbidden)
262 return;
263
264 assert(e->mem_obj);
265
266 if (e->mem_obj->request)
267 pe = storeGetPublicByRequest(e->mem_obj->request);
268 else
269 pe = storeGetPublic(e->mem_obj->url, e->mem_obj->method);
270
271 if (pe != NULL) {
272 assert(e != pe);
273 pe->release();
274 }
275
276 /*
277 * Also remove any cached HEAD response in case the object has
278 * changed.
279 */
280 if (e->mem_obj->request)
281 pe = storeGetPublicByRequestMethod(e->mem_obj->request, METHOD_HEAD);
282 else
283 pe = storeGetPublic(e->mem_obj->url, METHOD_HEAD);
284
285 if (pe != NULL) {
286 assert(e != pe);
287 pe->release();
288 }
289
290 if (forbidden)
291 return;
292
293 switch (e->mem_obj->method) {
294
295 case METHOD_PUT:
296
297 case METHOD_DELETE:
298
299 case METHOD_PROPPATCH:
300
301 case METHOD_MKCOL:
302
303 case METHOD_MOVE:
304
305 case METHOD_BMOVE:
306
307 case METHOD_BDELETE:
308 /*
309 * Remove any cached GET object if it is beleived that the
310 * object may have changed as a result of other methods
311 */
312
313 if (e->mem_obj->request)
314 pe = storeGetPublicByRequestMethod(e->mem_obj->request, METHOD_GET);
315 else
316 pe = storeGetPublic(e->mem_obj->url, METHOD_GET);
317
318 if (pe != NULL) {
319 assert(e != pe);
320 pe->release();
321 }
322
323 break;
324
325 default:
326 /* Keep GCC happy. The methods above are all mutating HTTP methods
327 */
328 break;
329 }
330}
331
332void
333HttpStateData::processSurrogateControl(HttpReply *reply)
334{
335#if ESI
336
337 if (request->flags.accelerated && reply->surrogate_control) {
338 HttpHdrScTarget *sctusable =
339 httpHdrScGetMergedTarget(reply->surrogate_control,
340 Config.Accel.surrogate_id);
341
342 if (sctusable) {
343 if (EBIT_TEST(sctusable->mask, SC_NO_STORE) ||
344 (Config.onoff.surrogate_is_remote
345 && EBIT_TEST(sctusable->mask, SC_NO_STORE_REMOTE))) {
346 surrogateNoStore = true;
347 entry->makePrivate();
348 }
349
350 /* The HttpHeader logic cannot tell if the header it's parsing is a reply to an
351 * accelerated request or not...
352 * Still, this is an abtraction breach. - RC
353 */
354 if (sctusable->max_age != -1) {
355 if (sctusable->max_age < sctusable->max_stale)
356 reply->expires = reply->date + sctusable->max_age;
357 else
358 reply->expires = reply->date + sctusable->max_stale;
359
360 /* And update the timestamps */
361 entry->timestampsSet();
362 }
363
364 /* We ignore cache-control directives as per the Surrogate specification */
365 ignoreCacheControl = true;
366
367 httpHdrScTargetDestroy(sctusable);
368 }
369 }
370
371#endif
372}
373
374int
375HttpStateData::cacheableReply()
376{
377 HttpReply const *rep = getReply();
378 HttpHeader const *hdr = &rep->header;
379 const int cc_mask = (rep->cache_control) ? rep->cache_control->mask : 0;
380 const char *v;
381#if HTTP_VIOLATIONS
382
383 const refresh_t *R = NULL;
384
385 /* This strange looking define first looks up the refresh pattern
386 * and then checks if the specified flag is set. The main purpose
387 * of this is to simplify the refresh pattern lookup and HTTP_VIOLATIONS
388 * condition
389 */
390#define REFRESH_OVERRIDE(flag) \
391 ((R = (R ? R : refreshLimits(entry->mem_obj->url))) , \
392 (R && R->flags.flag))
393#else
394#define REFRESH_OVERRIDE(flag) 0
395#endif
396
397 if (surrogateNoStore)
398 return 0;
399
400 if (!ignoreCacheControl) {
401 if (EBIT_TEST(cc_mask, CC_PRIVATE)) {
402 if (!REFRESH_OVERRIDE(ignore_private))
403 return 0;
404 }
405
406 if (EBIT_TEST(cc_mask, CC_NO_CACHE)) {
407 if (!REFRESH_OVERRIDE(ignore_no_cache))
408 return 0;
409 }
410
411 if (EBIT_TEST(cc_mask, CC_NO_STORE)) {
412 if (!REFRESH_OVERRIDE(ignore_no_store))
413 return 0;
414 }
415 }
416
417 if (request->flags.auth) {
418 /*
419 * Responses to requests with authorization may be cached
420 * only if a Cache-Control: public reply header is present.
421 * RFC 2068, sec 14.9.4
422 */
423
424 if (!EBIT_TEST(cc_mask, CC_PUBLIC)) {
425 if (!REFRESH_OVERRIDE(ignore_auth))
426 return 0;
427 }
428 }
429
430 /* Pragma: no-cache in _replies_ is not documented in HTTP,
431 * but servers like "Active Imaging Webcast/2.0" sure do use it */
432 if (hdr->has(HDR_PRAGMA)) {
433 String s = hdr->getList(HDR_PRAGMA);
434 const int no_cache = strListIsMember(&s, "no-cache", ',');
435 s.clean();
436
437 if (no_cache) {
438 if (!REFRESH_OVERRIDE(ignore_no_cache))
439 return 0;
440 }
441 }
442
443 /*
444 * The "multipart/x-mixed-replace" content type is used for
445 * continuous push replies. These are generally dynamic and
446 * probably should not be cachable
447 */
448 if ((v = hdr->getStr(HDR_CONTENT_TYPE)))
449 if (!strncasecmp(v, "multipart/x-mixed-replace", 25))
450 return 0;
451
452 switch (getReply()->sline.status) {
453 /* Responses that are cacheable */
454
455 case HTTP_OK:
456
457 case HTTP_NON_AUTHORITATIVE_INFORMATION:
458
459 case HTTP_MULTIPLE_CHOICES:
460
461 case HTTP_MOVED_PERMANENTLY:
462
463 case HTTP_GONE:
464 /*
465 * Don't cache objects that need to be refreshed on next request,
466 * unless we know how to refresh it.
467 */
468
469 if (!refreshIsCachable(entry)) {
470 debug(22, 3) ("refreshIsCachable() returned non-cacheable..\n");
471 return 0;
472 }
473
474 /* don't cache objects from peers w/o LMT, Date, or Expires */
475 /* check that is it enough to check headers @?@ */
476 if (rep->date > -1)
477 return 1;
478 else if (rep->last_modified > -1)
479 return 1;
480 else if (!_peer)
481 return 1;
482
483 /* @?@ (here and 302): invalid expires header compiles to squid_curtime */
484 else if (rep->expires > -1)
485 return 1;
486 else
487 return 0;
488
489 /* NOTREACHED */
490 break;
491
492 /* Responses that only are cacheable if the server says so */
493
494 case HTTP_MOVED_TEMPORARILY:
495 if (rep->expires > rep->date && rep->date > 0)
496 return 1;
497 else
498 return 0;
499
500 /* NOTREACHED */
501 break;
502
503 /* Errors can be negatively cached */
504
505 case HTTP_NO_CONTENT:
506
507 case HTTP_USE_PROXY:
508
509 case HTTP_BAD_REQUEST:
510
511 case HTTP_FORBIDDEN:
512
513 case HTTP_NOT_FOUND:
514
515 case HTTP_METHOD_NOT_ALLOWED:
516
517 case HTTP_REQUEST_URI_TOO_LARGE:
518
519 case HTTP_INTERNAL_SERVER_ERROR:
520
521 case HTTP_NOT_IMPLEMENTED:
522
523 case HTTP_BAD_GATEWAY:
524
525 case HTTP_SERVICE_UNAVAILABLE:
526
527 case HTTP_GATEWAY_TIMEOUT:
528 return -1;
529
530 /* NOTREACHED */
531 break;
532
533 /* Some responses can never be cached */
534
535 case HTTP_PARTIAL_CONTENT: /* Not yet supported */
536
537 case HTTP_SEE_OTHER:
538
539 case HTTP_NOT_MODIFIED:
540
541 case HTTP_UNAUTHORIZED:
542
543 case HTTP_PROXY_AUTHENTICATION_REQUIRED:
544
545 case HTTP_INVALID_HEADER: /* Squid header parsing error */
546
547 case HTTP_HEADER_TOO_LARGE:
548
549 case HTTP_PAYMENT_REQUIRED:
550 case HTTP_NOT_ACCEPTABLE:
551 case HTTP_REQUEST_TIMEOUT:
552 case HTTP_CONFLICT:
553 case HTTP_LENGTH_REQUIRED:
554 case HTTP_PRECONDITION_FAILED:
555 case HTTP_REQUEST_ENTITY_TOO_LARGE:
556 case HTTP_UNSUPPORTED_MEDIA_TYPE:
557 case HTTP_UNPROCESSABLE_ENTITY:
558 case HTTP_LOCKED:
559 case HTTP_FAILED_DEPENDENCY:
560 case HTTP_INSUFFICIENT_STORAGE:
561
562 return 0;
563
564 default: /* Unknown status code */
565 debugs (11, 0, HERE << "HttpStateData::cacheableReply: unexpected http status code " << getReply()->sline.status);
566
567 return 0;
568
569 /* NOTREACHED */
570 break;
571 }
572
573 /* NOTREACHED */
574}
575
576/*
577 * For Vary, store the relevant request headers as
578 * virtual headers in the reply
579 * Returns false if the variance cannot be stored
580 */
581const char *
582httpMakeVaryMark(HttpRequest * request, HttpReply const * reply)
583{
584 String vary, hdr;
585 const char *pos = NULL;
586 const char *item;
587 const char *value;
588 int ilen;
589 static String vstr;
590
591 vstr.clean();
592 vary = reply->header.getList(HDR_VARY);
593
594 while (strListGetItem(&vary, ',', &item, &ilen, &pos)) {
595 char *name = (char *)xmalloc(ilen + 1);
596 xstrncpy(name, item, ilen + 1);
597 Tolower(name);
598
599 if (strcmp(name, "*") == 0) {
600 /* Can not handle "Vary: *" withtout ETag support */
601 safe_free(name);
602 vstr.clean();
603 break;
604 }
605
606 strListAdd(&vstr, name, ',');
607 hdr = request->header.getByName(name);
608 safe_free(name);
609 value = hdr.buf();
610
611 if (value) {
612 value = rfc1738_escape_part(value);
613 vstr.append("=\"", 2);
614 vstr.append(value);
615 vstr.append("\"", 1);
616 }
617
618 hdr.clean();
619 }
620
621 vary.clean();
622#if X_ACCELERATOR_VARY
623
624 pos = NULL;
625 vary = reply->header.getList(HDR_X_ACCELERATOR_VARY);
626
627 while (strListGetItem(&vary, ',', &item, &ilen, &pos)) {
628 char *name = (char *)xmalloc(ilen + 1);
629 xstrncpy(name, item, ilen + 1);
630 Tolower(name);
631 strListAdd(&vstr, name, ',');
632 hdr = request->header.getByName(name);
633 safe_free(name);
634 value = hdr.buf();
635
636 if (value) {
637 value = rfc1738_escape_part(value);
638 vstr.append("=\"", 2);
639 vstr.append(value);
640 vstr.append("\"", 1);
641 }
642
643 hdr.clean();
644 }
645
646 vary.clean();
647#endif
648
649 debug(11, 3) ("httpMakeVaryMark: %s\n", vstr.buf());
650 return vstr.buf();
651}
652
653void
654HttpStateData::failReply(HttpReply *reply, http_status const & status)
655{
656 reply->sline.version = HttpVersion(1, 0);
657 reply->sline.status = status;
658 entry->replaceHttpReply(reply);
659
660 if (eof == 1) {
661 serverComplete();
662 }
663}
664
665void
666HttpStateData::keepaliveAccounting(HttpReply *reply)
667{
668 if (flags.keepalive)
669 if (_peer)
670 _peer->stats.n_keepalives_sent++;
671
672 if (reply->keep_alive) {
673 if (_peer)
674 _peer->stats.n_keepalives_recv++;
675
676 if (Config.onoff.detect_broken_server_pconns && reply->bodySize(request->method) == -1) {
677 debug(11, 1) ("keepaliveAccounting: Impossible keep-alive header from '%s'\n", entry->url());
678 // debug(11, 2) ("GOT HTTP REPLY HDR:\n---------\n%s\n----------\n", readBuf->content());
679 flags.keepalive_broken = 1;
680 }
681 }
682}
683
684void
685HttpStateData::checkDateSkew(HttpReply *reply)
686{
687 if (reply->date > -1 && !_peer) {
688 int skew = abs((int)(reply->date - squid_curtime));
689
690 if (skew > 86400)
691 debug(11, 3) ("%s's clock is skewed by %d seconds!\n",
692 request->host, skew);
693 }
694}
695
696/*
697 * This creates the error page itself.. its likely
698 * that the forward ported reply header max size patch
699 * generates non http conformant error pages - in which
700 * case the errors where should be 'BAD_GATEWAY' etc
701 */
702void
703HttpStateData::processReplyHeader()
704{
705 /* Creates a blank header. If this routine is made incremental, this will
706 * not do
707 */
708 HttpReply *newrep = new HttpReply;
709 Ctx ctx = ctx_enter(entry->mem_obj->url);
710 debug(11, 3) ("processReplyHeader: key '%s'\n", entry->getMD5Text());
711
712 assert(!flags.headers_parsed);
713
714 http_status error = HTTP_STATUS_NONE;
715
716 const bool parsed = newrep->parse(readBuf, eof, &error);
717
718 if (!parsed && error > 0) { // unrecoverable parsing error
719 debugs(11, 3, "processReplyHeader: Non-HTTP-compliant header: '" << readBuf->content() << "'");
720 flags.headers_parsed = 1;
721 // negated result yields http_status
722 failReply (newrep, error);
723 ctx_exit(ctx);
724 return;
725 }
726
727 if (!parsed) { // need more data
728 assert(!error);
729 assert(!eof);
730 delete newrep;
731 ctx_exit(ctx);
732 return;
733 }
734
735 reply = HTTPMSGLOCK(newrep);
736
737 debug(11, 9) ("GOT HTTP REPLY HDR:\n---------\n%s\n----------\n",
738 readBuf->content());
739
740 header_bytes_read = headersEnd(readBuf->content(), readBuf->contentSize());
741 readBuf->consume(header_bytes_read);
742
743 flags.headers_parsed = 1;
744
745 keepaliveAccounting(reply);
746
747 checkDateSkew(reply);
748
749 processSurrogateControl (reply);
750
751 /* TODO: IF the reply is a 1.0 reply, AND it has a Connection: Header
752 * Parse the header and remove all referenced headers
753 */
754
755#if ICAP_CLIENT
756
757 if (TheICAPConfig.onoff) {
758 ICAPAccessCheck *icap_access_check =
759 new ICAPAccessCheck(ICAP::methodRespmod, ICAP::pointPreCache, request, reply, icapAclCheckDoneWrapper, this);
760
761 icapAccessCheckPending = true;
762 icap_access_check->check(); // will eventually delete self
763 ctx_exit(ctx);
764 return;
765 }
766
767#endif
768
769 entry->replaceHttpReply(reply);
770
771 haveParsedReplyHeaders();
772
773 if (eof == 1) {
774 serverComplete();
775 }
776
777 ctx_exit(ctx);
778}
779
780// Called when we parsed (and possibly adapted) the headers but
781// had not starting storing (a.k.a., sending) the body yet.
782void
783HttpStateData::haveParsedReplyHeaders()
784{
785 Ctx ctx = ctx_enter(entry->mem_obj->url);
786
787 if (getReply()->sline.status == HTTP_PARTIAL_CONTENT &&
788 getReply()->content_range)
789 currentOffset = getReply()->content_range->spec.offset;
790
791 entry->timestampsSet();
792
793 /* Check if object is cacheable or not based on reply code */
794 debug(11, 3) ("haveParsedReplyHeaders: HTTP CODE: %d\n", getReply()->sline.status);
795
796 if (neighbors_do_private_keys)
797 httpMaybeRemovePublic(entry, getReply()->sline.status);
798
799 if (getReply()->header.has(HDR_VARY)
800#if X_ACCELERATOR_VARY
801 || getReply()->header.has(HDR_X_ACCELERATOR_VARY)
802#endif
803 ) {
804 const char *vary = httpMakeVaryMark(orig_request, getReply());
805
806 if (!vary) {
807 entry->makePrivate();
808 goto no_cache;
809
810 }
811
812 entry->mem_obj->vary_headers = xstrdup(vary);
813 }
814
815#if WIP_FWD_LOG
816 fwdStatus(fwd, s);
817
818#endif
819 /*
820 * If its not a reply that we will re-forward, then
821 * allow the client to get it.
822 */
823 if (!fwd->reforwardableStatus(getReply()->sline.status))
824 EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
825
826 switch (cacheableReply()) {
827
828 case 1:
829 entry->makePublic();
830 break;
831
832 case 0:
833 entry->makePrivate();
834 break;
835
836 case -1:
837
838 if (Config.negativeTtl > 0)
839 entry->cacheNegatively();
840 else
841 entry->makePrivate();
842
843 break;
844
845 default:
846 assert(0);
847
848 break;
849 }
850
851no_cache:
852
853 if (!ignoreCacheControl && getReply()->cache_control) {
854 if (EBIT_TEST(getReply()->cache_control->mask, CC_PROXY_REVALIDATE))
855 EBIT_SET(entry->flags, ENTRY_REVALIDATE);
856 else if (EBIT_TEST(getReply()->cache_control->mask, CC_MUST_REVALIDATE))
857 EBIT_SET(entry->flags, ENTRY_REVALIDATE);
858 }
859
860#if HEADERS_LOG
861 headersLog(1, 0, request->method, getReply());
862
863#endif
864
865 ctx_exit(ctx);
866}
867
868HttpStateData::ConnectionStatus
869HttpStateData::statusIfComplete() const
870{
871 HttpReply const *rep = getReply();
872 /* If the reply wants to close the connection, it takes precedence */
873
874 if (httpHeaderHasConnDir(&rep->header, "close"))
875 return COMPLETE_NONPERSISTENT_MSG;
876
877 /* If we didn't send a keep-alive request header, then this
878 * can not be a persistent connection.
879 */
880 if (!flags.keepalive)
881 return COMPLETE_NONPERSISTENT_MSG;
882
883 /*
884 * If we haven't sent the whole request then this can not be a persistent
885 * connection.
886 */
887 if (!flags.request_sent) {
888 debug(11, 1) ("statusIfComplete: Request not yet fully sent \"%s %s\"\n",
889 RequestMethodStr[orig_request->method],
890 entry->url());
891 return COMPLETE_NONPERSISTENT_MSG;
892 }
893
894 /*
895 * What does the reply have to say about keep-alive?
896 */
897 /*
898 * XXX BUG?
899 * If the origin server (HTTP/1.0) does not send a keep-alive
900 * header, but keeps the connection open anyway, what happens?
901 * We'll return here and http.c waits for an EOF before changing
902 * store_status to STORE_OK. Combine this with ENTRY_FWD_HDR_WAIT
903 * and an error status code, and we might have to wait until
904 * the server times out the socket.
905 */
906 if (!rep->keep_alive)
907 return COMPLETE_NONPERSISTENT_MSG;
908
909 return COMPLETE_PERSISTENT_MSG;
910}
911
912HttpStateData::ConnectionStatus
913HttpStateData::persistentConnStatus() const
914{
915 debug(11, 3) ("persistentConnStatus: FD %d\n", fd);
916 debug(11, 5) ("persistentConnStatus: content_length=%d\n",
917 reply->content_length);
918
919 /* If we haven't seen the end of reply headers, we are not done */
920 debug(11,5)("persistentConnStatus: flags.headers_parsed=%d\n", flags.headers_parsed);
921
922 if (!flags.headers_parsed)
923 return INCOMPLETE_MSG;
924
925 const int clen = reply->bodySize(request->method);
926
927 debug(11,5)("persistentConnStatus: clen=%d\n", clen);
928
929 /* If the body size is unknown we must wait for EOF */
930 if (clen < 0)
931 return INCOMPLETE_MSG;
932
933 /* If the body size is known, we must wait until we've gotten all of it. */
934 if (clen > 0) {
935 // old technique:
936 // if (entry->mem_obj->endOffset() < reply->content_length + reply->hdr_sz)
937 const int body_bytes_read = reply_bytes_read - header_bytes_read;
938 debugs(11,5, "persistentConnStatus: body_bytes_read=" <<
939 body_bytes_read << " content_length=" << reply->content_length);
940
941 if (body_bytes_read < reply->content_length)
942 return INCOMPLETE_MSG;
943 }
944
945 /* If there is no message body or we got it all, we can be persistent */
946 return statusIfComplete();
947}
948
949/*
950 * This is the callback after some data has been read from the network
951 */
952void
953HttpStateData::ReadReplyWrapper(int fd, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
954{
955 HttpStateData *httpState = static_cast<HttpStateData *>(data);
956 assert (fd == httpState->fd);
957 // assert(buf == readBuf->content());
958 PROF_start(HttpStateData_readReply);
959 httpState->readReply (len, flag, xerrno);
960 PROF_stop(HttpStateData_readReply);
961}
962
963/* XXX this function is too long! */
964void
965HttpStateData::readReply (size_t len, comm_err_t flag, int xerrno)
966{
967 int bin;
968 int clen;
969 flags.do_next_read = 0;
970
971 /*
972 * Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us
973 */
974
975 if (flag == COMM_ERR_CLOSING) {
976 debug (11,3)("http socket closing\n");
977 return;
978 }
979
980 if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
981 maybeReadVirginBody();
982 return;
983 }
984
985 errno = 0;
986 /* prepare the read size for the next read (if any) */
987
988 debug(11, 5) ("httpReadReply: FD %d: len %d.\n", fd, (int)len);
989
990 if (flag == COMM_OK && len > 0) {
991 readBuf->appended(len);
992 reply_bytes_read += len;
993#if DELAY_POOLS
994
995 DelayId delayId = entry->mem_obj->mostBytesAllowed();
996 delayId.bytesIn(len);
997#endif
998
999 kb_incr(&statCounter.server.all.kbytes_in, len);
1000 kb_incr(&statCounter.server.http.kbytes_in, len);
1001 IOStats.Http.reads++;
1002
1003 for (clen = len - 1, bin = 0; clen; bin++)
1004 clen >>= 1;
1005
1006 IOStats.Http.read_hist[bin]++;
1007 }
1008
1009 /* here the RFC says we should ignore whitespace between replies, but we can't as
1010 * doing so breaks HTTP/0.9 replies beginning with witespace, and in addition
1011 * the response splitting countermeasures is extremely likely to trigger on this,
1012 * not allowing connection reuse in the first place.
1013 */
1014#if DONT_DO_THIS
1015 if (!flags.headers_parsed && flag == COMM_OK && len > 0 && fd_table[fd].uses > 1) {
1016 /* Skip whitespace between replies */
1017
1018 while (len > 0 && xisspace(*buf))
1019 xmemmove(buf, buf + 1, len--);
1020
1021 if (len == 0) {
1022 /* Continue to read... */
1023 /* Timeout NOT increased. This whitespace was from previous reply */
1024 flags.do_next_read = 1;
1025 maybeReadVirginBody();
1026 return;
1027 }
1028 }
1029
1030#endif
1031
1032 if (flag != COMM_OK || len < 0) {
1033 debug(50, 2) ("httpReadReply: FD %d: read failure: %s.\n",
1034 fd, xstrerror());
1035
1036 if (ignoreErrno(errno)) {
1037 flags.do_next_read = 1;
1038 } else {
1039 ErrorState *err;
1040 err = errorCon(ERR_READ_ERROR, HTTP_BAD_GATEWAY, fwd->request);
1041 err->xerrno = errno;
1042 fwd->fail(err);
1043 flags.do_next_read = 0;
1044 comm_close(fd);
1045 }
1046 } else if (flag == COMM_OK && len == 0 && !flags.headers_parsed) {
1047 fwd->fail(errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_BAD_GATEWAY, fwd->request));
1048 eof = 1;
1049 flags.do_next_read = 0;
1050 comm_close(fd);
1051 } else if (flag == COMM_OK && len == 0) {
1052 /* Connection closed; retrieval done. */
1053 eof = 1;
1054
1055 if (!flags.headers_parsed) {
1056 /*
1057 * When we called processReplyHeader() before, we
1058 * didn't find the end of headers, but now we are
1059 * definately at EOF, so we want to process the reply
1060 * headers.
1061 */
1062 PROF_start(HttpStateData_processReplyHeader);
1063 processReplyHeader();
1064 PROF_stop(HttpStateData_processReplyHeader);
1065 } else if (getReply()->sline.status == HTTP_INVALID_HEADER && HttpVersion(0,9) != getReply()->sline.version) {
1066 fwd->fail(errorCon(ERR_INVALID_RESP, HTTP_BAD_GATEWAY, fwd->request));
1067 flags.do_next_read = 0;
1068 } else {
1069 if (entry->mem_obj->getReply()->sline.status == HTTP_HEADER_TOO_LARGE) {
1070 entry->reset();
1071 fwd->fail( errorCon(ERR_TOO_BIG, HTTP_BAD_GATEWAY, fwd->request));
1072 fwd->dontRetry(true);
1073 flags.do_next_read = 0;
1074 comm_close(fd);
1075 } else {
1076 serverComplete();
1077 }
1078 }
1079 } else {
1080 if (!flags.headers_parsed) {
1081 PROF_start(HttpStateData_processReplyHeader);
1082 processReplyHeader();
1083 PROF_stop(HttpStateData_processReplyHeader);
1084
1085 if (flags.headers_parsed) {
1086 bool fail = reply == NULL;
1087
1088 if (!fail) {
1089 http_status s = getReply()->sline.status;
1090 HttpVersion httpver = getReply()->sline.version;
1091 fail = s == HTTP_INVALID_HEADER && httpver != HttpVersion(0,9);
1092 }
1093
1094 if (fail) {
1095 entry->reset();
1096 fwd->fail( errorCon(ERR_INVALID_RESP, HTTP_BAD_GATEWAY, fwd->request));
1097 comm_close(fd);
1098 return;
1099 }
1100
1101 }
1102 }
1103
1104 PROF_start(HttpStateData_processReplyBody);
1105 processReplyBody();
1106 PROF_stop(HttpStateData_processReplyBody);
1107 }
1108}
1109
1110/*
1111 * Call this when there is data from the origin server
1112 * which should be sent to either StoreEntry, or to ICAP...
1113 */
1114void
1115HttpStateData::writeReplyBody()
1116{
1117 const char *data = readBuf->content();
1118 int len = readBuf->contentSize();
1119
1120#if ICAP_CLIENT
1121
1122 if (virginBodyDestination != NULL) {
1123 const size_t putSize = virginBodyDestination->putMoreData(data, len);
1124 readBuf->consume(putSize);
1125 return;
1126 }
1127
1128 // Even if we are done with sending the virgin body to ICAP, we may still
1129 // be waiting for adapted headers. We need them before writing to store.
1130 if (adaptedHeadSource != NULL) {
1131 debugs(11,5, HERE << "need adapted head from " << adaptedHeadSource);
1132 return;
1133 }
1134
1135#endif
1136
1137 entry->write (StoreIOBuffer(len, currentOffset, (char*)data));
1138
1139 readBuf->consume(len);
1140
1141 currentOffset += len;
1142}
1143
1144/*
1145 * processReplyBody has two purposes:
1146 * 1 - take the reply body data, if any, and put it into either
1147 * the StoreEntry, or give it over to ICAP.
1148 * 2 - see if we made it to the end of the response (persistent
1149 * connections and such)
1150 */
1151void
1152HttpStateData::processReplyBody()
1153{
1154
1155 struct IN_ADDR *client_addr = NULL;
1156
1157 if (!flags.headers_parsed) {
1158 flags.do_next_read = 1;
1159 maybeReadVirginBody();
1160 return;
1161 }
1162
1163#if ICAP_CLIENT
1164 if (icapAccessCheckPending)
1165 return;
1166
1167#endif
1168
1169 /*
1170 * At this point the reply headers have been parsed and consumed.
1171 * That means header content has been removed from readBuf and
1172 * it contains only body data.
1173 */
1174 writeReplyBody();
1175
1176 if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
1177 /*
1178 * the above writeReplyBody() call could ABORT this entry,
1179 * in that case, the server FD should already be closed.
1180 * there's nothing for us to do.
1181 */
1182 (void) 0;
1183 } else
1184 switch (persistentConnStatus()) {
1185
1186 case INCOMPLETE_MSG:
1187 debug(11,5)("processReplyBody: INCOMPLETE_MSG\n");
1188 /* Wait for more data or EOF condition */
1189
1190 if (flags.keepalive_broken) {
1191 commSetTimeout(fd, 10, NULL, NULL);
1192 } else {
1193 commSetTimeout(fd, Config.Timeout.read, NULL, NULL);
1194 }
1195
1196 flags.do_next_read = 1;
1197 break;
1198
1199 case COMPLETE_PERSISTENT_MSG:
1200 debug(11,5)("processReplyBody: COMPLETE_PERSISTENT_MSG\n");
1201 /* yes we have to clear all these! */
1202 commSetTimeout(fd, -1, NULL, NULL);
1203 flags.do_next_read = 0;
1204
1205 comm_remove_close_handler(fd, httpStateFree, this);
1206 fwd->unregister(fd);
1207#if LINUX_TPROXY
1208
1209 if (orig_request->flags.tproxy)
1210 client_addr = &orig_request->client_addr;
1211
1212#endif
1213
1214 if (_peer) {
1215 if (_peer->options.originserver)
1216 fwd->pconnPush(fd, _peer->name, orig_request->port, orig_request->host, client_addr);
1217 else
1218 fwd->pconnPush(fd, _peer->name, _peer->http_port, NULL, client_addr);
1219 } else {
1220 fwd->pconnPush(fd, request->host, request->port, NULL, client_addr);
1221 }
1222
1223 fd = -1;
1224
1225 serverComplete();
1226 return;
1227
1228 case COMPLETE_NONPERSISTENT_MSG:
1229 debug(11,5)("processReplyBody: COMPLETE_NONPERSISTENT_MSG\n");
1230 serverComplete();
1231 return;
1232 }
1233
1234 maybeReadVirginBody();
1235}
1236
1237void
1238HttpStateData::maybeReadVirginBody()
1239{
1240 int read_sz = readBuf->spaceSize();
1241
1242#if ICAP_CLIENT
1243#if RE_ENABLE_THIS_IF_NEEDED_OR_DELETE
1244 // This code is not broken, but is probably not needed because we
1245 // probably can read more than will fit into the BodyPipe buffer.
1246
1247 if (virginBodyDestination != NULL) {
1248 /*
1249 * BodyPipe buffer has a finite size limit. We
1250 * should not read more data from the network than will fit
1251 * into the pipe buffer. If totally full, don't register
1252 * the read handler at all. The ICAP side will call our
1253 * icapSpaceAvailable() method when it has free space again.
1254 */
1255 int icap_space = virginBodyDestination->buf().potentialSpaceSize();
1256
1257 debugs(11,9, "HttpStateData may read up to min(" << icap_space <<
1258 ", " << read_sz << ") bytes");
1259
1260 if (icap_space < read_sz)
1261 read_sz = icap_space;
1262 }
1263
1264#endif
1265#endif
1266
1267 debugs(11,9, HERE << (flags.do_next_read ? "may" : "wont") <<
1268 " read up to " << read_sz << " bytes from FD " << fd);
1269
1270 /*
1271 * why <2? Because delayAwareRead() won't actually read if
1272 * you ask it to read 1 byte. The delayed read request
1273 * just gets re-queued until the client side drains, then
1274 * the I/O thread hangs. Better to not register any read
1275 * handler until we get a notification from someone that
1276 * its okay to read again.
1277 */
1278 if (read_sz < 2)
1279 return;
1280
1281 if (flags.do_next_read) {
1282 flags.do_next_read = 0;
1283 entry->delayAwareRead(fd, readBuf->space(), read_sz, ReadReplyWrapper, this);
1284 }
1285}
1286
1287/*
1288 * This will be called when request write is complete.
1289 */
1290void
1291HttpStateData::SendComplete(int fd, char *bufnotused, size_t size, comm_err_t errflag, int xerrno, void *data)
1292{
1293 HttpStateData *httpState = static_cast<HttpStateData *>(data);
1294 debug(11, 5) ("httpSendComplete: FD %d: size %d: errflag %d.\n",
1295 fd, (int) size, errflag);
1296#if URL_CHECKSUM_DEBUG
1297
1298 entry->mem_obj->checkUrlChecksum();
1299#endif
1300
1301 if (size > 0) {
1302 fd_bytes(fd, size, FD_WRITE);
1303 kb_incr(&statCounter.server.all.kbytes_out, size);
1304 kb_incr(&statCounter.server.http.kbytes_out, size);
1305 }
1306
1307 if (errflag == COMM_ERR_CLOSING)
1308 return;
1309
1310 if (errflag) {
1311 ErrorState *err;
1312 err = errorCon(ERR_WRITE_ERROR, HTTP_BAD_GATEWAY, httpState->fwd->request);
1313 err->xerrno = xerrno;
1314 httpState->fwd->fail(err);
1315 comm_close(fd);
1316 return;
1317 }
1318
1319 /*
1320 * Set the read timeout here because it hasn't been set yet.
1321 * We only set the read timeout after the request has been
1322 * fully written to the server-side. If we start the timeout
1323 * after connection establishment, then we are likely to hit
1324 * the timeout for POST/PUT requests that have very large
1325 * request bodies.
1326 */
1327 commSetTimeout(fd, Config.Timeout.read, httpTimeout, httpState);
1328
1329 httpState->flags.request_sent = 1;
1330}
1331
1332// Close the HTTP server connection. Used by serverComplete().
1333void
1334HttpStateData::closeServer()
1335{
1336 debugs(11,5, HERE << "closing HTTP server FD " << fd << " this " << this);
1337
1338 if (fd >= 0) {
1339 fwd->unregister(fd);
1340 comm_remove_close_handler(fd, httpStateFree, this);
1341 comm_close(fd);
1342 fd = -1;
1343 }
1344}
1345
1346bool
1347HttpStateData::doneWithServer() const
1348{
1349 return fd < 0;
1350}
1351
1352/*
1353 * build request headers and append them to a given MemBuf
1354 * used by buildRequestPrefix()
1355 * note: initialised the HttpHeader, the caller is responsible for Clean()-ing
1356 */
1357void
1358HttpStateData::httpBuildRequestHeader(HttpRequest * request,
1359 HttpRequest * orig_request,
1360 StoreEntry * entry,
1361 HttpHeader * hdr_out,
1362 http_state_flags flags)
1363{
1364 /* building buffer for complex strings */
1365#define BBUF_SZ (MAX_URL+32)
1366 LOCAL_ARRAY(char, bbuf, BBUF_SZ);
1367 const HttpHeader *hdr_in = &orig_request->header;
1368 const HttpHeaderEntry *e;
1369 String strFwd;
1370 HttpHeaderPos pos = HttpHeaderInitPos;
1371 assert (hdr_out->owner == hoRequest);
1372 /* append our IMS header */
1373
1374 if (request->lastmod > -1)
1375 hdr_out->putTime(HDR_IF_MODIFIED_SINCE, request->lastmod);
1376
1377 bool we_do_ranges = decideIfWeDoRanges (orig_request);
1378
1379 String strConnection (hdr_in->getList(HDR_CONNECTION));
1380
1381 while ((e = hdr_in->getEntry(&pos)))
1382 copyOneHeaderFromClientsideRequestToUpstreamRequest(e, strConnection, request, orig_request, hdr_out, we_do_ranges, flags);
1383
1384 /* Abstraction break: We should interpret multipart/byterange responses
1385 * into offset-length data, and this works around our inability to do so.
1386 */
1387 if (!we_do_ranges && orig_request->multipartRangeRequest()) {
1388 /* don't cache the result */
1389 orig_request->flags.cachable = 0;
1390 /* pretend it's not a range request */
1391 delete orig_request->range;
1392 orig_request->range = NULL;
1393 orig_request->flags.range = 0;
1394 }
1395
1396 /* append Via */
1397 if (Config.onoff.via) {
1398 String strVia;
1399 strVia = hdr_in->getList(HDR_VIA);
1400 snprintf(bbuf, BBUF_SZ, "%d.%d %s",
1401 orig_request->http_ver.major,
1402 orig_request->http_ver.minor, ThisCache);
1403 strListAdd(&strVia, bbuf, ',');
1404 hdr_out->putStr(HDR_VIA, strVia.buf());
1405 strVia.clean();
1406 }
1407
1408#if ESI
1409 {
1410 /* Append Surrogate-Capabilities */
1411 String strSurrogate (hdr_in->getList(HDR_SURROGATE_CAPABILITY));
1412 snprintf(bbuf, BBUF_SZ, "%s=\"Surrogate/1.0 ESI/1.0\"",
1413 Config.Accel.surrogate_id);
1414 strListAdd(&strSurrogate, bbuf, ',');
1415 hdr_out->putStr(HDR_SURROGATE_CAPABILITY, strSurrogate.buf());
1416 }
1417#endif
1418
1419 /* append X-Forwarded-For */
1420 strFwd = hdr_in->getList(HDR_X_FORWARDED_FOR);
1421
1422 if (opt_forwarded_for && orig_request->client_addr.s_addr != no_addr.s_addr)
1423 strListAdd(&strFwd, inet_ntoa(orig_request->client_addr), ',');
1424 else
1425 strListAdd(&strFwd, "unknown", ',');
1426
1427 hdr_out->putStr(HDR_X_FORWARDED_FOR, strFwd.buf());
1428
1429 strFwd.clean();
1430
1431 /* append Host if not there already */
1432 if (!hdr_out->has(HDR_HOST)) {
1433 if (orig_request->peer_domain) {
1434 hdr_out->putStr(HDR_HOST, orig_request->peer_domain);
1435 } else if (orig_request->port == urlDefaultPort(orig_request->protocol)) {
1436 /* use port# only if not default */
1437 hdr_out->putStr(HDR_HOST, orig_request->host);
1438 } else {
1439 httpHeaderPutStrf(hdr_out, HDR_HOST, "%s:%d",
1440 orig_request->host, (int) orig_request->port);
1441 }
1442 }
1443
1444 /* append Authorization if known in URL, not in header and going direct */
1445 if (!hdr_out->has(HDR_AUTHORIZATION)) {
1446 if (!request->flags.proxying && *request->login) {
1447 httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s",
1448 base64_encode(request->login));
1449 }
1450 }
1451
1452 /* append Proxy-Authorization if configured for peer, and proxying */
1453 if (request->flags.proxying && orig_request->peer_login &&
1454 !hdr_out->has(HDR_PROXY_AUTHORIZATION)) {
1455 if (*orig_request->peer_login == '*') {
1456 /* Special mode, to pass the username to the upstream cache */
1457 char loginbuf[256];
1458 const char *username = "-";
1459
1460 if (orig_request->auth_user_request)
1461 username = orig_request->auth_user_request->username();
1462 else if (orig_request->extacl_user.size())
1463 username = orig_request->extacl_user.buf();
1464
1465 snprintf(loginbuf, sizeof(loginbuf), "%s%s", username, orig_request->peer_login + 1);
1466
1467 httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s",
1468 base64_encode(loginbuf));
1469 } else if (strcmp(orig_request->peer_login, "PASS") == 0) {
1470 if (orig_request->extacl_user.size() && orig_request->extacl_passwd.size()) {
1471 char loginbuf[256];
1472 snprintf(loginbuf, sizeof(loginbuf), "%s:%s", orig_request->extacl_user.buf(), orig_request->extacl_passwd.buf());
1473 httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s",
1474 base64_encode(loginbuf));
1475 }
1476 } else if (strcmp(orig_request->peer_login, "PROXYPASS") == 0) {
1477 /* Nothing to do */
1478 } else {
1479 httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s",
1480 base64_encode(orig_request->peer_login));
1481 }
1482 }
1483
1484 /* append WWW-Authorization if configured for peer */
1485 if (flags.originpeer && orig_request->peer_login &&
1486 !hdr_out->has(HDR_AUTHORIZATION)) {
1487 if (strcmp(orig_request->peer_login, "PASS") == 0) {
1488 /* No credentials to forward.. (should have been done above if available) */
1489 } else if (strcmp(orig_request->peer_login, "PROXYPASS") == 0) {
1490 /* Special mode, convert proxy authentication to WWW authentication
1491 * (also applies to authentication provided by external acl)
1492 */
1493 const char *auth = hdr_in->getStr(HDR_PROXY_AUTHORIZATION);
1494
1495 if (auth && strncasecmp(auth, "basic ", 6) == 0) {
1496 hdr_out->putStr(HDR_AUTHORIZATION, auth);
1497 } else if (orig_request->extacl_user.size() && orig_request->extacl_passwd.size()) {
1498 char loginbuf[256];
1499 snprintf(loginbuf, sizeof(loginbuf), "%s:%s", orig_request->extacl_user.buf(), orig_request->extacl_passwd.buf());
1500 httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s",
1501 base64_encode(loginbuf));
1502 }
1503 } else if (*orig_request->peer_login == '*') {
1504 /* Special mode, to pass the username to the upstream cache */
1505 char loginbuf[256];
1506 const char *username = "-";
1507
1508 if (orig_request->auth_user_request)
1509 username = orig_request->auth_user_request->username();
1510 else if (orig_request->extacl_user.size())
1511 username = orig_request->extacl_user.buf();
1512
1513 snprintf(loginbuf, sizeof(loginbuf), "%s%s", username, orig_request->peer_login + 1);
1514
1515 httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s",
1516 base64_encode(loginbuf));
1517 } else {
1518 /* Fixed login string */
1519 httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s",
1520 base64_encode(orig_request->peer_login));
1521 }
1522 }
1523
1524 /* append Cache-Control, add max-age if not there already */ {
1525 HttpHdrCc *cc = hdr_in->getCc();
1526
1527 if (!cc)
1528 cc = httpHdrCcCreate();
1529
1530 if (!EBIT_TEST(cc->mask, CC_MAX_AGE)) {
1531 const char *url =
1532 entry ? entry->url() : urlCanonical(orig_request);
1533 httpHdrCcSetMaxAge(cc, getMaxAge(url));
1534
1535 if (request->urlpath.size())
1536 assert(strstr(url, request->urlpath.buf()));
1537 }
1538
1539 /* Set no-cache if determined needed but not found */
1540 if (orig_request->flags.nocache && !hdr_in->has(HDR_PRAGMA))
1541 EBIT_SET(cc->mask, CC_NO_CACHE);
1542
1543 /* Enforce sibling relations */
1544 if (flags.only_if_cached)
1545 EBIT_SET(cc->mask, CC_ONLY_IF_CACHED);
1546
1547 hdr_out->putCc(cc);
1548
1549 httpHdrCcDestroy(cc);
1550 }
1551
1552 /* maybe append Connection: keep-alive */
1553 if (flags.keepalive) {
1554 if (flags.proxying) {
1555 hdr_out->putStr(HDR_PROXY_CONNECTION, "keep-alive");
1556 } else {
1557 hdr_out->putStr(HDR_CONNECTION, "keep-alive");
1558 }
1559 }
1560
1561 /* append Front-End-Https */
1562 if (flags.front_end_https) {
1563 if (flags.front_end_https == 1 || request->protocol == PROTO_HTTPS)
1564 hdr_out->putStr(HDR_FRONT_END_HTTPS, "On");
1565 }
1566
1567 /* Now mangle the headers. */
1568 if (Config2.onoff.mangle_request_headers)
1569 httpHdrMangleList(hdr_out, request, ROR_REQUEST);
1570
1571 strConnection.clean();
1572}
1573
1574void
1575copyOneHeaderFromClientsideRequestToUpstreamRequest(const HttpHeaderEntry *e, String strConnection, HttpRequest * request, HttpRequest * orig_request, HttpHeader * hdr_out, int we_do_ranges, http_state_flags flags)
1576{
1577 debug(11, 5) ("httpBuildRequestHeader: %s: %s\n",
1578 e->name.buf(), e->value.buf());
1579
1580 if (!httpRequestHdrAllowed(e, &strConnection)) {
1581 debug(11, 2) ("'%s' header denied by anonymize_headers configuration\n",+ e->name.buf());
1582 return;
1583 }
1584
1585 switch (e->id) {
1586
1587 case HDR_PROXY_AUTHORIZATION:
1588 /* Only pass on proxy authentication to peers for which
1589 * authentication forwarding is explicitly enabled
1590 */
1591
1592 if (flags.proxying && orig_request->peer_login &&
1593 (strcmp(orig_request->peer_login, "PASS") == 0 ||
1594 strcmp(orig_request->peer_login, "PROXYPASS") == 0)) {
1595 hdr_out->addEntry(e->clone());
1596 }
1597
1598 break;
1599
1600 case HDR_AUTHORIZATION:
1601 /* Pass on WWW authentication */
1602
1603 if (!flags.originpeer) {
1604 hdr_out->addEntry(e->clone());
1605 } else {
1606 /* In accelerators, only forward authentication if enabled
1607 * (see also below for proxy->server authentication)
1608 */
1609
1610 if (orig_request->peer_login &&
1611 (strcmp(orig_request->peer_login, "PASS") == 0 ||
1612 strcmp(orig_request->peer_login, "PROXYPASS") == 0)) {
1613 hdr_out->addEntry(e->clone());
1614 }
1615 }
1616
1617 break;
1618
1619 case HDR_HOST:
1620 /*
1621 * Normally Squid rewrites the Host: header.
1622 * However, there is one case when we don't: If the URL
1623 * went through our redirector and the admin configured
1624 * 'redir_rewrites_host' to be off.
1625 */
1626
1627 if (request->flags.redirected && !Config.onoff.redir_rewrites_host)
1628 hdr_out->addEntry(e->clone());
1629 else {
1630 /* use port# only if not default */
1631
1632 if (orig_request->port == urlDefaultPort(orig_request->protocol)) {
1633 hdr_out->putStr(HDR_HOST, orig_request->host);
1634 } else {
1635 httpHeaderPutStrf(hdr_out, HDR_HOST, "%s:%d",
1636 orig_request->host, (int) orig_request->port);
1637 }
1638 }
1639
1640 break;
1641
1642 case HDR_IF_MODIFIED_SINCE:
1643 /* append unless we added our own;
1644 * note: at most one client's ims header can pass through */
1645
1646 if (!hdr_out->has(HDR_IF_MODIFIED_SINCE))
1647 hdr_out->addEntry(e->clone());
1648
1649 break;
1650
1651 case HDR_MAX_FORWARDS:
1652 if (orig_request->method == METHOD_TRACE) {
1653 const int hops = e->getInt();
1654
1655 if (hops > 0)
1656 hdr_out->putInt(HDR_MAX_FORWARDS, hops - 1);
1657 }
1658
1659 break;
1660
1661 case HDR_VIA:
1662 /* If Via is disabled then forward any received header as-is */
1663
1664 if (!Config.onoff.via)
1665 hdr_out->addEntry(e->clone());
1666
1667 break;
1668
1669 case HDR_RANGE:
1670
1671 case HDR_IF_RANGE:
1672
1673 case HDR_REQUEST_RANGE:
1674 if (!we_do_ranges)
1675 hdr_out->addEntry(e->clone());
1676
1677 break;
1678
1679 case HDR_PROXY_CONNECTION:
1680
1681 case HDR_CONNECTION:
1682
1683 case HDR_X_FORWARDED_FOR:
1684
1685 case HDR_CACHE_CONTROL:
1686 /* append these after the loop if needed */
1687 break;
1688
1689 case HDR_FRONT_END_HTTPS:
1690 if (!flags.front_end_https)
1691 hdr_out->addEntry(e->clone());
1692
1693 break;
1694
1695 default:
1696 /* pass on all other header fields */
1697 hdr_out->addEntry(e->clone());
1698 }
1699}
1700
1701bool
1702HttpStateData::decideIfWeDoRanges (HttpRequest * orig_request)
1703{
1704 bool result = true;
1705 /* decide if we want to do Ranges ourselves
1706 * and fetch the whole object now)
1707 * We want to handle Ranges ourselves iff
1708 * - we can actually parse client Range specs
1709 * - the specs are expected to be simple enough (e.g. no out-of-order ranges)
1710 * - reply will be cachable
1711 * (If the reply will be uncachable we have to throw it away after
1712 * serving this request, so it is better to forward ranges to
1713 * the server and fetch only the requested content)
1714 */
1715
1716 if (NULL == orig_request->range || !orig_request->flags.cachable
1717 || orig_request->range->offsetLimitExceeded())
1718 result = false;
1719
1720 debug(11, 8) ("decideIfWeDoRanges: range specs: %p, cachable: %d; we_do_ranges: %d\n",
1721 orig_request->range, orig_request->flags.cachable, result);
1722
1723 return result;
1724}
1725
1726/* build request prefix and append it to a given MemBuf;
1727 * return the length of the prefix */
1728mb_size_t
1729HttpStateData::buildRequestPrefix(HttpRequest * request,
1730 HttpRequest * orig_request,
1731 StoreEntry * entry,
1732 MemBuf * mb,
1733 http_state_flags flags)
1734{
1735 const int offset = mb->size;
1736 HttpVersion httpver(1, 0);
1737 mb->Printf("%s %s HTTP/%d.%d\r\n",
1738 RequestMethodStr[request->method],
1739 request->urlpath.size() ? request->urlpath.buf() : "/",
1740 httpver.major,httpver.minor);
1741 /* build and pack headers */
1742 {
1743 HttpHeader hdr(hoRequest);
1744 Packer p;
1745 httpBuildRequestHeader(request, orig_request, entry, &hdr, flags);
1746 packerToMemInit(&p, mb);
1747 hdr.packInto(&p);
1748 hdr.clean();
1749 packerClean(&p);
1750 }
1751 /* append header terminator */
1752 mb->append(crlf, 2);
1753 return mb->size - offset;
1754}
1755
1756/* This will be called when connect completes. Write request. */
1757bool
1758HttpStateData::sendRequest()
1759{
1760 MemBuf mb;
1761
1762 debug(11, 5) ("httpSendRequest: FD %d, request %p, this %p.\n", fd, request, this);
1763
1764 commSetTimeout(fd, Config.Timeout.lifetime, httpTimeout, this);
1765 flags.do_next_read = 1;
1766 maybeReadVirginBody();
1767
1768 if (orig_request->body_pipe != NULL) {
1769 requestBodySource = orig_request->body_pipe;
1770
1771 if (!requestBodySource->setConsumerIfNotLate(this)) {
1772 debugs(32,3, HERE << "aborting on partially consumed body");
1773 requestBodySource = NULL;
1774 return false;
1775 }
1776
1777 requestSender = HttpStateData::sentRequestBodyWrapper;
1778 debugs(32,3, HERE << "expecting request body on pipe " << requestBodySource);
1779 } else {
1780 assert(!requestBodySource);
1781 requestSender = HttpStateData::SendComplete;
1782 }
1783
1784 if (_peer != NULL) {
1785 if (_peer->options.originserver) {
1786 flags.proxying = 0;
1787 flags.originpeer = 1;
1788 } else {
1789 flags.proxying = 1;
1790 flags.originpeer = 0;
1791 }
1792 } else {
1793 flags.proxying = 0;
1794 flags.originpeer = 0;
1795 }
1796
1797 /*
1798 * Is keep-alive okay for all request methods?
1799 */
1800 if (!Config.onoff.server_pconns)
1801 flags.keepalive = 0;
1802 else if (_peer == NULL)
1803 flags.keepalive = 1;
1804 else if (_peer->stats.n_keepalives_sent < 10)
1805 flags.keepalive = 1;
1806 else if ((double) _peer->stats.n_keepalives_recv /
1807 (double) _peer->stats.n_keepalives_sent > 0.50)
1808 flags.keepalive = 1;
1809
1810 if (_peer) {
1811 if (neighborType(_peer, request) == PEER_SIBLING &&
1812 !_peer->options.allow_miss)
1813 flags.only_if_cached = 1;
1814
1815 flags.front_end_https = _peer->front_end_https;
1816 }
1817
1818 mb.init();
1819 buildRequestPrefix(request, orig_request, entry, &mb, flags);
1820 debug(11, 6) ("httpSendRequest: FD %d:\n%s\n", fd, mb.buf);
1821 comm_write_mbuf(fd, &mb, requestSender, this);
1822
1823 return true;
1824}
1825
1826void
1827httpStart(FwdState *fwd)
1828{
1829 debug(11, 3) ("httpStart: \"%s %s\"\n",
1830 RequestMethodStr[fwd->request->method],
1831 fwd->entry->url());
1832 HttpStateData *httpState = new HttpStateData(fwd);
1833
1834 if (!httpState->sendRequest()) {
1835 debug(11, 3) ("httpStart: aborted");
1836 delete httpState;
1837 return;
1838 }
1839
1840 statCounter.server.all.requests++;
1841 statCounter.server.http.requests++;
1842
1843 /*
1844 * We used to set the read timeout here, but not any more.
1845 * Now its set in httpSendComplete() after the full request,
1846 * including request body, has been written to the server.
1847 */
1848}
1849
1850void
1851HttpStateData::doneSendingRequestBody()
1852{
1853 ACLChecklist ch;
1854 debugs(11,5, HERE << "doneSendingRequestBody: FD " << fd);
1855 ch.request = HTTPMSGLOCK(request);
1856
1857 if (Config.accessList.brokenPosts)
1858 ch.accessList = cbdataReference(Config.accessList.brokenPosts);
1859
1860 /* cbdataReferenceDone() happens in either fastCheck() or ~ACLCheckList */
1861
1862 if (!Config.accessList.brokenPosts) {
1863 debug(11, 5) ("doneSendingRequestBody: No brokenPosts list\n");
1864 HttpStateData::SendComplete(fd, NULL, 0, COMM_OK, 0, this);
1865 } else if (!ch.fastCheck()) {
1866 debug(11, 5) ("doneSendingRequestBody: didn't match brokenPosts\n");
1867 HttpStateData::SendComplete(fd, NULL, 0, COMM_OK, 0, this);
1868 } else {
1869 debug(11, 2) ("doneSendingRequestBody: matched brokenPosts\n");
1870 comm_write(fd, "\r\n", 2, HttpStateData::SendComplete, this, NULL);
1871 }
1872}
1873
1874// more origin request body data is available
1875void
1876HttpStateData::handleMoreRequestBodyAvailable()
1877{
1878 if (eof || fd < 0) {
1879 // XXX: we should check this condition in other callbacks then!
1880 // TODO: Check whether this can actually happen: We should unsubscribe
1881 // as a body consumer when the above condition(s) are detected.
1882 debugs(11, 1, HERE << "Transaction aborted while reading HTTP body");
1883 return;
1884 }
1885
1886 assert(requestBodySource != NULL);
1887
1888 if (requestBodySource->buf().hasContent()) {
1889 // XXX: why does not this trigger a debug message on every request?
1890
1891 if (flags.headers_parsed && !flags.abuse_detected) {
1892 flags.abuse_detected = 1;
1893 debug(11, 1) ("http handleMoreRequestBodyAvailable: Likely proxy abuse detected '%s' -> '%s'\n",
1894 inet_ntoa(orig_request->client_addr),
1895 entry->url());
1896
1897 if (getReply()->sline.status == HTTP_INVALID_HEADER) {
1898 comm_close(fd);
1899 return;
1900 }
1901 }
1902 }
1903
1904 HttpStateData::handleMoreRequestBodyAvailable();
1905}
1906
1907// premature end of the request body
1908void
1909HttpStateData::handleRequestBodyProducerAborted()
1910{
1911 ServerStateData::handleRequestBodyProducerAborted();
1912 // XXX: SendComplete(COMM_ERR_CLOSING) does little. Is it enough?
1913 SendComplete(fd, NULL, 0, COMM_ERR_CLOSING, 0, this);
1914}
1915
1916// called when we wrote request headers(!) or a part of the body
1917void
1918HttpStateData::sentRequestBody(int fd, size_t size, comm_err_t errflag)
1919{
1920 if (size > 0)
1921 kb_incr(&statCounter.server.http.kbytes_out, size);
1922
1923 ServerStateData::sentRequestBody(fd, size, errflag);
1924}
1925
1926// Quickly abort the transaction
1927// TODO: destruction should be sufficient as the destructor should cleanup,
1928// including canceling close handlers
1929void
1930HttpStateData::abortTransaction(const char *reason)
1931{
1932 debugs(11,5, HERE << "aborting transaction for " << reason <<
1933 "; FD " << fd << ", this " << this);
1934
1935 if (fd >= 0)
1936 comm_close(fd);
1937 else
1938 delete this;
1939}
1940
1941void
1942httpBuildVersion(HttpVersion * version, unsigned int major, unsigned int minor)
1943{
1944 version->major = major;
1945 version->minor = minor;
1946}
1947
1948#if ICAP_CLIENT
1949
1950static void
1951icapAclCheckDoneWrapper(ICAPServiceRep::Pointer service, void *data)
1952{
1953 HttpStateData *http = (HttpStateData *)data;
1954 http->icapAclCheckDone(service);
1955}
1956
1957void
1958HttpStateData::icapAclCheckDone(ICAPServiceRep::Pointer service)
1959{
1960 icapAccessCheckPending = false;
1961
1962 const bool startedIcap = startIcap(service, orig_request);
1963
1964 if (!startedIcap && (!service || service->bypass)) {
1965 // handle ICAP start failure when no service was selected
1966 // or where the selected service was optional
1967 entry->replaceHttpReply(reply);
1968
1969 haveParsedReplyHeaders();
1970 processReplyBody();
1971
1972 if (eof == 1)
1973 serverComplete();
1974
1975 return;
1976 }
1977
1978 if (!startedIcap) {
1979 // handle start failure for an essential ICAP service
1980 ErrorState *err = errorCon(ERR_ICAP_FAILURE, HTTP_INTERNAL_SERVER_ERROR, orig_request);
1981 err->xerrno = errno;
1982 errorAppendEntry(entry, err);
1983 comm_close(fd);
1984 return;
1985 }
1986
1987 processReplyBody();
1988}
1989
1990#endif