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