]>
Commit | Line | Data |
---|---|---|
e6ccf245 | 1 | /* |
b8ae064d | 2 | * Copyright (C) 1996-2023 The Squid Software Foundation and contributors |
e6ccf245 | 3 | * |
bbc27441 AJ |
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. | |
e6ccf245 | 7 | */ |
8 | ||
9 | #ifndef SQUID_HTTPHEADER_H | |
10 | #define SQUID_HTTPHEADER_H | |
11 | ||
90be6ff5 | 12 | #include "anyp/ProtocolVersion.h" |
383154d7 | 13 | #include "base/LookupTable.h" |
1139d406 | 14 | #include "http/RegisteredHeaders.h" |
528b2c61 | 15 | /* because we pass a spec by value */ |
25b6a907 | 16 | #include "HttpHeaderMask.h" |
c3b51d64 | 17 | #include "mem/PoolingAllocator.h" |
92e8f3ad | 18 | #include "sbuf/forward.h" |
71b673d4 | 19 | #include "SquidString.h" |
43ca19e0 | 20 | |
b7347197 FC |
21 | #include <vector> |
22 | ||
696a257c | 23 | /* class forward declarations */ |
696a257c | 24 | class HttpHdrCc; |
71b673d4 | 25 | class HttpHdrContRange; |
696a257c | 26 | class HttpHdrRange; |
71b673d4 | 27 | class HttpHdrSc; |
17802cf1 | 28 | class Packable; |
696a257c | 29 | |
63be0a78 | 30 | /** Possible owners of http header */ |
25b6a907 | 31 | typedef enum { |
0b57cb3d | 32 | hoNone =0, |
25b6a907 | 33 | #if USE_HTCP |
34 | hoHtcpReply, | |
35 | #endif | |
36 | hoRequest, | |
02259ff8 | 37 | hoReply, |
cb4f4424 | 38 | #if USE_OPENSSL |
02259ff8 CT |
39 | hoErrorDetail, |
40 | #endif | |
41 | hoEnd | |
25b6a907 | 42 | } http_hdr_owner_type; |
43 | ||
63be0a78 | 44 | /** Iteration for headers; use HttpHeaderPos as opaque type, do not interpret */ |
985c86bc | 45 | typedef ssize_t HttpHeaderPos; |
46 | ||
47 | /* use this and only this to initialize HttpHeaderPos */ | |
48 | #define HttpHeaderInitPos (-1) | |
49 | ||
eede25e7 | 50 | class HttpHeaderEntry |
51 | { | |
741c2986 | 52 | MEMPROXY_CLASS(HttpHeaderEntry); |
eede25e7 | 53 | |
54 | public: | |
d5f18517 | 55 | HttpHeaderEntry(Http::HdrType id, const SBuf &name, const char *value); |
eede25e7 | 56 | ~HttpHeaderEntry(); |
2358b975 | 57 | static HttpHeaderEntry *parse(const char *field_start, const char *field_end, const http_hdr_owner_type msgType); |
eede25e7 | 58 | HttpHeaderEntry *clone() const; |
17802cf1 | 59 | void packInto(Packable *p) const; |
eede25e7 | 60 | int getInt() const; |
47f6e231 | 61 | int64_t getInt64() const; |
741c2986 | 62 | |
789217a2 | 63 | Http::HdrType id; |
d5f18517 | 64 | SBuf name; |
30abd221 | 65 | String value; |
eede25e7 | 66 | }; |
67 | ||
81a94152 AJ |
68 | class ETag; |
69 | class TimeOrTag; | |
70 | ||
924f73bc | 71 | class HttpHeader |
72 | { | |
73 | ||
74 | public: | |
75faaa7a | 75 | HttpHeader(); |
5e5fa5b1 AR |
76 | explicit HttpHeader(const http_hdr_owner_type owner); |
77 | HttpHeader(const HttpHeader &other); | |
75faaa7a | 78 | ~HttpHeader(); |
5e5fa5b1 AR |
79 | |
80 | HttpHeader &operator =(const HttpHeader &other); | |
81 | ||
924f73bc | 82 | /* Interface functions */ |
519e0948 | 83 | void clean(); |
a9925b40 | 84 | void append(const HttpHeader * src); |
66d51f4f | 85 | /// replaces fields with matching names and adds fresh fields with new names |
0ac163be | 86 | /// assuming `fresh` is a 304 reply |
66d51f4f AR |
87 | void update(const HttpHeader *fresh); |
88 | /// \returns whether calling update(fresh) would change our set of fields | |
89 | bool needUpdate(const HttpHeader *fresh) const; | |
394499bd | 90 | void compact(); |
4f1c93a7 | 91 | int parse(const char *header_start, size_t len, Http::ContentLengthInterpreter &interpreter); |
69c698a3 EB |
92 | /// Parses headers stored in a buffer. |
93 | /// \returns 1 and sets hdr_sz on success | |
94 | /// \returns 0 when needs more data | |
95 | /// \returns -1 on error | |
4f1c93a7 | 96 | int parse(const char *buf, size_t buf_len, bool atEnd, size_t &hdr_sz, Http::ContentLengthInterpreter &interpreter); |
17802cf1 | 97 | void packInto(Packable * p, bool mask_sensitive_info=false) const; |
a9925b40 | 98 | HttpHeaderEntry *getEntry(HttpHeaderPos * pos) const; |
789217a2 | 99 | HttpHeaderEntry *findEntry(Http::HdrType id) const; |
d5f18517 AJ |
100 | /// deletes all fields with a given name, if any. |
101 | /// \return #fields deleted | |
102 | int delByName(const SBuf &name); | |
103 | /// \deprecated use SBuf method instead. performance regression: reallocates | |
104 | int delByName(const char *name) { return delByName(SBuf(name)); } | |
789217a2 | 105 | int delById(Http::HdrType id); |
ba9fb01d | 106 | void delAt(HttpHeaderPos pos, int &headers_deleted); |
107 | void refreshMask(); | |
a9925b40 | 108 | void addEntry(HttpHeaderEntry * e); |
109 | void insertEntry(HttpHeaderEntry * e); | |
789217a2 FC |
110 | String getList(Http::HdrType id) const; |
111 | bool getList(Http::HdrType id, String *s) const; | |
3e42b356 | 112 | bool conflictingContentLength() const { return conflictingContentLength_; } |
789217a2 | 113 | String getStrOrList(Http::HdrType id) const; |
81ab22b6 | 114 | String getByName(const SBuf &name) const; |
30abd221 | 115 | String getByName(const char *name) const; |
81ab22b6 | 116 | String getById(Http::HdrType id) const; |
f29d429e EB |
117 | /// returns true iff a [possibly empty] field identified by id is there |
118 | /// when returning true, also sets the `result` parameter (if it is not nil) | |
119 | bool getByIdIfPresent(Http::HdrType id, String *result) const; | |
120 | /// returns true iff a [possibly empty] named field is there | |
121 | /// when returning true, also sets the `value` parameter (if it is not nil) | |
aee3523a | 122 | bool hasNamed(const SBuf &s, String *value = nullptr) const; |
d5f18517 | 123 | /// \deprecated use SBuf method instead. |
aee3523a | 124 | bool hasNamed(const char *name, unsigned int namelen, String *value = nullptr) const; |
36c774f7 EB |
125 | /// searches for the first matching key=value pair within the name-identified field |
126 | /// \returns the value of the found pair or an empty string | |
127 | SBuf getByNameListMember(const char *name, const char *member, const char separator) const; | |
128 | /// searches for the first matching key=value pair within the field | |
129 | /// \returns the value of the found pair or an empty string | |
130 | SBuf getListMember(Http::HdrType id, const char *member, const char separator) const; | |
789217a2 | 131 | int has(Http::HdrType id) const; |
90be6ff5 EB |
132 | /// Appends "this cache" information to VIA header field. |
133 | /// Takes the initial VIA value from "from" parameter, if provided. | |
aee3523a | 134 | void addVia(const AnyP::ProtocolVersion &ver, const HttpHeader *from = nullptr); |
789217a2 FC |
135 | void putInt(Http::HdrType id, int number); |
136 | void putInt64(Http::HdrType id, int64_t number); | |
137 | void putTime(Http::HdrType id, time_t htime); | |
789217a2 | 138 | void putStr(Http::HdrType id, const char *str); |
a9925b40 | 139 | void putAuth(const char *auth_scheme, const char *realm); |
140 | void putCc(const HttpHdrCc * cc); | |
141 | void putContRange(const HttpHdrContRange * cr); | |
142 | void putRange(const HttpHdrRange * range); | |
143 | void putSc(HttpHdrSc *sc); | |
144 | void putExt(const char *name, const char *value); | |
05ba40fc EW |
145 | |
146 | /// Ensures that the header has the given field, removing or replacing any | |
147 | /// same-name fields with conflicting values as needed. | |
148 | void updateOrAddStr(Http::HdrType, const SBuf &); | |
149 | ||
789217a2 FC |
150 | int getInt(Http::HdrType id) const; |
151 | int64_t getInt64(Http::HdrType id) const; | |
152 | time_t getTime(Http::HdrType id) const; | |
153 | const char *getStr(Http::HdrType id) const; | |
154 | const char *getLastStr(Http::HdrType id) const; | |
a9925b40 | 155 | HttpHdrCc *getCc() const; |
156 | HttpHdrRange *getRange() const; | |
157 | HttpHdrSc *getSc() const; | |
158 | HttpHdrContRange *getContRange() const; | |
2582f64a | 159 | SBuf getAuthToken(Http::HdrType id, const char *auth_scheme) const; |
789217a2 FC |
160 | ETag getETag(Http::HdrType id) const; |
161 | TimeOrTag getTimeOrTag(Http::HdrType id) const; | |
162 | int hasListMember(Http::HdrType id, const char *member, const char separator) const; | |
a9925b40 | 163 | int hasByNameListMember(const char *name, const char *member, const char separator) const; |
2cdeea82 | 164 | void removeHopByHopEntries(); |
f6dd87e9 AJ |
165 | |
166 | /// whether the message uses chunked Transfer-Encoding | |
167 | /// optimized implementation relies on us rejecting/removing other codings | |
168 | bool chunked() const { return has(Http::HdrType::TRANSFER_ENCODING); } | |
169 | ||
170 | /// whether message used an unsupported and/or invalid Transfer-Encoding | |
171 | bool unsupportedTe() const { return teUnsupported_; } | |
63be0a78 | 172 | |
924f73bc | 173 | /* protected, do not use these, use interface functions instead */ |
c3b51d64 | 174 | std::vector<HttpHeaderEntry*, PoolingAllocator<HttpHeaderEntry*> > entries; /**< parsed fields in raw format */ |
f53969cc SM |
175 | HttpHeaderMask mask; /**< bit set <=> entry present */ |
176 | http_hdr_owner_type owner; /**< request or reply */ | |
177 | int len; /**< length when packed, not counting terminating null-byte */ | |
a9925b40 | 178 | |
2cdeea82 | 179 | protected: |
63be0a78 | 180 | /** \deprecated Public access replaced by removeHopByHopEntries() */ |
2cdeea82 | 181 | void removeConnectionHeaderEntries(); |
69c698a3 EB |
182 | /// either finds the end of headers or returns false |
183 | /// If the end was found: | |
184 | /// *parse_start points to the first character after the header delimiter | |
185 | /// *blk_start points to the first header character (i.e. old parse_start value) | |
186 | /// *blk_end points to the first header delimiter character (CR or LF in CR?LF). | |
187 | /// If block starts where it ends, then there are no fields in the header. | |
188 | static bool Isolate(const char **parse_start, size_t l, const char **blk_start, const char **blk_end); | |
2d4f252d | 189 | bool skipUpdateHeader(const Http::HdrType id) const; |
63be0a78 | 190 | |
a9925b40 | 191 | private: |
789217a2 | 192 | HttpHeaderEntry *findLastEntry(Http::HdrType id) const; |
3e42b356 | 193 | bool conflictingContentLength_; ///< found different Content-Length fields |
f6dd87e9 AJ |
194 | /// unsupported encoding, unnecessary syntax characters, and/or |
195 | /// invalid field-value found in Transfer-Encoding header | |
196 | bool teUnsupported_ = false; | |
924f73bc | 197 | }; |
528b2c61 | 198 | |
8a648e8d | 199 | int httpHeaderParseQuotedString(const char *start, const int len, String *val); |
a2c7f09a | 200 | |
e7ce227f AR |
201 | /// quotes string using RFC 7230 quoted-string rules |
202 | SBuf httpHeaderQuoteString(const char *raw); | |
a2c7f09a | 203 | |
789217a2 | 204 | void httpHeaderCalcMask(HttpHeaderMask * mask, Http::HdrType http_hdr_type_enums[], size_t count); |
25b6a907 | 205 | |
8a648e8d | 206 | void httpHeaderInitModule(void); |
ec6f82c1 | 207 | |
e6ccf245 | 208 | #endif /* SQUID_HTTPHEADER_H */ |
f53969cc | 209 |