/* * Copyright (C) 1996-2023 The Squid Software Foundation and contributors * * Squid software is distributed under GPLv2+ license and includes * contributions from numerous individuals and organizations. * Please see the COPYING and CONTRIBUTORS files for details. */ #ifndef SQUID_SRC_HTTPREQUEST_H #define SQUID_SRC_HTTPREQUEST_H #include "anyp/Uri.h" #include "base/CbcPointer.h" #include "dns/forward.h" #include "error/Error.h" #include "HierarchyLogEntry.h" #include "http/Message.h" #include "http/RequestMethod.h" #include "MasterXaction.h" #include "Notes.h" #include "RequestFlags.h" #if USE_AUTH #include "auth/UserRequest.h" #endif #if USE_ADAPTATION #include "adaptation/History.h" #endif #if ICAP_CLIENT #include "adaptation/icap/History.h" #endif #if USE_SQUID_EUI #include "eui/Eui48.h" #include "eui/Eui64.h" #endif class AccessLogEntry; typedef RefCount AccessLogEntryPointer; class CachePeer; class ConnStateData; class Downloader; /* Http Request */ void httpRequestPack(void *obj, Packable *p); class HttpHdrRange; class HttpRequest: public Http::Message { MEMPROXY_CLASS(HttpRequest); public: typedef RefCount Pointer; HttpRequest(const MasterXaction::Pointer &); HttpRequest(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *schemeImage, const char *aUrlpath, const MasterXaction::Pointer &); ~HttpRequest() override; void reset() override; void initHTTP(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *schemeImage, const char *aUrlpath); HttpRequest *clone() const override; /// Whether response to this request is potentially cachable /// \retval false Not cacheable. /// \retval true Possibly cacheable. Response factors will determine. bool maybeCacheable(); bool conditional() const; ///< has at least one recognized If-* header /// whether the client is likely to be able to handle a 1xx reply bool canHandle1xx() const; /// \returns a pointer to a local static buffer containing request URI /// that honors strip_query_terms and %-encodes unsafe URI characters char *canonicalCleanUrl() const; #if USE_ADAPTATION /// Returns possibly nil history, creating it if adapt. logging is enabled Adaptation::History::Pointer adaptLogHistory() const; /// Returns possibly nil history, creating it if requested Adaptation::History::Pointer adaptHistory(bool createIfNone = false) const; /// Makes their history ours, throwing on conflicts void adaptHistoryImport(const HttpRequest &them); #endif #if ICAP_CLIENT /// Returns possibly nil history, creating it if icap logging is enabled Adaptation::Icap::History::Pointer icapHistory() const; #endif /* If a request goes through several destinations, then the following two * methods will be called several times, in destinations-dependent order. */ /// get ready to be sent to the given cache_peer, including originserver void prepForPeering(const CachePeer &peer); /// get ready to be sent directly to an origin server, excluding originserver void prepForDirect(); void recordLookup(const Dns::LookupDetails &detail); /// sets error detail if no earlier detail was available void detailError(const err_type c, const ErrorDetail::Pointer &d) { error.update(c, d); } /// clear error details, useful for retries/repeats void clearError(); /// associates the request with a from-client connection manager void manager(const CbcPointer &aMgr, const AccessLogEntryPointer &al); protected: void clean(); void init(); public: HttpRequestMethod method; AnyP::Uri url; ///< the request URI private: #if USE_ADAPTATION mutable Adaptation::History::Pointer adaptHistory_; ///< per-HTTP transaction info #endif #if ICAP_CLIENT mutable Adaptation::Icap::History::Pointer icapHistory_; ///< per-HTTP transaction info #endif public: #if USE_AUTH Auth::UserRequest::Pointer auth_user_request; #endif /// RFC 7230 section 5.5 - Effective Request URI const SBuf &effectiveRequestUri() const; /** * If defined, store_id_program mapped the request URL to this ID. * Store uses this ID (and not the URL) to find and store entries, * avoiding caching duplicate entries when different URLs point to * "essentially the same" cachable resource. */ String store_id; RequestFlags flags; HttpHdrRange *range; time_t ims; int imslen; Ip::Address client_addr; #if FOLLOW_X_FORWARDED_FOR Ip::Address indirect_client_addr; #endif /* FOLLOW_X_FORWARDED_FOR */ Ip::Address my_addr; HierarchyLogEntry hier; int dnsWait; ///< sum of DNS lookup delays in milliseconds, for %dt Error error; ///< the first transaction problem encountered (or falsy) char *peer_login; /* Configured peer login:password */ char *peer_host; /* Selected peer host*/ time_t lastmod; /* Used on refreshes */ /// The variant second-stage cache key. Generated from Vary header pattern for this request. SBuf vary_headers; char *peer_domain; /* Configured peer forceddomain */ String myportname; // Internal tag name= value from port this requests arrived in. String tag; /* Internal tag for this request */ String extacl_user; /* User name returned by extacl lookup */ String extacl_passwd; /* Password returned by extacl lookup */ String extacl_log; /* String to be used for access.log purposes */ String extacl_message; /* String to be used for error page purposes */ #if FOLLOW_X_FORWARDED_FOR String x_forwarded_for_iterator; /* XXX a list of IP addresses */ #endif /* FOLLOW_X_FORWARDED_FOR */ /// A strong etag of the cached entry. Used for refreshing that entry. String etag; /// whether we have responded with HTTP 100 or FTP 150 already bool forcedBodyContinuation; public: bool multipartRangeRequest() const; bool parseFirstLine(const char *start, const char *end) override; bool expectingBody(const HttpRequestMethod& unused, int64_t&) const override; bool bodyNibbled() const; // the request has a [partially] consumed body int prefixLen() const; void swapOut(StoreEntry * e); void pack(Packable * p) const; static void httpRequestPack(void *obj, Packable *p); static HttpRequest * FromUrl(const SBuf &url, const MasterXaction::Pointer &, const HttpRequestMethod &method = Http::METHOD_GET); /// \deprecated use SBuf variant instead static HttpRequest * FromUrlXXX(const char * url, const MasterXaction::Pointer &, const HttpRequestMethod &method = Http::METHOD_GET); ConnStateData *pinnedConnection(); /** * Returns the current StoreID for the request as a nul-terminated char*. * Always returns the current id for the request * (either the effective request URI or modified ID by the helper). */ const SBuf storeId(); /** * The client connection manager, if known; * Used for any response actions needed directly to the client. * ie 1xx forwarding or connection pinning state changes */ CbcPointer clientConnectionManager; /// The Downloader object which initiated the HTTP request if any CbcPointer downloader; /// the master transaction this request belongs to. Never nil. MasterXaction::Pointer masterXaction; /// forgets about the cached Range header (for a reason) void ignoreRange(const char *reason); int64_t getRangeOffsetLimit(); /* the result of this function gets cached in rangeOffsetLimit */ /// \returns existing non-empty transaction annotations, /// creates and returns empty annotations otherwise NotePairs::Pointer notes(); bool hasNotes() const { return bool(theNotes) && !theNotes->empty(); } void configureContentLengthInterpreter(Http::ContentLengthInterpreter &) override {} /// Check whether the message framing headers are valid. /// \returns Http::scNone or an HTTP error status Http::StatusCode checkEntityFraming() const; /// Parses request header using Parser. /// Use it in contexts where the Parser object is available. bool parseHeader(Http1::Parser &hp); /// Parses request header from the buffer. /// Use it in contexts where the Parser object not available. bool parseHeader(const char *buffer, const size_t size); private: mutable int64_t rangeOffsetLimit; /* caches the result of getRangeOffsetLimit */ /// annotations added by the note directive and helpers /// and(or) by annotate_transaction/annotate_client ACLs. NotePairs::Pointer theNotes; protected: void packFirstLineInto(Packable * p, bool full_uri) const override; bool sanityCheckStartLine(const char *buf, const size_t hdr_len, Http::StatusCode *error) override; void hdrCacheInit() override; bool inheritProperties(const Http::Message *) override; }; class ConnStateData; /** * Updates ConnStateData ids and HttpRequest notes from helpers received notes. */ void UpdateRequestNotes(ConnStateData *csd, HttpRequest &request, NotePairs const ¬es); /// \returns listening/*_port address used by the client connection (or nil) /// nil parameter(s) indicate missing caller information and are handled safely const Ip::Address *FindListeningPortAddress(const HttpRequest *, const AccessLogEntry *); /// \returns listening/*_port port number used by the client connection (or nothing) /// nil parameter(s) indicate missing caller information and are handled safely AnyP::Port FindListeningPortNumber(const HttpRequest *, const AccessLogEntry *); #endif /* SQUID_SRC_HTTPREQUEST_H */