Squid Web Cache v8/master
Loading...
Searching...
No Matches
HttpRequest.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9/* DEBUG: section 73 HTTP Request */
10
11#include "squid.h"
12#include "AccessLogEntry.h"
13#include "acl/AclSizeLimit.h"
14#include "acl/FilledChecklist.h"
15#include "CachePeer.h"
16#include "client_side.h"
17#include "client_side_request.h"
18#include "dns/LookupDetails.h"
19#include "Downloader.h"
20#include "error/Detail.h"
21#include "globals.h"
22#include "http.h"
25#include "http/Stream.h"
26#include "HttpHdrCc.h"
27#include "HttpHeaderRange.h"
28#include "HttpRequest.h"
29#include "log/Config.h"
30#include "MemBuf.h"
31#include "sbuf/StringConvert.h"
32#include "SquidConfig.h"
33#include "Store.h"
34
35#if USE_AUTH
36#include "auth/UserRequest.h"
37#endif
38#if ICAP_CLIENT
40#endif
41
43 Http::Message(hoRequest),
44 masterXaction(mx)
45{
46 assert(mx);
47 init();
48}
49
50HttpRequest::HttpRequest(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aSchemeImg, const char *aUrlpath, const MasterXaction::Pointer &mx) :
51 Http::Message(hoRequest),
52 masterXaction(mx)
53{
54 assert(mx);
55 static unsigned int id = 1;
56 debugs(93,7, "constructed, this=" << this << " id=" << ++id);
57 init();
58 initHTTP(aMethod, aProtocol, aSchemeImg, aUrlpath);
59}
60
62{
63 clean();
64 debugs(93,7, "destructed, this=" << this);
65}
66
67void
68HttpRequest::initHTTP(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aSchemeImg, const char *aUrlpath)
69{
70 method = aMethod;
71 url.setScheme(aProtocol, aSchemeImg);
72 url.path(aUrlpath);
73}
74
75void
77{
79 url.clear();
80#if USE_AUTH
81 auth_user_request = nullptr;
82#endif
84 range = nullptr;
85 ims = -1;
86 imslen = 0;
87 lastmod = -1;
90 body_pipe = nullptr;
91 // hier
92 dnsWait = -1;
93 error.clear();
94 peer_login = nullptr; // not allocated/deallocated by this class
95 peer_domain = nullptr; // not allocated/deallocated by this class
99#if USE_AUTH
102#endif
106#if FOLLOW_X_FORWARDED_FOR
108#endif /* FOLLOW_X_FORWARDED_FOR */
109#if USE_ADAPTATION
110 adaptHistory_ = nullptr;
111#endif
112#if ICAP_CLIENT
113 icapHistory_ = nullptr;
114#endif
115 rangeOffsetLimit = -2; //a value of -2 means not checked yet
117}
118
119void
121{
122 // we used to assert that the pipe is NULL, but now the request only
123 // points to a pipe that is owned and initiated by another object.
124 body_pipe = nullptr;
125#if USE_AUTH
126 auth_user_request = nullptr;
127#endif
129 url.clear();
130
131 header.clean();
132
133 if (cache_control) {
134 delete cache_control;
135 cache_control = nullptr;
136 }
137
138 if (range) {
139 delete range;
140 range = nullptr;
141 }
142
144
145 theNotes = nullptr;
146
147 tag.clean();
148#if USE_AUTH
151#endif
153
155
156 etag.clean();
157
158#if USE_ADAPTATION
159 adaptHistory_ = nullptr;
160#endif
161#if ICAP_CLIENT
162 icapHistory_ = nullptr;
163#endif
164}
165
166void
168{
169 clean();
170 init();
171}
172
175{
177 copy->method = method;
178 // TODO: move common cloning clone to Msg::copyTo() or copy ctor
179 copy->header.append(&header);
180 copy->hdrCacheInit();
181 copy->hdr_sz = hdr_sz;
182 copy->http_ver = http_ver;
183 copy->pstate = pstate; // TODO: should we assert a specific state here?
184 copy->body_pipe = body_pipe;
185
186 copy->url = url;
187
188 // range handled in hdrCacheInit()
189 copy->ims = ims;
190 copy->imslen = imslen;
191 copy->hier = hier; // Is it safe to copy? Should we?
192
193 copy->error = error;
194
195 // XXX: what to do with copy->peer_login?
196
197 copy->lastmod = lastmod;
198 copy->etag = etag;
200 // XXX: what to do with copy->peer_domain?
201
202 copy->tag = tag;
203 copy->extacl_log = extacl_log;
205
206 const bool inheritWorked = copy->inheritProperties(this);
207 assert(inheritWorked);
208
209 return copy;
210}
211
212bool
214{
215 const HttpRequest* aReq = dynamic_cast<const HttpRequest*>(aMsg);
216 if (!aReq)
217 return false;
218
219 client_addr = aReq->client_addr;
220#if FOLLOW_X_FORWARDED_FOR
222#endif
223 my_addr = aReq->my_addr;
224
225 dnsWait = aReq->dnsWait;
226
227#if USE_ADAPTATION
228 adaptHistory_ = aReq->adaptHistory();
229#endif
230#if ICAP_CLIENT
231 icapHistory_ = aReq->icapHistory();
232#endif
233
234 // This may be too conservative for the 204 No Content case
235 // may eventually need cloneNullAdaptationImmune() for that.
237
238 error = aReq->error;
239#if USE_AUTH
241 extacl_user = aReq->extacl_user;
243#endif
244
245 myportname = aReq->myportname;
246
248
249 // main property is which connection the request was received on (if any)
251
252 downloader = aReq->downloader;
253
254 theNotes = aReq->theNotes;
255
256 sources = aReq->sources;
257 return true;
258}
259
266bool
267HttpRequest::sanityCheckStartLine(const char *buf, const size_t hdr_len, Http::StatusCode *scode)
268{
269 // content is long enough to possibly hold a reply
270 // 2 being magic size of a 1-byte request method plus space delimiter
271 if (hdr_len < 2) {
272 // this is only a real error if the headers apparently complete.
273 if (hdr_len > 0) {
274 debugs(58, 3, "Too large request header (" << hdr_len << " bytes)");
275 *scode = Http::scInvalidHeader;
276 }
277 return false;
278 }
279
280 /* See if the request buffer starts with a non-whitespace HTTP request 'method'. */
283 if (m == Http::METHOD_NONE) {
284 debugs(73, 3, "HttpRequest::sanityCheckStartLine: did not find HTTP request method");
285 *scode = Http::scInvalidHeader;
286 return false;
287 }
288
289 return true;
290}
291
292bool
293HttpRequest::parseFirstLine(const char *start, const char *end)
294{
296
298 return false;
299
300 // XXX: performance regression, strcspn() over the method bytes a second time.
301 // cheaper than allocate+copy+deallocate cycle to SBuf convert a piece of start.
302 const char *t = start + strcspn(start, w_space);
303
304 start = t + strspn(t, w_space); // skip w_space after method
305
306 const char *ver = findTrailingHTTPVersion(start, end);
307
308 if (ver) {
309 end = ver - 1;
310
311 while (xisspace(*end)) // find prev non-space
312 --end;
313
314 ++end; // back to space
315
316 if (2 != sscanf(ver + 5, "%d.%d", &http_ver.major, &http_ver.minor)) {
317 debugs(73, DBG_IMPORTANT, "ERROR: parseRequestLine: Invalid HTTP identifier.");
318 return false;
319 }
320 } else {
321 http_ver.major = 0;
322 http_ver.minor = 9;
323 }
324
325 if (end < start) // missing URI
326 return false;
327
328 return url.parse(method, SBuf(start, size_t(end-start)));
329}
330
331/* swaps out request using httpRequestPack */
332void
334{
335 assert(e);
336 e->buffer();
337 pack(e);
338 e->flush();
339}
340
341/* packs request-line and headers, appends <crlf> terminator */
342void
343HttpRequest::pack(Packable * const p, const bool maskSensitiveInfo) const
344{
345 assert(p);
346 /* pack request-line */
347 packFirstLineInto(p, false /* origin-form */);
348 /* headers */
349 header.packInto(p, maskSensitiveInfo);
350 /* indicate the end of the header section */
351 p->append("\r\n", 2);
352}
353
354/*
355 * A wrapper for debugObj()
356 */
357void
359{
360 HttpRequest *request = static_cast<HttpRequest*>(obj);
361 request->pack(p);
362}
363
364/* returns the length of request line + headers + crlf */
365int
367{
368 return method.image().length() + 1 +
369 url.originForm().length() + 1 +
370 4 + 1 + 3 + 2 +
371 header.len + 2;
372}
373
374/* sync this routine when you update HttpRequest struct */
375void
383
384#if ICAP_CLIENT
387{
388 if (!icapHistory_) {
389 if (Log::TheConfig.hasIcapToken || IcapLogfileStatus == LOG_ENABLE) {
391 debugs(93,4, "made " << icapHistory_ << " for " << this);
392 }
393 }
394
395 return icapHistory_;
396}
397#endif
398
399#if USE_ADAPTATION
401HttpRequest::adaptHistory(bool createIfNone) const
402{
403 if (!adaptHistory_ && createIfNone) {
405 debugs(93,4, "made " << adaptHistory_ << " for " << this);
406 }
407
408 return adaptHistory_;
409}
410
413{
414 return HttpRequest::adaptHistory(Log::TheConfig.hasAdaptToken);
415}
416
417void
419{
420 if (!adaptHistory_) {
421 adaptHistory_ = them.adaptHistory_; // may be nil
422 } else {
423 // check that histories did not diverge
425 }
426}
427
428#endif
429
430bool
432{
433 return (range && range->specs.size() > 1);
434}
435
436bool
438{
439 return body_pipe != nullptr && body_pipe->consumedSize() > 0;
440}
441
442void
444{
445 // XXX: Saving two pointers to memory controlled by an independent object.
446 peer_login = peer.login;
447 peer_domain = peer.domain;
449 debugs(11, 4, this << " to " << peer);
450}
451
452void
454{
455 peer_login = nullptr;
456 peer_domain = nullptr;
457 flags.auth_no_keytab = false;
458 debugs(11, 4, this);
459}
460
461void
463{
464 debugs(11, 7, "old: " << error);
465 error.clear();
466}
467
468void
470{
471 const SBuf tmp(full_uri ? effectiveRequestUri() : url.originForm());
472
473 // form HTTP request-line
474 p->appendf(SQUIDSBUFPH " " SQUIDSBUFPH " HTTP/%d.%d\r\n",
476 SQUIDSBUFPRINT(tmp),
478}
479
480/*
481 * Indicate whether or not we would expect an entity-body
482 * along with this request
483 */
484bool
485HttpRequest::expectingBody(const HttpRequestMethod &, int64_t &theSize) const
486{
487 bool expectBody = false;
488
489 /*
490 * Note: Checks for message validity is in clientIsContentLengthValid().
491 * this just checks if a entity-body is expected based on HTTP message syntax
492 */
493 if (header.chunked()) {
494 expectBody = true;
495 theSize = -1;
496 } else if (content_length >= 0) {
497 expectBody = true;
498 theSize = content_length;
499 } else {
500 expectBody = false;
501 // theSize undefined
502 }
503
504 return expectBody;
505}
506
507/*
508 * Create a Request from a URL and METHOD.
509 *
510 * If the METHOD is CONNECT, then a host:port pair is looked for instead of a URL.
511 * If the request cannot be created cleanly, NULL is returned
512 */
515{
516 std::unique_ptr<HttpRequest> req(new HttpRequest(mx));
517 if (req->url.parse(method, url)) {
518 req->method = method;
519 return req.release();
520 }
521 return nullptr;
522}
523
525HttpRequest::FromUrlXXX(const char * url, const MasterXaction::Pointer &mx, const HttpRequestMethod& method)
526{
527 return FromUrl(SBuf(url), mx, method);
528}
529
534bool
536{
537 // Intercepted request with Host: header which cannot be trusted.
538 // Because it failed verification, or someone bypassed the security tests
539 // we cannot cache the response for sharing between clients.
540 // TODO: update cache to store for particular clients only (going to same Host: and destination IP)
542 return false;
543
544 switch (url.getScheme()) {
545 case AnyP::PROTO_HTTP:
548 return false;
549
550 // RFC 9111 section 5.2.1.5:
551 // "The no-store request directive indicates that a cache MUST NOT
552 // store any part of either this request or any response to it."
553 //
554 // NP: refresh_pattern ignore-no-store only applies to response messages
555 // this test is handling request message CC header.
557 return false;
558 break;
559
560 //case AnyP::PROTO_FTP:
561 default:
562 break;
563 }
564
565 return true;
566}
567
568bool
575
576void
578{
579 if (dns.wait >= 0) { // known delay
580 if (dnsWait >= 0) { // have recorded DNS wait before
581 debugs(78, 7, this << " " << dnsWait << " += " << dns);
582 dnsWait += dns.wait;
583 } else {
584 debugs(78, 7, this << " " << dns);
585 dnsWait = dns.wait;
586 }
587 }
588}
589
590int64_t
592{
593 /* -2 is the starting value of rangeOffsetLimit.
594 * If it is -2, that means we haven't checked it yet.
595 * Otherwise, return the current value */
596 if (rangeOffsetLimit != -2)
597 return rangeOffsetLimit;
598
599 rangeOffsetLimit = 0; // default value for rangeOffsetLimit
600
601 ACLFilledChecklist ch(nullptr, this);
603 ch.my_addr = my_addr;
604
605 for (AclSizeLimit *l = Config.rangeOffsetLimit; l; l = l -> next) {
606 /* if there is no ACL list or if the ACLs listed match use this limit value */
607 if (!l->aclList || ch.fastCheck(l->aclList).allowed()) {
608 rangeOffsetLimit = l->size; // may be -1
609 debugs(58, 4, rangeOffsetLimit);
610 break;
611 }
612 }
613
614 return rangeOffsetLimit;
615}
616
617void
618HttpRequest::ignoreRange(const char *reason)
619{
620 if (range) {
621 debugs(73, 3, static_cast<void*>(range) << " for " << reason);
622 delete range;
623 range = nullptr;
624 }
625 // Some callers also reset isRanged but it may not be safe for all callers:
626 // isRanged is used to determine whether a weak ETag comparison is allowed,
627 // and that check should not ignore the Range header if it was present.
628 // TODO: Some callers also delete HDR_RANGE, HDR_REQUEST_RANGE. Should we?
629}
630
631bool
633{
634 // old clients do not support 1xx unless they sent Expect: 100-continue
635 // (we reject all other Http::HdrType::EXPECT values so just check for Http::HdrType::EXPECT)
637 return false;
638
639 // others must support 1xx control messages
640 return true;
641}
642
645{
646 // RFC 7230 section 3.3.1:
647 // "
648 // A server that receives a request message with a transfer coding it
649 // does not understand SHOULD respond with 501 (Not Implemented).
650 // "
651 if (header.unsupportedTe())
653
654 // RFC 7230 section 3.3.3 #3 paragraph 3:
655 // Transfer-Encoding overrides Content-Length
656 if (header.chunked())
657 return Http::scNone;
658
659 // RFC 7230 Section 3.3.3 #4:
660 // conflicting Content-Length(s) mean a message framing error
662 return Http::scBadRequest;
663
664 // HTTP/1.0 requirements differ from HTTP/1.1
665 if (http_ver <= Http::ProtocolVersion(1,0)) {
666 const auto m = method.id();
667
668 // RFC 1945 section 8.3:
669 // "
670 // A valid Content-Length is required on all HTTP/1.0 POST requests.
671 // "
672 // RFC 1945 Appendix D.1.1:
673 // "
674 // The fundamental difference between the POST and PUT requests is
675 // reflected in the different meaning of the Request-URI.
676 // "
677 if (m == Http::METHOD_POST || m == Http::METHOD_PUT)
679
680 // RFC 1945 section 7.2:
681 // "
682 // An entity body is included with a request message only when the
683 // request method calls for one.
684 // "
685 // section 8.1-2: GET and HEAD do not define ('call for') an entity
686 if (m == Http::METHOD_GET || m == Http::METHOD_HEAD)
688 // appendix D1.1.2-4: DELETE, LINK, UNLINK do not define ('call for') an entity
691
692 // other methods are not defined in RFC 1945
693 // assume they support an (optional) entity
694 return Http::scNone;
695 }
696
697 // RFC 7230 section 3.3
698 // "
699 // The presence of a message body in a request is signaled by a
700 // Content-Length or Transfer-Encoding header field. Request message
701 // framing is independent of method semantics, even if the method does
702 // not define any use for a message body.
703 // "
704 return Http::scNone;
705}
706
707bool
709{
711 return Message::parseHeader(hp, clen);
712}
713
714bool
715HttpRequest::parseHeader(const char *buffer, const size_t size)
716{
718 return header.parse(buffer, size, clen);
719}
720
728
729const SBuf
731{
732 if (store_id.size() != 0) {
733 debugs(73, 3, "sent back store_id: " << store_id);
734 return StringToSBuf(store_id);
735 }
736 debugs(73, 3, "sent back effectiveRequestUrl: " << effectiveRequestUri());
737 return effectiveRequestUri();
738}
739
740const SBuf &
742{
744 return url.authority(true); // host:port
745 return url.absolute();
746}
747
750{
751 if (!theNotes)
752 theNotes = new NotePairs;
753 return theNotes;
754}
755
756void
757UpdateRequestNotes(ConnStateData *csd, HttpRequest &request, NotePairs const &helperNotes)
758{
759 // Tag client connection if the helper responded with clt_conn_tag=tag.
760 const char *cltTag = "clt_conn_tag";
761 if (const char *connTag = helperNotes.findFirst(cltTag)) {
762 if (csd) {
763 csd->notes()->remove(cltTag);
764 csd->notes()->add(cltTag, connTag);
765 }
766 }
767 request.notes()->replaceOrAdd(&helperNotes);
768}
769
770void
772{
774
776 return;
777
779 if (port) {
780 myportname = port->name;
781 flags.ignoreCc = port->ignore_cc;
782 }
783
784 if (auto clientConnection = clientConnectionManager->clientConnection) {
785 client_addr = clientConnection->remote; // XXX: remove request->client_addr member.
786#if FOLLOW_X_FORWARDED_FOR
787 // indirect client gets stored here because it is an HTTP header result (from X-Forwarded-For:)
788 // not details about the TCP connection itself
789 indirect_client_addr = clientConnection->remote;
790#endif /* FOLLOW_X_FORWARDED_FOR */
791 my_addr = clientConnection->local;
792
793 flags.intercepted = ((clientConnection->flags & COMM_INTERCEPTION) != 0);
794 flags.interceptTproxy = ((clientConnection->flags & COMM_TRANSPARENT) != 0 ) ;
795 const bool proxyProtocolPort = port ? port->flags.proxySurrogate : false;
796 if (flags.interceptTproxy && !proxyProtocolPort) {
799 checklist.al = al;
800 checklist.syncAle(this, nullptr);
801 flags.spoofClientIp = checklist.fastCheck().allowed();
802 } else
803 flags.spoofClientIp = true;
804 } else
805 flags.spoofClientIp = false;
806 }
807}
808
809char *
814
816template <typename Filter>
817static const Ip::Address *
819{
820 return (port && isGood(port->s)) ? &port->s : nullptr;
821}
822
824template <typename Filter>
825static const Ip::Address *
827{
828 return (conn && isGood(conn->local)) ? &conn->local : nullptr;
829}
830
831template <typename Filter>
832const Ip::Address *
833FindGoodListeningPortAddress(const HttpRequest *callerRequest, const AccessLogEntry *ale, const Filter filter)
834{
835 // Check all sources of usable listening port information, giving
836 // HttpRequest and masterXaction a preference over ALE.
837
838 const HttpRequest *request = callerRequest;
839 if (!request && ale)
840 request = ale->request;
841 if (!request)
842 return nullptr; // not enough information
843
845 if (!ip && ale)
847
848 // XXX: also handle PROXY protocol here when we have a flag to identify such request
849 if (ip || request->flags.interceptTproxy || request->flags.intercepted)
850 return ip;
851
852 /* handle non-intercepted cases that were not handled above */
854 if (!ip && ale)
856 return ip; // may still be nil
857}
858
859const Ip::Address *
860FindListeningPortAddress(const HttpRequest *callerRequest, const AccessLogEntry *ale)
861{
862 return FindGoodListeningPortAddress(callerRequest, ale, [](const Ip::Address &address) {
863 // FindListeningPortAddress() callers do not want INADDR_ANY addresses
864 return !address.isAnyAddr();
865 });
866}
867
869FindListeningPortNumber(const HttpRequest *callerRequest, const AccessLogEntry *ale)
870{
871 const auto ip = FindGoodListeningPortAddress(callerRequest, ale, [](const Ip::Address &address) {
872 return address.port() > 0;
873 });
874
875 if (!ip)
876 return std::nullopt;
877
878 Assure(ip->port() > 0);
879 return ip->port();
880}
#define Assure(condition)
Definition Assure.h:35
#define COMM_TRANSPARENT
Definition Connection.h:50
#define COMM_INTERCEPTION
Definition Connection.h:51
@ hoRequest
Definition HttpHeader.h:36
const Ip::Address * FindGoodListeningPortAddress(const HttpRequest *callerRequest, const AccessLogEntry *ale, const Filter filter)
void UpdateRequestNotes(ConnStateData *csd, HttpRequest &request, NotePairs const &helperNotes)
static const Ip::Address * FindGoodListeningPortAddressInPort(const AnyP::PortCfgPointer &port, const Filter isGood)
a helper for handling PortCfg cases of FindListeningPortAddress()
AnyP::Port FindListeningPortNumber(const HttpRequest *callerRequest, const AccessLogEntry *ale)
const Ip::Address * FindListeningPortAddress(const HttpRequest *callerRequest, const AccessLogEntry *ale)
void httpRequestPack(void *obj, Packable *p)
static const Ip::Address * FindGoodListeningPortAddressInConn(const Comm::ConnectionPointer &conn, const Filter isGood)
a helper for handling Connection cases of FindListeningPortAddress()
int size
Definition ModDevPoll.cc:70
#define SQUIDSBUFPH
Definition SBuf.h:31
#define SQUIDSBUFPRINT(s)
Definition SBuf.h:32
class SquidConfig Config
SBuf StringToSBuf(const String &s)
create a new SBuf from a String by copying contents
#define Must(condition)
char * urlCanonicalCleanWithoutRequest(const SBuf &url, const HttpRequestMethod &method, const AnyP::UriScheme &scheme)
Definition Uri.cc:790
#define assert(EX)
Definition assert.h:17
Acl::Answer const & fastCheck()
Definition Checklist.cc:298
AccessLogEntry::Pointer al
info for the future access.log, and external ACL
void syncAle(HttpRequest *adaptedRequest, const char *logUri) const override
assigns uninitialized adapted_request and url ALE components
AnyP::PortCfgPointer port
class AccessLogEntry::CacheDetails cache
Comm::ConnectionPointer tcpClient
TCP/IP level details about the client connection.
HttpRequest * request
representation of a class of Size-limit ACLs
bool allowed() const
Definition Acl.h:82
collects information about adaptations related to a master transaction
Definition History.h:25
collects information about ICAP processing related to an HTTP transaction
Definition History.h:24
unsigned int major
major version number
unsigned int minor
minor version number
AnyP::UriScheme const & getScheme() const
Definition Uri.h:58
void clear()
Definition Uri.h:43
SBuf & authority(bool requirePort=false) const
Definition Uri.cc:721
void setScheme(const AnyP::ProtocolType &p, const char *str)
convert the URL scheme to that given
Definition Uri.h:61
void path(const char *p)
Definition Uri.h:96
SBuf & originForm() const
The RFC 7230 origin-form URI for currently stored values.
Definition Uri.h:154
SBuf & absolute() const
Definition Uri.cc:743
bool parse(const HttpRequestMethod &, const SBuf &url)
Definition Uri.cc:326
uint64_t consumedSize() const
Definition BodyPipe.h:111
struct CachePeer::@20 options
char * login
Definition CachePeer.h:202
char * domain
Forced domain.
Definition CachePeer.h:215
bool auth_no_keytab
Definition CachePeer.h:147
Cbc * valid() const
was set and is valid
Definition CbcPointer.h:41
Cbc * get() const
a temporary valid raw Cbc pointer or NULL
Definition CbcPointer.h:159
Ip::Address local
Definition Connection.h:149
struct ConnStateData::@29 pinning
bool pinned
this connection was pinned
AnyP::Port port
destination port of the request that caused serverConnection
NotePairs::Pointer notes()
encapsulates DNS lookup results
int wait
msecs spent waiting for the lookup (if any) or -1 (if none)
void clear()
switch to the default "no error information" state
Definition Error.h:53
bool hasNoStore() const
Definition HttpHdrCc.h:102
std::vector< HttpHdrRangeSpec * > specs
bool chunked() const
Definition HttpHeader.h:169
bool unsupportedTe() const
whether message used an unsupported and/or invalid Transfer-Encoding
Definition HttpHeader.h:172
int parse(const char *header_start, size_t len, Http::ContentLengthInterpreter &interpreter)
HttpHdrRange * getRange() const
int has(Http::HdrType id) const
bool conflictingContentLength() const
Definition HttpHeader.h:113
void clean()
void packInto(Packable *p, bool mask_sensitive_info=false) const
void append(const HttpHeader *src)
void HttpRequestMethodXXX(char const *)
const SBuf & image() const
bool respMaybeCacheable() const
Http::MethodType id() const
String extacl_log
void recordLookup(const Dns::LookupDetails &detail)
bool conditional() const
has at least one recognized If-* header
HttpHdrRange * range
CbcPointer< ConnStateData > clientConnectionManager
Adaptation::History::Pointer adaptHistory(bool createIfNone=false) const
Returns possibly nil history, creating it if requested.
MasterXaction::Pointer masterXaction
the master transaction this request belongs to. Never nil.
void clearError()
clear error details, useful for retries/repeats
void prepForDirect()
get ready to be sent directly to an origin server, excluding originserver
void prepForPeering(const CachePeer &peer)
get ready to be sent to the given cache_peer, including originserver
HttpRequestMethod method
void initHTTP(const HttpRequestMethod &aMethod, AnyP::ProtocolType aProtocol, const char *schemeImage, const char *aUrlpath)
int64_t getRangeOffsetLimit()
String myportname
HttpRequest * clone() const override
bool inheritProperties(const Http::Message *) override
int prefixLen() const
Ip::Address indirect_client_addr
static HttpRequest * FromUrlXXX(const char *url, const MasterXaction::Pointer &, const HttpRequestMethod &method=Http::METHOD_GET)
bool parseHeader(Http1::Parser &hp)
String extacl_user
void packFirstLineInto(Packable *p, bool full_uri) const override
bool sanityCheckStartLine(const char *buf, const size_t hdr_len, Http::StatusCode *error) override
bool multipartRangeRequest() const
void pack(Packable *p, bool maskSensitiveInfo=false) const
HierarchyLogEntry hier
time_t lastmod
String extacl_message
Adaptation::Icap::History::Pointer icapHistory_
per-HTTP transaction info
String store_id
RequestFlags flags
String extacl_passwd
int64_t rangeOffsetLimit
bool forcedBodyContinuation
whether we have responded with HTTP 100 or FTP 150 already
bool parseFirstLine(const char *start, const char *end) override
char * peer_domain
NotePairs::Pointer notes()
bool bodyNibbled() const
SBuf vary_headers
The variant second-stage cache key. Generated from Vary header pattern for this request.
String etag
A strong etag of the cached entry. Used for refreshing that entry.
Adaptation::History::Pointer adaptHistory_
per-HTTP transaction info
~HttpRequest() override
CbcPointer< Downloader > downloader
The Downloader object which initiated the HTTP request if any.
ConnStateData * pinnedConnection()
int dnsWait
sum of DNS lookup delays in milliseconds, for dt
void ignoreRange(const char *reason)
forgets about the cached Range header (for a reason)
NotePairs::Pointer theNotes
char * peer_login
const SBuf storeId()
bool maybeCacheable()
void adaptHistoryImport(const HttpRequest &them)
Makes their history ours, throwing on conflicts.
void swapOut(StoreEntry *e)
void hdrCacheInit() override
char * canonicalCleanUrl() const
Ip::Address my_addr
void reset() override
Adaptation::History::Pointer adaptLogHistory() const
Returns possibly nil history, creating it if adapt. logging is enabled.
Auth::UserRequest::Pointer auth_user_request
bool expectingBody(const HttpRequestMethod &unused, int64_t &) const override
bool canHandle1xx() const
whether the client is likely to be able to handle a 1xx reply
HttpRequest(const MasterXaction::Pointer &)
static HttpRequest * FromUrl(const SBuf &url, const MasterXaction::Pointer &, const HttpRequestMethod &method=Http::METHOD_GET)
Http::StatusCode checkEntityFraming() const
Error error
the first transaction problem encountered (or falsy)
Adaptation::Icap::History::Pointer icapHistory() const
Returns possibly nil history, creating it if icap logging is enabled.
AnyP::Uri url
the request URI
Ip::Address client_addr
void manager(const CbcPointer< ConnStateData > &aMgr, const AccessLogEntryPointer &al)
associates the request with a from-client connection manager
const SBuf & effectiveRequestUri() const
RFC 7230 section 5.5 - Effective Request URI.
common parts of HttpRequest and HttpReply
Definition Message.h:26
virtual void hdrCacheInit()
Definition Message.cc:261
uint32_t sources
The message sources.
Definition Message.h:99
@ psReadyToParseStartLine
Definition Message.h:87
HttpHeader header
Definition Message.h:74
ParseState pstate
the current parsing state
Definition Message.h:94
int64_t content_length
Definition Message.h:83
BodyPipe::Pointer body_pipe
optional pipeline to receive message body
Definition Message.h:97
HttpHdrCc * cache_control
Definition Message.h:76
AnyP::ProtocolVersion http_ver
Definition Message.h:72
void setEmpty()
Fast reset of the stored content to what would be after default constructor.
Definition Address.cc:204
bool isAnyAddr() const
Definition Address.cc:190
unsigned short port() const
Definition Address.cc:790
AnyP::PortCfgPointer squidPort
the listening port which originated this transaction
Comm::ConnectionPointer tcpClient
the client TCP connection which originated this transaction
void add(const SBuf &key, const SBuf &value)
Definition Notes.cc:322
void remove(const char *key)
Definition Notes.cc:328
void replaceOrAdd(const NotePairs *src)
Definition Notes.cc:410
const char * findFirst(const char *noteKey) const
Definition Notes.cc:307
void appendf(const char *fmt,...) PRINTF_FORMAT_ARG2
Append operation with printf-style arguments.
Definition Packable.h:61
virtual void append(const char *buf, int size)=0
Appends a c-string to existing packed data.
bool interceptTproxy
Set for requests handled by a "tproxy" port.
bool auth_no_keytab
RequestFlags cloneAdaptationImmune() const
Definition SBuf.h:94
size_type length() const
Returns the number of bytes stored in SBuf.
Definition SBuf.h:419
void clear()
Definition SBuf.cc:175
Comm::ConnectionPointer clientConnection
Definition Server.h:100
acl_access * spoof_client_ip
AclSizeLimit * rangeOffsetLimit
struct SquidConfig::@91 accessList
void flush() override
Definition store.cc:1612
void buffer() override
Definition store.cc:1601
void clean()
Definition String.cc:104
size_type size() const
Definition SquidString.h:74
const char * findTrailingHTTPVersion(const char *uriAndHTTPVersion, const char *end)
#define w_space
#define DBG_IMPORTANT
Definition Stream.h:38
#define debugs(SECTION, LEVEL, CONTENT)
Definition Stream.h:192
#define LOG_ENABLE
Definition defines.h:60
static int port
const char * null_string
int IcapLogfileStatus
Definition icap_log.cc:20
std::optional< KnownPort > Port
validated/supported port number (if any)
Definition UriScheme.h:26
@ PROTO_HTTPS
@ PROTO_AUTHORITY_FORM
@ PROTO_HTTP
Definition forward.h:18
StatusCode
Definition StatusCode.h:20
@ scNotImplemented
Definition StatusCode.h:74
@ scBadRequest
Definition StatusCode.h:45
@ scInvalidHeader
Squid header parsing error.
Definition StatusCode.h:88
@ scNone
Definition StatusCode.h:21
@ scLengthRequired
Definition StatusCode.h:56
@ METHOD_NONE
Definition MethodType.h:22
@ METHOD_LINK
Definition MethodType.h:35
@ METHOD_PUT
Definition MethodType.h:27
@ METHOD_POST
Definition MethodType.h:26
@ METHOD_UNLINK
Definition MethodType.h:36
@ METHOD_CONNECT
Definition MethodType.h:29
@ METHOD_GET
Definition MethodType.h:25
@ METHOD_DELETE
Definition MethodType.h:32
@ METHOD_HEAD
Definition MethodType.h:28
AnyP::ProtocolVersion ProtocolVersion()
LogConfig TheConfig
Definition Config.cc:15
#define xisspace(x)
Definition xis.h:15