2 * Copyright (C) 1996-2021 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_HTTPHEADER_H
10 #define SQUID_HTTPHEADER_H
12 #include "anyp/ProtocolVersion.h"
13 #include "base/LookupTable.h"
14 #include "http/RegisteredHeaders.h"
15 /* because we pass a spec by value */
16 #include "HttpHeaderMask.h"
17 #include "mem/PoolingAllocator.h"
18 #include "sbuf/forward.h"
19 #include "SquidString.h"
23 /* class forward declarations */
25 class HttpHdrContRange
;
30 /** Possible owners of http header */
42 } http_hdr_owner_type
;
44 /** Iteration for headers; use HttpHeaderPos as opaque type, do not interpret */
45 typedef ssize_t HttpHeaderPos
;
47 /* use this and only this to initialize HttpHeaderPos */
48 #define HttpHeaderInitPos (-1)
52 MEMPROXY_CLASS(HttpHeaderEntry
);
55 HttpHeaderEntry(Http::HdrType id
, const SBuf
&name
, const char *value
);
57 static HttpHeaderEntry
*parse(const char *field_start
, const char *field_end
, const http_hdr_owner_type msgType
);
58 HttpHeaderEntry
*clone() const;
59 void packInto(Packable
*p
) const;
61 int64_t getInt64() const;
76 explicit HttpHeader(const http_hdr_owner_type owner
);
77 HttpHeader(const HttpHeader
&other
);
80 HttpHeader
&operator =(const HttpHeader
&other
);
82 /* Interface functions */
84 void append(const HttpHeader
* src
);
85 /// replaces fields with matching names and adds fresh fields with new names
86 /// also updates Http::HdrType::WARNINGs, assuming `fresh` is a 304 reply
87 /// TODO: Refactor most callers to avoid special handling of WARNINGs.
88 void update(const HttpHeader
*fresh
);
89 /// \returns whether calling update(fresh) would change our set of fields
90 bool needUpdate(const HttpHeader
*fresh
) const;
92 int parse(const char *header_start
, size_t len
, Http::ContentLengthInterpreter
&interpreter
);
93 /// Parses headers stored in a buffer.
94 /// \returns 1 and sets hdr_sz on success
95 /// \returns 0 when needs more data
96 /// \returns -1 on error
97 int parse(const char *buf
, size_t buf_len
, bool atEnd
, size_t &hdr_sz
, Http::ContentLengthInterpreter
&interpreter
);
98 void packInto(Packable
* p
, bool mask_sensitive_info
=false) const;
99 HttpHeaderEntry
*getEntry(HttpHeaderPos
* pos
) const;
100 HttpHeaderEntry
*findEntry(Http::HdrType id
) const;
101 /// deletes all fields with a given name, if any.
102 /// \return #fields deleted
103 int delByName(const SBuf
&name
);
104 /// \deprecated use SBuf method instead. performance regression: reallocates
105 int delByName(const char *name
) { return delByName(SBuf(name
)); }
106 int delById(Http::HdrType id
);
107 void delAt(HttpHeaderPos pos
, int &headers_deleted
);
109 void addEntry(HttpHeaderEntry
* e
);
110 void insertEntry(HttpHeaderEntry
* e
);
111 String
getList(Http::HdrType id
) const;
112 bool getList(Http::HdrType id
, String
*s
) const;
113 bool conflictingContentLength() const { return conflictingContentLength_
; }
114 String
getStrOrList(Http::HdrType id
) const;
115 String
getByName(const SBuf
&name
) const;
116 String
getByName(const char *name
) const;
117 String
getById(Http::HdrType id
) const;
118 /// returns true iff a [possibly empty] field identified by id is there
119 /// when returning true, also sets the `result` parameter (if it is not nil)
120 bool getByIdIfPresent(Http::HdrType id
, String
*result
) const;
121 /// returns true iff a [possibly empty] named field is there
122 /// when returning true, also sets the `value` parameter (if it is not nil)
123 bool hasNamed(const SBuf
&s
, String
*value
= 0) const;
124 /// \deprecated use SBuf method instead.
125 bool hasNamed(const char *name
, unsigned int namelen
, String
*value
= 0) const;
126 /// searches for the first matching key=value pair within the name-identified field
127 /// \returns the value of the found pair or an empty string
128 SBuf
getByNameListMember(const char *name
, const char *member
, const char separator
) const;
129 /// searches for the first matching key=value pair within the field
130 /// \returns the value of the found pair or an empty string
131 SBuf
getListMember(Http::HdrType id
, const char *member
, const char separator
) const;
132 int has(Http::HdrType id
) const;
133 /// Appends "this cache" information to VIA header field.
134 /// Takes the initial VIA value from "from" parameter, if provided.
135 void addVia(const AnyP::ProtocolVersion
&ver
, const HttpHeader
*from
= 0);
136 void putInt(Http::HdrType id
, int number
);
137 void putInt64(Http::HdrType id
, int64_t number
);
138 void putTime(Http::HdrType id
, time_t htime
);
139 void putStr(Http::HdrType id
, const char *str
);
140 void putAuth(const char *auth_scheme
, const char *realm
);
141 void putCc(const HttpHdrCc
* cc
);
142 void putContRange(const HttpHdrContRange
* cr
);
143 void putRange(const HttpHdrRange
* range
);
144 void putSc(HttpHdrSc
*sc
);
145 void putWarning(const int code
, const char *const text
); ///< add a Warning header
146 void putExt(const char *name
, const char *value
);
147 int getInt(Http::HdrType id
) const;
148 int64_t getInt64(Http::HdrType id
) const;
149 time_t getTime(Http::HdrType id
) const;
150 const char *getStr(Http::HdrType id
) const;
151 const char *getLastStr(Http::HdrType id
) const;
152 HttpHdrCc
*getCc() const;
153 HttpHdrRange
*getRange() const;
154 HttpHdrSc
*getSc() const;
155 HttpHdrContRange
*getContRange() const;
156 SBuf
getAuthToken(Http::HdrType id
, const char *auth_scheme
) const;
157 ETag
getETag(Http::HdrType id
) const;
158 TimeOrTag
getTimeOrTag(Http::HdrType id
) const;
159 int hasListMember(Http::HdrType id
, const char *member
, const char separator
) const;
160 int hasByNameListMember(const char *name
, const char *member
, const char separator
) const;
161 void removeHopByHopEntries();
163 /// whether the message uses chunked Transfer-Encoding
164 /// optimized implementation relies on us rejecting/removing other codings
165 bool chunked() const { return has(Http::HdrType::TRANSFER_ENCODING
); }
167 /// whether message used an unsupported and/or invalid Transfer-Encoding
168 bool unsupportedTe() const { return teUnsupported_
; }
170 /* protected, do not use these, use interface functions instead */
171 std::vector
<HttpHeaderEntry
*, PoolingAllocator
<HttpHeaderEntry
*> > entries
; /**< parsed fields in raw format */
172 HttpHeaderMask mask
; /**< bit set <=> entry present */
173 http_hdr_owner_type owner
; /**< request or reply */
174 int len
; /**< length when packed, not counting terminating null-byte */
177 /** \deprecated Public access replaced by removeHopByHopEntries() */
178 void removeConnectionHeaderEntries();
179 /// either finds the end of headers or returns false
180 /// If the end was found:
181 /// *parse_start points to the first character after the header delimiter
182 /// *blk_start points to the first header character (i.e. old parse_start value)
183 /// *blk_end points to the first header delimiter character (CR or LF in CR?LF).
184 /// If block starts where it ends, then there are no fields in the header.
185 static bool Isolate(const char **parse_start
, size_t l
, const char **blk_start
, const char **blk_end
);
186 bool skipUpdateHeader(const Http::HdrType id
) const;
187 void updateWarnings();
190 HttpHeaderEntry
*findLastEntry(Http::HdrType id
) const;
191 bool conflictingContentLength_
; ///< found different Content-Length fields
192 /// unsupported encoding, unnecessary syntax characters, and/or
193 /// invalid field-value found in Transfer-Encoding header
194 bool teUnsupported_
= false;
197 int httpHeaderParseQuotedString(const char *start
, const int len
, String
*val
);
199 /// quotes string using RFC 7230 quoted-string rules
200 SBuf
httpHeaderQuoteString(const char *raw
);
202 void httpHeaderCalcMask(HttpHeaderMask
* mask
, Http::HdrType http_hdr_type_enums
[], size_t count
);
204 void httpHeaderInitModule(void);
206 #endif /* SQUID_HTTPHEADER_H */