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