35
#include "AccessLogEntry.h"
36
#include "acl/AclSizeLimit.h"
37
#include "acl/FilledChecklist.h"
38
#include "client_side.h"
39
#include "DnsLookupDetails.h"
40
#include "err_detail_type.h"
44
#include "HttpHdrCc.h"
45
#include "HttpHeaderRange.h"
38
46
#include "HttpRequest.h"
39
#include "auth/UserRequest.h"
40
#include "HttpHeaderRange.h"
47
#include "log/Config.h"
41
48
#include "MemBuf.h"
49
#include "SquidConfig.h"
54
#include "auth/UserRequest.h"
44
57
#include "adaptation/icap/icap_log.h"
52
HttpRequest::HttpRequest(const HttpRequestMethod& aMethod, protocol_t aProtocol, const char *aUrlpath) : HttpMsg(hoRequest)
65
HttpRequest::HttpRequest(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aUrlpath) : HttpMsg(hoRequest)
54
67
static unsigned int id = 1;
55
68
debugs(93,7, HERE << "constructed, this=" << this << " id=" << ++id);
67
HttpRequest::initHTTP(const HttpRequestMethod& aMethod, protocol_t aProtocol, const char *aUrlpath)
80
HttpRequest::initHTTP(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aUrlpath)
70
83
protocol = aProtocol;
75
88
HttpRequest::init()
77
90
method = METHOD_NONE;
78
protocol = PROTO_NONE;
91
protocol = AnyP::PROTO_NONE;
82
95
host_is_numeric = -1;
83
97
auth_user_request = NULL;
84
pinned_connection = NULL;
87
101
memset(&flags, '\0', sizeof(flags));
97
111
errType = ERR_NONE;
112
errDetail = ERR_DETAIL_NONE;
98
113
peer_login = NULL; // not allocated/deallocated by this class
99
114
peer_domain = NULL; // not allocated/deallocated by this class
100
115
vary_headers = NULL;
101
116
myportname = null_string;
102
117
tag = null_string;
103
119
extacl_user = null_string;
104
120
extacl_passwd = null_string;
105
122
extacl_log = null_string;
106
123
extacl_message = null_string;
107
124
pstate = psReadyToParseStartLine;
122
140
// we used to assert that the pipe is NULL, but now the request only
123
141
// points to a pipe that is owned and initiated by another object.
124
142
body_pipe = NULL;
126
AUTHUSERREQUESTUNLOCK(auth_user_request, "request");
144
auth_user_request = NULL;
128
146
safe_free(canonical);
130
148
safe_free(vary_headers);
209
223
copy->myportname = myportname;
211
226
copy->extacl_user = extacl_user;
212
227
copy->extacl_passwd = extacl_passwd;
213
229
copy->extacl_log = extacl_log;
214
230
copy->extacl_message = extacl_message;
238
HttpRequest::inheritProperties(const HttpMsg *aMsg)
240
const HttpRequest* aReq = dynamic_cast<const HttpRequest*>(aMsg);
244
client_addr = aReq->client_addr;
245
#if FOLLOW_X_FORWARDED_FOR
246
indirect_client_addr = aReq->indirect_client_addr;
248
my_addr = aReq->my_addr;
250
dnsWait = aReq->dnsWait;
253
adaptHistory_ = aReq->adaptHistory();
256
icapHistory_ = aReq->icapHistory();
259
// This may be too conservative for the 204 No Content case
260
// may eventually need cloneNullAdaptationImmune() for that.
261
flags = aReq->flags.cloneAdaptationImmune();
263
errType = aReq->errType;
264
errDetail = aReq->errDetail;
266
auth_user_request = aReq->auth_user_request;
269
// main property is which connection the request was received on (if any)
270
clientConnectionManager = aReq->clientConnectionManager;
222
276
* Checks the first line of an HTTP request is valid
223
277
* currently just checks the request method is present.
267
321
while (xisspace(*end)) // find prev non-space
270
end++; // back to space
324
++end; // back to space
272
326
if (2 != sscanf(ver + 5, "%d.%d", &http_ver.major, &http_ver.minor)) {
273
debugs(73, 1, "parseRequestLine: Invalid HTTP identifier.");
327
debugs(73, DBG_IMPORTANT, "parseRequestLine: Invalid HTTP identifier.");
367
421
range = header.getRange();
372
request_flags::resetTCP() const
374
return reset_tcp != 0;
378
request_flags::setResetTCP()
380
debugs(73, 9, "request_flags::setResetTCP");
385
request_flags::clearResetTCP()
387
debugs(73, 9, "request_flags::clearResetTCP");
392
425
Adaptation::Icap::History::Pointer
393
426
HttpRequest::icapHistory() const
395
428
if (!icapHistory_) {
396
if ((LogfileStatus == LOG_ENABLE && alLogformatHasIcapToken) ||
397
IcapLogfileStatus == LOG_ENABLE) {
429
if (Log::TheConfig.hasIcapToken || IcapLogfileStatus == LOG_ENABLE) {
398
430
icapHistory_ = new Adaptation::Icap::History();
399
431
debugs(93,4, HERE << "made " << icapHistory_ << " for " << this);
419
451
Adaptation::History::Pointer
420
452
HttpRequest::adaptLogHistory() const
422
const bool loggingNeedsHistory = (LogfileStatus == LOG_ENABLE) &&
423
alLogformatHasAdaptToken; // TODO: make global to remove this method?
424
return HttpRequest::adaptHistory(loggingNeedsHistory);
454
return HttpRequest::adaptHistory(Log::TheConfig.hasAdaptToken);
458
HttpRequest::adaptHistoryImport(const HttpRequest &them)
460
if (!adaptHistory_) {
461
adaptHistory_ = them.adaptHistory_; // may be nil
463
// check that histories did not diverge
464
Must(!them.adaptHistory_ || them.adaptHistory_ == adaptHistory_);
432
473
return (range && range->specs.count > 1);
436
request_flags::destinationIPLookupCompleted()
438
destinationIPLookedUp_ = true;
442
request_flags::destinationIPLookedUp() const
444
return destinationIPLookedUp_;
448
request_flags::cloneAdaptationImmune() const
450
// At the time of writing, all flags where either safe to copy after
451
// adaptation or were not set at the time of the adaptation. If there
452
// are flags that are different, they should be cleared in the clone.
457
477
HttpRequest::bodyNibbled() const
459
479
return body_pipe != NULL && body_pipe->consumedSize() > 0;
483
HttpRequest::detailError(err_type aType, int aDetail)
485
if (errType || errDetail)
486
debugs(11, 5, HERE << "old error details: " << errType << '/' << errDetail);
487
debugs(11, 5, HERE << "current error details: " << aType << '/' << aDetail);
488
// checking type and detail separately may cause inconsistency, but
489
// may result in more details available if they only become available later
497
HttpRequest::clearError()
499
debugs(11, 7, HERE << "old error details: " << errType << '/' << errDetail);
501
errDetail = ERR_DETAIL_NONE;
462
504
const char *HttpRequest::packableURI(bool full_uri) const
537
579
HttpRequest::cacheable() const
539
if (protocol == PROTO_HTTP)
581
// Intercepted request with Host: header which cannot be trusted.
582
// Because it failed verification, or someone bypassed the security tests
583
// we cannot cache the reponse for sharing between clients.
584
// TODO: update cache to store for particular clients only (going to same Host: and destination IP)
585
if (!flags.hostVerified && (flags.intercepted || flags.spoofClientIp))
588
if (protocol == AnyP::PROTO_HTTP)
540
589
return httpCachable(method);
551
600
* XXX POST may be cached sometimes.. ignored
554
if (protocol == PROTO_GOPHER)
603
if (protocol == AnyP::PROTO_GOPHER)
555
604
return gopherCachable(this);
557
if (protocol == PROTO_CACHEOBJ)
606
if (protocol == AnyP::PROTO_CACHE_OBJECT)
568
617
header.has(HDR_IF_NONE_MATCH);
571
bool HttpRequest::inheritProperties(const HttpMsg *aMsg)
573
const HttpRequest* aReq = dynamic_cast<const HttpRequest*>(aMsg);
577
client_addr = aReq->client_addr;
578
#if FOLLOW_X_FORWARDED_FOR
579
indirect_client_addr = aReq->indirect_client_addr;
581
my_addr = aReq->my_addr;
583
dnsWait = aReq->dnsWait;
586
adaptHistory_ = aReq->adaptHistory();
589
icapHistory_ = aReq->icapHistory();
592
// This may be too conservative for the 204 No Content case
593
// may eventually need cloneNullAdaptationImmune() for that.
594
flags = aReq->flags.cloneAdaptationImmune();
596
if (aReq->auth_user_request) {
597
auth_user_request = aReq->auth_user_request;
598
AUTHUSERREQUESTLOCK(auth_user_request, "inheritProperties");
601
if (aReq->pinned_connection) {
602
pinned_connection = cbdataReference(aReq->pinned_connection);
607
void HttpRequest::recordLookup(const DnsLookupDetails &dns)
621
HttpRequest::recordLookup(const DnsLookupDetails &dns)
609
623
if (dns.wait >= 0) { // known delay
610
624
if (dnsWait >= 0) // have recorded DNS wait before
613
627
dnsWait = dns.wait;
632
HttpRequest::getRangeOffsetLimit()
634
/* -2 is the starting value of rangeOffsetLimit.
635
* If it is -2, that means we haven't checked it yet.
636
* Otherwise, return the current value */
637
if (rangeOffsetLimit != -2)
638
return rangeOffsetLimit;
640
rangeOffsetLimit = 0; // default value for rangeOffsetLimit
642
ACLFilledChecklist ch(NULL, this, NULL);
643
ch.src_addr = client_addr;
644
ch.my_addr = my_addr;
646
for (AclSizeLimit *l = Config.rangeOffsetLimit; l; l = l -> next) {
647
/* if there is no ACL list or if the ACLs listed match use this limit value */
648
if (!l->aclList || ch.fastCheck(l->aclList) == ACCESS_ALLOWED) {
649
debugs(58, 4, HERE << "rangeOffsetLimit=" << rangeOffsetLimit);
650
rangeOffsetLimit = l->size; // may be -1
655
return rangeOffsetLimit;
659
HttpRequest::canHandle1xx() const
661
// old clients do not support 1xx unless they sent Expect: 100-continue
662
// (we reject all other HDR_EXPECT values so just check for HDR_EXPECT)
663
if (http_ver <= HttpVersion(1,0) && !header.has(HDR_EXPECT))
666
// others must support 1xx control messages
671
HttpRequest::pinnedConnection()
673
if (clientConnectionManager.valid() && clientConnectionManager->pinning.pinned)
674
return clientConnectionManager.get();