]> git.ipfire.org Git - thirdparty/squid.git/blame - src/HttpRequest.cc
Prep for 3.3.12 and 3.4.4
[thirdparty/squid.git] / src / HttpRequest.cc
CommitLineData
99edd1c3 1/*
99edd1c3 2 * DEBUG: section 73 HTTP Request
3 * AUTHOR: Duane Wessels
4 *
2b6662ba 5 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 6 * ----------------------------------------------------------
99edd1c3 7 *
2b6662ba 8 * Squid is the result of efforts by numerous individuals from
9 * the Internet community; see the CONTRIBUTORS file for full
10 * details. Many organizations have provided support for Squid's
11 * development; see the SPONSORS file for full details. Squid is
12 * Copyrighted (C) 2001 by the Regents of the University of
13 * California; see the COPYRIGHT file for full details. Squid
14 * incorporates software developed and/or copyrighted by other
15 * sources; see the CREDITS file for full details.
99edd1c3 16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
9e008dda 21 *
99edd1c3 22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
9e008dda 26 *
99edd1c3 27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
cbdec147 29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 30 *
51ee7c82 31 * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
99edd1c3 32 */
33
582c2af2 34#include "squid.h"
f4698e0b 35#include "AccessLogEntry.h"
1328cfb7 36#include "acl/AclSizeLimit.h"
582c2af2
FC
37#include "acl/FilledChecklist.h"
38#include "client_side.h"
cfd66529 39#include "DnsLookupDetails.h"
582c2af2 40#include "err_detail_type.h"
67679543 41#include "globals.h"
d05c079c 42#include "gopher.h"
5c0c642e 43#include "http.h"
7ebe76de 44#include "HttpHdrCc.h"
528b2c61 45#include "HttpHeaderRange.h"
582c2af2 46#include "HttpRequest.h"
38e16f92 47#include "log/Config.h"
0eb49b6d 48#include "MemBuf.h"
4d5904f7 49#include "SquidConfig.h"
25b6a907 50#include "Store.h"
b1bd952a 51#include "URL.h"
582c2af2
FC
52
53#if USE_AUTH
54#include "auth/UserRequest.h"
55#endif
3ff65596
AR
56#if ICAP_CLIENT
57#include "adaptation/icap/icap_log.h"
58#endif
528b2c61 59
3aaa8e6f 60HttpRequest::HttpRequest() :
f4f55a21 61 HttpMsg(hoRequest)
75faaa7a 62{
5cafad19 63 init();
64}
65
d06e17ea 66HttpRequest::HttpRequest(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aUrlpath) :
f4f55a21 67 HttpMsg(hoRequest)
5cafad19 68{
5dfc3258
AR
69 static unsigned int id = 1;
70 debugs(93,7, HERE << "constructed, this=" << this << " id=" << ++id);
5cafad19 71 init();
0e8aad88 72 initHTTP(aMethod, aProtocol, aUrlpath);
5cafad19 73}
74
75HttpRequest::~HttpRequest()
76{
5cafad19 77 clean();
5dfc3258 78 debugs(93,7, HERE << "destructed, this=" << this);
5cafad19 79}
80
81void
0c3d3f65 82HttpRequest::initHTTP(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aUrlpath)
5cafad19 83{
84 method = aMethod;
85 protocol = aProtocol;
86 urlpath = aUrlpath;
87}
88
89void
90HttpRequest::init()
91{
c2a7cefd 92 method = Http::METHOD_NONE;
0c3d3f65 93 protocol = AnyP::PROTO_NONE;
30abd221 94 urlpath = NULL;
a3f28359 95 login[0] = '\0';
96 host[0] = '\0';
12ef783b 97 host_is_numeric = -1;
2f1431ea 98#if USE_AUTH
a3f28359 99 auth_user_request = NULL;
2f1431ea 100#endif
a3f28359 101 port = 0;
102 canonical = NULL;
a3f28359 103 memset(&flags, '\0', sizeof(flags));
104 range = NULL;
105 ims = -1;
106 imslen = 0;
5cafad19 107 lastmod = -1;
4dd643d5
AJ
108 client_addr.setEmpty();
109 my_addr.setEmpty();
5f8252d2 110 body_pipe = NULL;
a3f28359 111 // hier
3ff65596 112 dnsWait = -1;
a3f28359 113 errType = ERR_NONE;
64b66b76 114 errDetail = ERR_DETAIL_NONE;
5cafad19 115 peer_login = NULL; // not allocated/deallocated by this class
116 peer_domain = NULL; // not allocated/deallocated by this class
593d3cdb 117 peer_host = NULL;
a3f28359 118 vary_headers = NULL;
35fb56c9 119 myportname = null_string;
5cafad19 120 tag = null_string;
2f1431ea 121#if USE_AUTH
5cafad19 122 extacl_user = null_string;
123 extacl_passwd = null_string;
2f1431ea 124#endif
5cafad19 125 extacl_log = null_string;
8c93a598 126 extacl_message = null_string;
c99de607 127 pstate = psReadyToParseStartLine;
3d674977 128#if FOLLOW_X_FORWARDED_FOR
4dd643d5 129 indirect_client_addr.setEmpty();
3d674977 130#endif /* FOLLOW_X_FORWARDED_FOR */
3ff65596
AR
131#if USE_ADAPTATION
132 adaptHistory_ = NULL;
133#endif
134#if ICAP_CLIENT
135 icapHistory_ = NULL;
136#endif
11e3fa1c 137 rangeOffsetLimit = -2; //a value of -2 means not checked yet
8596962e 138}
139
99edd1c3 140void
5cafad19 141HttpRequest::clean()
99edd1c3 142{
9e008dda 143 // we used to assert that the pipe is NULL, but now the request only
5f8252d2 144 // points to a pipe that is owned and initiated by another object.
9e008dda 145 body_pipe = NULL;
2f1431ea 146#if USE_AUTH
a33a428a 147 auth_user_request = NULL;
2f1431ea 148#endif
8596962e 149 safe_free(canonical);
62e76326 150
8596962e 151 safe_free(vary_headers);
62e76326 152
30abd221 153 urlpath.clean();
62e76326 154
519e0948 155 header.clean();
62e76326 156
07947ad8 157 if (cache_control) {
3d7782c1 158 delete cache_control;
07947ad8 159 cache_control = NULL;
160 }
62e76326 161
5cafad19 162 if (range) {
8596962e 163 delete range;
5cafad19 164 range = NULL;
165 }
62e76326 166
35fb56c9
AJ
167 myportname.clean();
168
f4f55a21 169 notes = NULL;
d06e17ea 170
30abd221 171 tag.clean();
2f1431ea 172#if USE_AUTH
30abd221 173 extacl_user.clean();
30abd221 174 extacl_passwd.clean();
2f1431ea 175#endif
30abd221 176 extacl_log.clean();
3ff65596 177
8c93a598
HN
178 extacl_message.clean();
179
46017fdd
CT
180 etag.clean();
181
3ff65596
AR
182#if USE_ADAPTATION
183 adaptHistory_ = NULL;
184#endif
185#if ICAP_CLIENT
186 icapHistory_ = NULL;
187#endif
8596962e 188}
4a972fa2 189
5cafad19 190void
191HttpRequest::reset()
192{
193 clean();
194 init();
195}
196
fa0e6114
AR
197HttpRequest *
198HttpRequest::clone() const
199{
b4f2886c 200 HttpRequest *copy = new HttpRequest(method, protocol, urlpath.termedBuf());
fa0e6114
AR
201 // TODO: move common cloning clone to Msg::copyTo() or copy ctor
202 copy->header.append(&header);
203 copy->hdrCacheInit();
204 copy->hdr_sz = hdr_sz;
205 copy->http_ver = http_ver;
206 copy->pstate = pstate; // TODO: should we assert a specific state here?
207 copy->body_pipe = body_pipe;
208
209 strncpy(copy->login, login, sizeof(login)); // MAX_LOGIN_SZ
210 strncpy(copy->host, host, sizeof(host)); // SQUIDHOSTNAMELEN
211 copy->host_addr = host_addr;
212
fa0e6114
AR
213 copy->port = port;
214 // urlPath handled in ctor
9e008dda
AJ
215 copy->canonical = canonical ? xstrdup(canonical) : NULL;
216
66363092 217 // range handled in hdrCacheInit()
9e008dda
AJ
218 copy->ims = ims;
219 copy->imslen = imslen;
fa0e6114
AR
220 copy->hier = hier; // Is it safe to copy? Should we?
221
222 copy->errType = errType;
223
224 // XXX: what to do with copy->peer_login?
225
9e008dda 226 copy->lastmod = lastmod;
46017fdd 227 copy->etag = etag;
fa0e6114
AR
228 copy->vary_headers = vary_headers ? xstrdup(vary_headers) : NULL;
229 // XXX: what to do with copy->peer_domain?
230
231 copy->tag = tag;
fa0e6114 232 copy->extacl_log = extacl_log;
8c93a598 233 copy->extacl_message = extacl_message;
fa0e6114 234
fbc1c5a6
AJ
235 const bool inheritWorked = copy->inheritProperties(this);
236 assert(inheritWorked);
3ff65596 237
fa0e6114
AR
238 return copy;
239}
240
d5964067
AJ
241bool
242HttpRequest::inheritProperties(const HttpMsg *aMsg)
243{
244 const HttpRequest* aReq = dynamic_cast<const HttpRequest*>(aMsg);
245 if (!aReq)
246 return false;
247
248 client_addr = aReq->client_addr;
249#if FOLLOW_X_FORWARDED_FOR
250 indirect_client_addr = aReq->indirect_client_addr;
d5964067
AJ
251#endif
252 my_addr = aReq->my_addr;
253
254 dnsWait = aReq->dnsWait;
255
256#if USE_ADAPTATION
257 adaptHistory_ = aReq->adaptHistory();
258#endif
259#if ICAP_CLIENT
260 icapHistory_ = aReq->icapHistory();
261#endif
262
263 // This may be too conservative for the 204 No Content case
264 // may eventually need cloneNullAdaptationImmune() for that.
265 flags = aReq->flags.cloneAdaptationImmune();
266
267 errType = aReq->errType;
268 errDetail = aReq->errDetail;
269#if USE_AUTH
270 auth_user_request = aReq->auth_user_request;
f4f6ab06
AJ
271 extacl_user = aReq->extacl_user;
272 extacl_passwd = aReq->extacl_passwd;
d5964067 273#endif
983983ce 274
20fb3571
AJ
275 myportname = aReq->myportname;
276
983983ce 277 // main property is which connection the request was received on (if any)
d5964067 278 clientConnectionManager = aReq->clientConnectionManager;
f4698e0b 279
f4f55a21 280 notes = aReq->notes;
d5964067
AJ
281 return true;
282}
283
96ee497f
AJ
284/**
285 * Checks the first line of an HTTP request is valid
286 * currently just checks the request method is present.
287 *
288 * NP: Other errors are left for detection later in the parse.
289 */
c21ad0f5 290bool
955394ce 291HttpRequest::sanityCheckStartLine(MemBuf *buf, const size_t hdr_len, Http::StatusCode *error)
8596962e 292{
96ee497f
AJ
293 // content is long enough to possibly hold a reply
294 // 2 being magic size of a 1-byte request method plus space delimiter
295 if ( buf->contentSize() < 2 ) {
296 // this is ony a real error if the headers apparently complete.
297 if (hdr_len > 0) {
0246f6b8 298 debugs(58, 3, HERE << "Too large request header (" << hdr_len << " bytes)");
955394ce 299 *error = Http::scInvalidHeader;
96ee497f
AJ
300 }
301 return false;
302 }
8596962e 303
96ee497f 304 /* See if the request buffer starts with a known HTTP request method. */
c2a7cefd 305 if (HttpRequestMethod(buf->content(),NULL) == Http::METHOD_NONE) {
bf8fe701 306 debugs(73, 3, "HttpRequest::sanityCheckStartLine: did not find HTTP request method");
955394ce 307 *error = Http::scInvalidHeader;
8596962e 308 return false;
309 }
310
311 return true;
312}
313
c21ad0f5 314bool
315HttpRequest::parseFirstLine(const char *start, const char *end)
8596962e 316{
863d85ee 317 const char *t = start + strcspn(start, w_space);
985c86bc 318 method = HttpRequestMethod(start, t);
863d85ee 319
c2a7cefd 320 if (method == Http::METHOD_NONE)
863d85ee 321 return false;
322
323 start = t + strspn(t, w_space);
324
325 const char *ver = findTrailingHTTPVersion(start, end);
326
327 if (ver) {
328 end = ver - 1;
329
330 while (xisspace(*end)) // find prev non-space
5e263176 331 --end;
863d85ee 332
95dc7ff4 333 ++end; // back to space
863d85ee 334
335 if (2 != sscanf(ver + 5, "%d.%d", &http_ver.major, &http_ver.minor)) {
e0236918 336 debugs(73, DBG_IMPORTANT, "parseRequestLine: Invalid HTTP identifier.");
863d85ee 337 return false;
338 }
339 } else {
340 http_ver.major = 0;
341 http_ver.minor = 9;
342 }
343
344 if (end < start) // missing URI
345 return false;
346
347 char save = *end;
348
349 * (char *) end = '\0'; // temp terminate URI, XXX dangerous?
350
351 HttpRequest *tmp = urlParse(method, (char *) start, this);
352
353 * (char *) end = save;
354
355 if (NULL == tmp)
356 return false;
357
358 return true;
99edd1c3 359}
360
99edd1c3 361int
666f514b 362HttpRequest::parseHeader(const char *parse_start, int len)
99edd1c3 363{
364 const char *blk_start, *blk_end;
62e76326 365
666f514b 366 if (!httpMsgIsolateHeaders(&parse_start, len, &blk_start, &blk_end))
62e76326 367 return 0;
368
a9925b40 369 int result = header.parse(blk_start, blk_end);
62e76326 370
528b2c61 371 if (result)
07947ad8 372 hdrCacheInit();
62e76326 373
528b2c61 374 return result;
99edd1c3 375}
376
a00a7c85 377/* swaps out request using httpRequestPack */
99edd1c3 378void
5cafad19 379HttpRequest::swapOut(StoreEntry * e)
99edd1c3 380{
a00a7c85 381 Packer p;
5cafad19 382 assert(e);
a00a7c85 383 packerToStoreInit(&p, e);
5cafad19 384 pack(&p);
a00a7c85 385 packerClean(&p);
386}
387
388/* packs request-line and headers, appends <crlf> terminator */
389void
5cafad19 390HttpRequest::pack(Packer * p)
a00a7c85 391{
5cafad19 392 assert(p);
a00a7c85 393 /* pack request-line */
3872be7c
AJ
394 packerPrintf(p, "%s " SQUIDSTRINGPH " HTTP/%d.%d\r\n",
395 RequestMethodStr(method), SQUIDSTRINGPRINT(urlpath),
396 http_ver.major, http_ver.minor);
a00a7c85 397 /* headers */
a9925b40 398 header.packInto(p);
2246b732 399 /* trailer */
a00a7c85 400 packerAppend(p, "\r\n", 2);
2246b732 401}
402
5cafad19 403/*
404 * A wrapper for debugObj()
405 */
2246b732 406void
5cafad19 407httpRequestPack(void *obj, Packer *p)
2246b732 408{
5cafad19 409 HttpRequest *request = static_cast<HttpRequest*>(obj);
410 request->pack(p);
99edd1c3 411}
eeb423fb 412
2246b732 413/* returns the length of request line + headers + crlf */
414int
5cafad19 415HttpRequest::prefixLen()
2246b732 416{
60745f24 417 return strlen(RequestMethodStr(method)) + 1 +
5cafad19 418 urlpath.size() + 1 +
62e76326 419 4 + 1 + 3 + 2 +
5cafad19 420 header.len + 2;
2246b732 421}
99edd1c3 422
190154cf 423/* sync this routine when you update HttpRequest struct */
8596962e 424void
07947ad8 425HttpRequest::hdrCacheInit()
528b2c61 426{
07947ad8 427 HttpMsg::hdrCacheInit();
62e76326 428
66363092 429 assert(!range);
a9925b40 430 range = header.getRange();
528b2c61 431}
432
3ff65596 433#if ICAP_CLIENT
e1381638 434Adaptation::Icap::History::Pointer
3ff65596
AR
435HttpRequest::icapHistory() const
436{
437 if (!icapHistory_) {
38e16f92 438 if (Log::TheConfig.hasIcapToken || IcapLogfileStatus == LOG_ENABLE) {
3ff65596
AR
439 icapHistory_ = new Adaptation::Icap::History();
440 debugs(93,4, HERE << "made " << icapHistory_ << " for " << this);
441 }
442 }
443
444 return icapHistory_;
445}
446#endif
447
448#if USE_ADAPTATION
e1381638 449Adaptation::History::Pointer
a22e6cd3 450HttpRequest::adaptHistory(bool createIfNone) const
3ff65596 451{
a22e6cd3
AR
452 if (!adaptHistory_ && createIfNone) {
453 adaptHistory_ = new Adaptation::History();
454 debugs(93,4, HERE << "made " << adaptHistory_ << " for " << this);
3ff65596
AR
455 }
456
457 return adaptHistory_;
458}
a22e6cd3 459
e1381638 460Adaptation::History::Pointer
a22e6cd3
AR
461HttpRequest::adaptLogHistory() const
462{
38e16f92 463 return HttpRequest::adaptHistory(Log::TheConfig.hasAdaptToken);
a22e6cd3
AR
464}
465
aaf0559d
AR
466void
467HttpRequest::adaptHistoryImport(const HttpRequest &them)
468{
469 if (!adaptHistory_) {
470 adaptHistory_ = them.adaptHistory_; // may be nil
471 } else {
472 // check that histories did not diverge
473 Must(!them.adaptHistory_ || them.adaptHistory_ == adaptHistory_);
474 }
475}
476
3ff65596
AR
477#endif
478
528b2c61 479bool
190154cf 480HttpRequest::multipartRangeRequest() const
528b2c61 481{
9ad511b6 482 return (range && range->specs.size() > 1);
528b2c61 483}
8000a965 484
58217e94 485bool
9e008dda
AJ
486HttpRequest::bodyNibbled() const
487{
58217e94 488 return body_pipe != NULL && body_pipe->consumedSize() > 0;
489}
5f8252d2 490
64b66b76
CT
491void
492HttpRequest::detailError(err_type aType, int aDetail)
493{
494 if (errType || errDetail)
495 debugs(11, 5, HERE << "old error details: " << errType << '/' << errDetail);
496 debugs(11, 5, HERE << "current error details: " << aType << '/' << aDetail);
497 // checking type and detail separately may cause inconsistency, but
498 // may result in more details available if they only become available later
499 if (!errType)
500 errType = aType;
501 if (!errDetail)
502 errDetail = aDetail;
503}
504
129fe2a1
CT
505void
506HttpRequest::clearError()
507{
508 debugs(11, 7, HERE << "old error details: " << errType << '/' << errDetail);
509 errType = ERR_NONE;
510 errDetail = ERR_DETAIL_NONE;
511}
512
8596962e 513const char *HttpRequest::packableURI(bool full_uri) const
514{
515 if (full_uri)
516 return urlCanonical((HttpRequest*)this);
517
518 if (urlpath.size())
b4f2886c 519 return urlpath.termedBuf();
8596962e 520
521 return "/";
522}
523
524void HttpRequest::packFirstLineInto(Packer * p, bool full_uri) const
525{
526 // form HTTP request-line
527 packerPrintf(p, "%s %s HTTP/%d.%d\r\n",
60745f24 528 RequestMethodStr(method),
8596962e 529 packableURI(full_uri),
530 http_ver.major, http_ver.minor);
531}
8ddea643 532
533/*
684e9c80 534 * Indicate whether or not we would expect an entity-body
8ddea643 535 * along with this request
536 */
537bool
60745f24 538HttpRequest::expectingBody(const HttpRequestMethod& unused, int64_t& theSize) const
8ddea643 539{
540 bool expectBody = false;
541
542 /*
684e9c80
HN
543 * Note: Checks for message validity is in clientIsContentLengthValid().
544 * this just checks if a entity-body is expected based on HTTP message syntax
8ddea643 545 */
684e9c80 546 if (header.chunked()) {
8ddea643 547 expectBody = true;
684e9c80
HN
548 theSize = -1;
549 } else if (content_length >= 0) {
8ddea643 550 expectBody = true;
684e9c80
HN
551 theSize = content_length;
552 } else {
8ddea643 553 expectBody = false;
684e9c80 554 // theSize undefined
8ddea643 555 }
556
557 return expectBody;
558}
c21ad0f5 559
560/*
561 * Create a Request from a URL and METHOD.
562 *
563 * If the METHOD is CONNECT, then a host:port pair is looked for instead of a URL.
564 * If the request cannot be created cleanly, NULL is returned
565 */
566HttpRequest *
60745f24 567HttpRequest::CreateFromUrlAndMethod(char * url, const HttpRequestMethod& method)
c21ad0f5 568{
569 return urlParse(method, url, NULL);
570}
571
572/*
573 * Create a Request from a URL.
574 *
575 * If the request cannot be created cleanly, NULL is returned
576 */
577HttpRequest *
578HttpRequest::CreateFromUrl(char * url)
579{
c2a7cefd 580 return urlParse(Http::METHOD_GET, url, NULL);
c21ad0f5 581}
610ee341 582
c2a7cefd 583/**
610ee341 584 * Are responses to this request possible cacheable ?
585 * If false then no matter what the response must not be cached.
586 */
587bool
c2a7cefd 588HttpRequest::maybeCacheable()
610ee341 589{
2962f8b8
AJ
590 // Intercepted request with Host: header which cannot be trusted.
591 // Because it failed verification, or someone bypassed the security tests
592 // we cannot cache the reponse for sharing between clients.
593 // TODO: update cache to store for particular clients only (going to same Host: and destination IP)
0d901ef4 594 if (!flags.hostVerified && (flags.intercepted || flags.interceptTproxy))
2962f8b8
AJ
595 return false;
596
ffb82151 597 switch (protocol) {
c2a7cefd 598 case AnyP::PROTO_HTTP:
2c32c73e 599 case AnyP::PROTO_HTTPS:
c2a7cefd
AJ
600 if (!method.respMaybeCacheable())
601 return false;
9e008dda 602
c2a7cefd
AJ
603 // XXX: this would seem the correct place to detect request cache-controls
604 // no-store, private and related which block cacheability
605 break;
610ee341 606
c2a7cefd
AJ
607 case AnyP::PROTO_GOPHER:
608 if (!gopherCachable(this))
609 return false;
610 break;
610ee341 611
c2a7cefd 612 case AnyP::PROTO_CACHE_OBJECT:
60745f24 613 return false;
610ee341 614
ffb82151 615 //case AnyP::PROTO_FTP:
c2a7cefd
AJ
616 default:
617 break;
618 }
619
60745f24 620 return true;
610ee341 621}
d67acb4e 622
79c8035e
AR
623bool
624HttpRequest::conditional() const
625{
45e5102d 626 return flags.ims ||
b59e6847
A
627 header.has(HDR_IF_MATCH) ||
628 header.has(HDR_IF_NONE_MATCH);
79c8035e
AR
629}
630
d5964067
AJ
631void
632HttpRequest::recordLookup(const DnsLookupDetails &dns)
3ff65596
AR
633{
634 if (dns.wait >= 0) { // known delay
635 if (dnsWait >= 0) // have recorded DNS wait before
636 dnsWait += dns.wait;
637 else
638 dnsWait = dns.wait;
639 }
640}
11e3fa1c
AJ
641
642int64_t
643HttpRequest::getRangeOffsetLimit()
644{
645 /* -2 is the starting value of rangeOffsetLimit.
646 * If it is -2, that means we haven't checked it yet.
647 * Otherwise, return the current value */
5e5f247c 648 if (rangeOffsetLimit != -2)
11e3fa1c
AJ
649 return rangeOffsetLimit;
650
651 rangeOffsetLimit = 0; // default value for rangeOffsetLimit
652
653 ACLFilledChecklist ch(NULL, this, NULL);
654 ch.src_addr = client_addr;
655 ch.my_addr = my_addr;
656
1328cfb7 657 for (AclSizeLimit *l = Config.rangeOffsetLimit; l; l = l -> next) {
11e3fa1c 658 /* if there is no ACL list or if the ACLs listed match use this limit value */
2efeb0b7 659 if (!l->aclList || ch.fastCheck(l->aclList) == ACCESS_ALLOWED) {
11e3fa1c
AJ
660 debugs(58, 4, HERE << "rangeOffsetLimit=" << rangeOffsetLimit);
661 rangeOffsetLimit = l->size; // may be -1
662 break;
663 }
664 }
665
666 return rangeOffsetLimit;
667}
655daa06 668
f0baf149
AR
669void
670HttpRequest::ignoreRange(const char *reason)
671{
672 if (range) {
673 debugs(73, 3, static_cast<void*>(range) << " for " << reason);
674 delete range;
675 range = NULL;
676 }
677 // Some callers also reset isRanged but it may not be safe for all callers:
678 // isRanged is used to determine whether a weak ETag comparison is allowed,
679 // and that check should not ignore the Range header if it was present.
680 // TODO: Some callers also delete HDR_RANGE, HDR_REQUEST_RANGE. Should we?
681}
682
655daa06
AR
683bool
684HttpRequest::canHandle1xx() const
685{
686 // old clients do not support 1xx unless they sent Expect: 100-continue
687 // (we reject all other HDR_EXPECT values so just check for HDR_EXPECT)
526ed14e 688 if (http_ver <= Http::ProtocolVersion(1,0) && !header.has(HDR_EXPECT))
655daa06
AR
689 return false;
690
691 // others must support 1xx control messages
692 return true;
693}
582c2af2
FC
694
695ConnStateData *
b0fb853f
A
696HttpRequest::pinnedConnection()
697{
582c2af2
FC
698 if (clientConnectionManager.valid() && clientConnectionManager->pinning.pinned)
699 return clientConnectionManager.get();
700 return NULL;
701}
a8a0b1c2
EC
702
703const char *
704HttpRequest::storeId()
705{
706 if (store_id.size() != 0) {
707 debugs(73, 3, "sent back store_id:" << store_id);
708
709 return store_id.termedBuf();
710 }
711 debugs(73, 3, "sent back canonicalUrl:" << urlCanonical(this) );
712
713 return urlCanonical(this);
714}