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