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