]> git.ipfire.org Git - thirdparty/squid.git/blob - src/http/RequestMethod.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / http / RequestMethod.cc
1 /*
2 * Copyright (C) 1996-2015 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 "http/RequestMethod.h"
13 #include "SquidConfig.h"
14 #include "wordlist.h"
15
16 static Http::MethodType &
17 operator++ (Http::MethodType &aMethod)
18 {
19 int tmp = (int)aMethod;
20 aMethod = (Http::MethodType)(++tmp);
21 return aMethod;
22 }
23
24 /**
25 * Construct a HttpRequestMethod from a C-string such as "GET"
26 * Assumes the string is either nul-terminated or contains whitespace
27 *
28 * \deprecated use SBuf constructor instead
29 */
30 void
31 HttpRequestMethod::HttpRequestMethodXXX(char const *begin)
32 {
33 // XXX: performance regression due to this method no longer being a constructor
34 // ensure the members are empty/default values before any of the early-return
35 // optimizations can be used.
36 theMethod = Http::METHOD_NONE;
37 theImage.clear();
38
39 if (begin == NULL)
40 return;
41
42 char const *end = begin + strcspn(begin, w_space);
43
44 if (end == begin)
45 return;
46
47 // TODO: Optimize this linear search.
48 for (++theMethod; theMethod < Http::METHOD_ENUM_END; ++theMethod) {
49 // RFC 2616 section 5.1.1 - Method names are case-sensitive
50 // NP: this is not a HTTP_VIOLATIONS case since there is no MUST/SHOULD involved.
51 if (0 == image().caseCmp(begin, end-begin)) {
52
53 // relaxed parser allows mixed-case and corrects them on output
54 if (Config.onoff.relaxed_header_parser)
55 return;
56
57 if (0 == image().cmp(begin, end-begin))
58 return;
59 }
60 }
61
62 // if method not found and method string is not null then it is other method
63 theMethod = Http::METHOD_OTHER;
64 theImage.assign(begin, end-begin);
65 }
66
67 /**
68 * Construct a HttpRequestMethod from an SBuf string such as "GET"
69 * or from a range of chars such as "FOO" from buffer "GETFOOBARBAZ"
70 *
71 * Assumes the s parameter contains only the characters representing the method name
72 */
73 HttpRequestMethod::HttpRequestMethod(const SBuf &s) : theMethod(Http::METHOD_NONE)
74 {
75 if (s.isEmpty())
76 return;
77
78 // TODO: Optimize this linear search.
79 for (++theMethod; theMethod < Http::METHOD_ENUM_END; ++theMethod) {
80 // RFC 2616 section 5.1.1 - Method names are case-sensitive
81 // NP: this is not a HTTP_VIOLATIONS case since there is no MUST/SHOULD involved.
82 if (0 == image().caseCmp(s)) {
83
84 // relaxed parser allows mixed-case and corrects them on output
85 if (Config.onoff.relaxed_header_parser)
86 return;
87
88 if (0 == image().cmp(s))
89 return;
90 }
91 }
92
93 // if method not found and method string is not null then it is other method
94 theMethod = Http::METHOD_OTHER;
95 theImage = s;
96 }
97
98 const SBuf &
99 HttpRequestMethod::image() const
100 {
101 static const SBuf methodOther("METHOD_OTHER");
102 if (Http::METHOD_OTHER != theMethod) {
103 return Http::MethodType_sb[theMethod];
104 } else {
105 if (!theImage.isEmpty()) {
106 return theImage;
107 } else {
108 return methodOther;
109 }
110 }
111 }
112
113 bool
114 HttpRequestMethod::isHttpSafe() const
115 {
116 // Only a few methods are defined as safe. All others are "unsafe"
117
118 // NOTE:
119 // All known RFCs which register methods are listed in comments.
120 // if there is one not listed which defines methods, it needs
121 // checking and adding. If only to say it is known to define none.
122
123 switch (theMethod) {
124 // RFC 2068 - none
125
126 // RFC 2616 section 9.1.1
127 case Http::METHOD_GET:
128 case Http::METHOD_HEAD:
129 case Http::METHOD_OPTIONS:
130
131 // RFC 3253 section 3.6
132 case Http::METHOD_REPORT:
133
134 // RFC 3648 - none
135 // RFC 3744 - none
136 // RFC 4437 - none
137 // RFC 4791 - none
138
139 // RFC 4918 section 9.1
140 case Http::METHOD_PROPFIND:
141
142 // RFC 5323 section 2
143 case Http::METHOD_SEARCH:
144
145 // RFC 5789 - none
146 // RFC 5842 - none
147
148 return true;
149
150 default:
151 return false;
152 }
153 }
154
155 bool
156 HttpRequestMethod::isIdempotent() const
157 {
158 // Only a few methods are defined as idempotent.
159
160 // NOTE:
161 // All known RFCs which register methods are listed in comments.
162 // if there is one not listed which defines methods, it needs
163 // checking and adding. If only to say it is known to define none.
164
165 switch (theMethod) {
166 // RFC 2068 - TODO check LINK/UNLINK definition
167
168 // RFC 2616 section 9.1.2
169 case Http::METHOD_GET:
170 case Http::METHOD_HEAD:
171 case Http::METHOD_PUT:
172 case Http::METHOD_DELETE:
173 case Http::METHOD_OPTIONS:
174 case Http::METHOD_TRACE:
175
176 // RFC 3253 - TODO check
177 // RFC 3648 - TODO check
178 // RFC 3744 - TODO check
179 // RFC 4437 - TODO check
180 // RFC 4791 - TODO check
181
182 // RFC 4918 section 9
183 case Http::METHOD_PROPFIND:
184 case Http::METHOD_PROPPATCH:
185 case Http::METHOD_MKCOL:
186 case Http::METHOD_COPY:
187 case Http::METHOD_MOVE:
188 case Http::METHOD_UNLOCK:
189
190 // RFC 5323 - TODO check
191 // RFC 5789 - TODO check
192 // RFC 5842 - TODO check
193
194 return true;
195
196 default:
197 return false;
198 }
199 }
200
201 bool
202 HttpRequestMethod::respMaybeCacheable() const
203 {
204 // Only a few methods are defined as cacheable.
205 // All other methods from the below RFC are "MUST NOT cache"
206 switch (theMethod) {
207 // RFC 2616 section 9
208 case Http::METHOD_GET:
209 case Http::METHOD_HEAD:
210 return true;
211 #if WHEN_POST_CACHE_SUPPORTED
212 case Http::METHOD_POST: // Special case.
213 // RFC 2616 specifies POST as possibly cacheable
214 // However, Squid does not implement the required checks yet
215 return true;
216 #endif
217
218 // RFC 4918 section 9
219 #if WHEN_PROPFIND_CACHE_SUPPORTED
220 case Http::METHOD_PROPFIND: // Special case.
221 // RFC 4918 specifies PROPFIND as possibly cacheable
222 // However, Squid does not implement the required checks yet
223 return true;
224 #endif
225
226 // RFC 5323 section 2 - defines no cacheable methods
227
228 // RFC 3253
229 #if WHEN_CC_NOCACHE_DOES_REVALIDATES_IS_CONFIRMED
230 case Http::METHOD_CHECKOUT:
231 case Http::METHOD_CHECKIN:
232 case Http::METHOD_UNCHECKOUT:
233 case Http::METHOD_MKWORKSPACE:
234 case Http::METHOD_VERSION_CONTROL:
235 case Http::METHOD_UPDATE:
236 case Http::METHOD_LABEL:
237 case Http::METHOD_MERGE:
238 case Http::METHOD_BASELINE_CONTROL:
239 case Http::METHOD_MKACTIVITY:
240 // RFC 3253 defines these methods using "MUST include Cache-Control: no-cache".
241 //
242 // XXX: follow RFC 2616 definition of "no-cache" meaning "MAY cache, always revalidate"
243 // XXX: or treat as unregistered/undefined methods ??
244 // However, Squid may not implement the required revalidation checks yet
245 return ??;
246 #endif
247
248 // Special Squid method tokens are not cacheable.
249 // RFC 2616 defines all unregistered or unspecified methods as non-cacheable
250 // until such time as an RFC defines them cacheable.
251 default:
252 return false;
253 }
254 }
255
256 bool
257 HttpRequestMethod::shouldInvalidate() const
258 {
259 switch (theMethod) {
260 /* RFC 2616 section 13.10 - "MUST invalidate" */
261 case Http::METHOD_POST:
262 case Http::METHOD_PUT:
263 case Http::METHOD_DELETE:
264 return true;
265
266 /* Squid extension to force invalidation */
267 case Http::METHOD_PURGE:
268 return true;
269
270 /*
271 * RFC 2616 sayeth, in section 13.10, final paragraph:
272 * A cache that passes through requests for methods it does not
273 * understand SHOULD invalidate any entities referred to by the
274 * Request-URI.
275 */
276 case Http::METHOD_OTHER:
277 return true;
278
279 default:
280 // Methods which are known but not required to invalidate.
281 return false;
282 }
283 }
284
285 bool
286 HttpRequestMethod::purgesOthers() const
287 {
288 if (shouldInvalidate())
289 return true;
290
291 switch (theMethod) {
292 /* common sense suggests purging is not required? */
293 case Http::METHOD_GET: // XXX: but we do purge HEAD on successful GET
294 case Http::METHOD_HEAD:
295 case Http::METHOD_NONE:
296 case Http::METHOD_CONNECT:
297 case Http::METHOD_TRACE:
298 case Http::METHOD_OPTIONS:
299 case Http::METHOD_PROPFIND:
300 case Http::METHOD_COPY:
301 case Http::METHOD_LOCK:
302 case Http::METHOD_UNLOCK:
303 case Http::METHOD_SEARCH:
304 return false;
305
306 default:
307 return true;
308 }
309 }
310