2 * Copyright (C) 1996-2025 The Squid Software Foundation and contributors
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.
9 #ifndef SQUID_SRC_CLIENT_SIDE_REPLY_H
10 #define SQUID_SRC_CLIENT_SIDE_REPLY_H
12 #include "acl/forward.h"
13 #include "client_side_request.h"
14 #include "ip/forward.h"
15 #include "RequestFlags.h"
16 #include "StoreClient.h"
20 /* XXX make static method */
22 class clientReplyContext
: public RefCountable
, public StoreClient
24 CBDATA_CLASS(clientReplyContext
);
28 static STCB HandleIMSReply
;
29 static STCB SendMoreData
;
31 clientReplyContext(ClientHttpRequest
*);
32 ~clientReplyContext() override
;
38 void identifyStoreObject();
39 void identifyFoundObject(StoreEntry
*entry
, const char *detail
);
40 int storeOKTransferDone() const;
41 int storeNotOKTransferDone() const;
42 /// replaces current response store entry with the given one
43 void setReplyToStoreEntry(StoreEntry
*e
, const char *reason
);
44 /// builds error using clientBuildError() and calls setReplyToError() below
45 void setReplyToError(err_type
, Http::StatusCode
, char const *, const ConnStateData
*, HttpRequest
*, const char *,
47 Auth::UserRequest::Pointer
);
51 /// creates a store entry for the reply and appends err to it
52 void setReplyToError(const HttpRequestMethod
& method
, ErrorState
*err
);
53 /// creates a store entry for the reply and appends error reply to it
54 void setReplyToReply(HttpReply
*reply
);
55 void createStoreEntry(const HttpRequestMethod
& m
, RequestFlags flags
);
56 void removeStoreReference(store_client
** scp
, StoreEntry
** ep
);
57 void removeClientStoreReference(store_client
**scp
, ClientHttpRequest
*http
);
58 void startError(ErrorState
* err
);
59 void processExpired();
60 clientStream_status_t
replyStatus();
63 const char *storeId() const { return (http
->store_id
.size() > 0 ? http
->store_id
.termedBuf() : http
->uri
); }
65 Http::StatusCode purgeStatus
;
68 LogTags
*loggingTags() const override
;
70 ClientHttpRequest
*http
;
71 store_client
*sc
; /* The store_client we're using */
73 /// Buffer dedicated to receiving storeClientCopy() responses to generated
74 /// revalidation requests. These requests cannot use next()->readBuffer
75 /// because the latter keeps the contents of the stale HTTP response during
76 /// revalidation. sendClientOldEntry() uses that contents.
77 char tempbuf
[HTTP_REQBUF_SZ
];
80 Flags() : storelogiccomplete(0), complete(0), headersSent(false) {}
82 unsigned storelogiccomplete
:1;
83 unsigned complete
:1; ///< we have read all we can from upstream
86 clientStreamNode
*ourNode
; /* This will go away if/when this file gets refactored some more */
90 void fillChecklist(ACLFilledChecklist
&) const override
;
92 clientStreamNode
*getNextNode() const;
94 bool errorInStream(const StoreIOBuffer
&result
) const;
95 bool matchesStreamBodyBuffer(const StoreIOBuffer
&) const;
96 void sendStreamError(StoreIOBuffer
const &result
);
97 void pushStreamData(const StoreIOBuffer
&);
98 clientStreamNode
* next() const;
100 void processReplyAccess();
101 static ACLCB ProcessReplyAccessResult
;
102 void processReplyAccessResult(const Acl::Answer
&accessAllowed
);
104 void buildReplyHeader ();
105 bool alwaysAllowResponse(Http::StatusCode sline
) const;
106 int checkTransferDone();
107 void processOnlyIfCachedMiss();
108 bool processConditional();
109 void noteStreamBufferredBytes(const StoreIOBuffer
&);
110 void cacheHit(StoreIOBuffer result
);
111 void handleIMSReply(StoreIOBuffer result
);
112 void sendMoreData(StoreIOBuffer result
);
113 void triggerInitialStoreRead(STCB
= SendMoreData
);
114 void requestMoreBodyFromStore();
115 void sendClientOldEntry();
116 void purgeAllCached();
117 /// attempts to release the cached entry
118 /// \returns whether the entry was released
119 bool purgeEntry(StoreEntry
&, const Http::MethodType
, const char *descriptionPrefix
= "");
120 /// releases both cached GET and HEAD entries
123 bool blockedHit() const;
124 const char *storeLookupString(bool found
) const { return found
? "match" : "mismatch"; }
125 void detailStoreLookup(const char *detail
);
127 void sendBodyTooLargeError();
128 void sendPreconditionFailedError();
129 void sendNotModified();
130 void sendNotModifiedOrPreconditionFailedError();
131 void sendClientUpstreamResponse(const StoreIOBuffer
&upstreamResponse
);
133 /// Reduces a chance of an accidental direct storeClientCopy() call that
134 /// (should but) forgets to invalidate our lastStreamBufferedBytes. This
135 /// function is not defined; decltype() syntax prohibits "= delete", but
136 /// function usage will trigger deprecation warnings and linking errors.
137 static decltype(::storeClientCopy
) storeClientCopy
[[deprecated
]];
139 /// Classification of the initial Store lookup.
140 /// This very first lookup happens without the Vary-driven key augmentation.
141 /// TODO: Exclude internal Store match bans from the "mismatch" category.
142 const char *firstStoreLookup_
= nullptr;
144 /* (stale) cache hit information preserved during IMS revalidation */
145 StoreEntry
*old_entry
;
146 store_client
*old_sc
;
153 crNone
= 0, ///< collapsed revalidation is not allowed for this context
154 crInitiator
, ///< we initiated collapsed revalidation request
155 crSlave
///< we collapsed on the existing revalidation request
156 } CollapsedRevalidation
;
158 CollapsedRevalidation collapsedRevalidation
;
160 /// HTTP response body bytes stored in our Client Stream buffer (if any)
161 StoreIOBuffer lastStreamBufferedBytes
;
163 // TODO: Remove after moving the meat of this function into a method.
164 friend CSR clientGetMoreData
;
167 // TODO: move to SideAgent parent, when we have one
168 void purgeEntriesByUrl(HttpRequest
*, const char *);
170 #endif /* SQUID_SRC_CLIENT_SIDE_REPLY_H */