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