]>
Commit | Line | Data |
---|---|---|
99edd1c3 | 1 | |
2 | /* | |
190154cf | 3 | * $Id: HttpRequest.cc,v 1.43 2003/08/10 11:00:40 robertc Exp $ |
99edd1c3 | 4 | * |
5 | * DEBUG: section 73 HTTP Request | |
6 | * AUTHOR: Duane Wessels | |
7 | * | |
2b6662ba | 8 | * SQUID Web Proxy Cache http://www.squid-cache.org/ |
e25c139f | 9 | * ---------------------------------------------------------- |
99edd1c3 | 10 | * |
2b6662ba | 11 | * Squid is the result of efforts by numerous individuals from |
12 | * the Internet community; see the CONTRIBUTORS file for full | |
13 | * details. Many organizations have provided support for Squid's | |
14 | * development; see the SPONSORS file for full details. Squid is | |
15 | * Copyrighted (C) 2001 by the Regents of the University of | |
16 | * California; see the COPYRIGHT file for full details. Squid | |
17 | * incorporates software developed and/or copyrighted by other | |
18 | * sources; see the CREDITS file for full details. | |
99edd1c3 | 19 | * |
20 | * This program is free software; you can redistribute it and/or modify | |
21 | * it under the terms of the GNU General Public License as published by | |
22 | * the Free Software Foundation; either version 2 of the License, or | |
23 | * (at your option) any later version. | |
24 | * | |
25 | * This program is distributed in the hope that it will be useful, | |
26 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
27 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
28 | * GNU General Public License for more details. | |
29 | * | |
30 | * You should have received a copy of the GNU General Public License | |
31 | * along with this program; if not, write to the Free Software | |
cbdec147 | 32 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
e25c139f | 33 | * |
51ee7c82 | 34 | * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org> |
99edd1c3 | 35 | */ |
36 | ||
528b2c61 | 37 | #include "HttpRequest.h" |
99edd1c3 | 38 | #include "squid.h" |
e6ccf245 | 39 | #include "authenticate.h" |
528b2c61 | 40 | #include "HttpHeaderRange.h" |
41 | ||
190154cf | 42 | static void httpRequestHdrCacheInit(HttpRequest * req); |
51ee7c82 | 43 | MemPool (*HttpRequest::Pool)(NULL); |
99edd1c3 | 44 | |
75faaa7a | 45 | void * |
51ee7c82 | 46 | HttpRequest::operator new (size_t byteCount) |
75faaa7a | 47 | { |
51ee7c82 | 48 | /* derived classes with different sizes must implement their own new */ |
49 | assert (byteCount == sizeof (HttpRequest)); | |
50 | ||
51 | if (!Pool) | |
52 | Pool = memPoolCreate("HttpRequest", sizeof (HttpRequest)); | |
53 | ||
54 | return memPoolAlloc(Pool); | |
75faaa7a | 55 | } |
56 | ||
57 | void | |
51ee7c82 | 58 | HttpRequest::operator delete (void *address) |
75faaa7a | 59 | { |
51ee7c82 | 60 | memPoolFree (Pool, address); |
75faaa7a | 61 | } |
62 | ||
75faaa7a | 63 | HttpRequest::HttpRequest() : header(hoRequest) |
64 | { | |
65 | /* We should initialise these ... */ | |
66 | #if 0 | |
67 | method_t method; | |
68 | protocol_t protocol; | |
69 | char login[MAX_LOGIN_SZ]; | |
70 | char host[SQUIDHOSTNAMELEN + 1]; | |
71 | auth_user_request_t *auth_user_request; | |
72 | u_short port; | |
73 | String urlpath; | |
74 | char *canonical; | |
75 | int link_count; /* free when zero */ | |
76 | request_flags flags; | |
77 | HttpHdrCc *cache_control; | |
78 | HttpHdrRange *range; | |
79 | http_version_t http_ver; | |
80 | time_t ims; | |
81 | int imslen; | |
82 | int max_forwards; | |
83 | /* these in_addr's could probably be sockaddr_in's */ | |
84 | ||
85 | struct in_addr client_addr; | |
86 | ||
87 | struct in_addr my_addr; | |
88 | unsigned short my_port; | |
89 | unsigned short client_port; | |
90 | HttpHeader header; | |
91 | ConnStateData::Pointer body_connection; /* used by clientReadBody() */ | |
92 | int content_length; | |
93 | HierarchyLogEntry hier; | |
94 | err_type errType; | |
95 | char *peer_login; /* Configured peer login:password */ | |
96 | time_t lastmod; /* Used on refreshes */ | |
97 | const char *vary_headers; /* Used when varying entities are detected. Changes how the store key is calculated */ | |
98 | char *peer_domain; /* Configured peer forceddomain */ | |
99 | #endif | |
100 | } | |
101 | ||
190154cf | 102 | HttpRequest * |
528b2c61 | 103 | requestCreate(method_t method, protocol_t protocol, const char *aUrlpath) |
99edd1c3 | 104 | { |
190154cf | 105 | HttpRequest *req = new HttpRequest; |
99edd1c3 | 106 | req->method = method; |
107 | req->protocol = protocol; | |
62e76326 | 108 | |
528b2c61 | 109 | if (aUrlpath) |
62e76326 | 110 | req->urlpath = aUrlpath; |
111 | ||
99edd1c3 | 112 | req->max_forwards = -1; |
62e76326 | 113 | |
9bc73deb | 114 | req->lastmod = -1; |
62e76326 | 115 | |
7e3ce7b9 | 116 | req->client_addr = no_addr; |
62e76326 | 117 | |
7e3ce7b9 | 118 | req->my_addr = no_addr; |
62e76326 | 119 | |
528b2c61 | 120 | httpRequestHdrCacheInit(req); |
62e76326 | 121 | |
99edd1c3 | 122 | return req; |
123 | } | |
124 | ||
125 | void | |
190154cf | 126 | requestDestroy(HttpRequest * req) |
99edd1c3 | 127 | { |
128 | assert(req); | |
62e76326 | 129 | |
a2ac85d9 | 130 | if (req->body_connection.getRaw() != NULL) |
62e76326 | 131 | clientAbortBody(req); |
132 | ||
94439e4e | 133 | if (req->auth_user_request) |
62e76326 | 134 | authenticateAuthUserRequestUnlock(req->auth_user_request); |
135 | ||
b0431342 | 136 | safe_free(req->canonical); |
62e76326 | 137 | |
f66a9ef4 | 138 | safe_free(req->vary_headers); |
62e76326 | 139 | |
528b2c61 | 140 | req->urlpath.clean(); |
62e76326 | 141 | |
99edd1c3 | 142 | httpHeaderClean(&req->header); |
62e76326 | 143 | |
8e092300 | 144 | if (req->cache_control) |
62e76326 | 145 | httpHdrCcDestroy(req->cache_control); |
146 | ||
d192d11f | 147 | if (req->range) |
00d77d6b | 148 | delete req->range; |
62e76326 | 149 | |
abb929f0 | 150 | req->tag.clean(); |
151 | ||
152 | req->extacl_user.clean(); | |
153 | ||
154 | req->extacl_passwd.clean(); | |
155 | ||
4a972fa2 | 156 | req->extacl_log.clean(); |
157 | ||
00d77d6b | 158 | delete req; |
99edd1c3 | 159 | } |
160 | ||
190154cf | 161 | HttpRequest * |
162 | requestLink(HttpRequest * request) | |
99edd1c3 | 163 | { |
164 | assert(request); | |
165 | request->link_count++; | |
166 | return request; | |
167 | } | |
168 | ||
169 | void | |
190154cf | 170 | requestUnlink(HttpRequest * request) |
99edd1c3 | 171 | { |
172 | if (!request) | |
62e76326 | 173 | return; |
174 | ||
1cc5cec5 | 175 | assert(request->link_count > 0); |
62e76326 | 176 | |
a7eb786a | 177 | if (--request->link_count > 0) |
62e76326 | 178 | return; |
179 | ||
a7eb786a | 180 | requestDestroy(request); |
99edd1c3 | 181 | } |
182 | ||
183 | int | |
190154cf | 184 | httpRequestParseHeader(HttpRequest * req, const char *parse_start) |
99edd1c3 | 185 | { |
186 | const char *blk_start, *blk_end; | |
62e76326 | 187 | |
99edd1c3 | 188 | if (!httpMsgIsolateHeaders(&parse_start, &blk_start, &blk_end)) |
62e76326 | 189 | return 0; |
190 | ||
528b2c61 | 191 | int result = httpHeaderParse(&req->header, blk_start, blk_end); |
62e76326 | 192 | |
528b2c61 | 193 | if (result) |
62e76326 | 194 | httpRequestHdrCacheInit(req); |
195 | ||
528b2c61 | 196 | return result; |
99edd1c3 | 197 | } |
198 | ||
a00a7c85 | 199 | /* swaps out request using httpRequestPack */ |
99edd1c3 | 200 | void |
190154cf | 201 | httpRequestSwapOut(const HttpRequest * req, StoreEntry * e) |
99edd1c3 | 202 | { |
a00a7c85 | 203 | Packer p; |
2246b732 | 204 | assert(req && e); |
a00a7c85 | 205 | packerToStoreInit(&p, e); |
206 | httpRequestPack(req, &p); | |
207 | packerClean(&p); | |
208 | } | |
209 | ||
210 | /* packs request-line and headers, appends <crlf> terminator */ | |
211 | void | |
190154cf | 212 | httpRequestPack(const HttpRequest * req, Packer * p) |
a00a7c85 | 213 | { |
214 | assert(req && p); | |
215 | /* pack request-line */ | |
216 | packerPrintf(p, "%s %s HTTP/1.0\r\n", | |
62e76326 | 217 | RequestMethodStr[req->method], req->urlpath.buf()); |
a00a7c85 | 218 | /* headers */ |
219 | httpHeaderPackInto(&req->header, p); | |
2246b732 | 220 | /* trailer */ |
a00a7c85 | 221 | packerAppend(p, "\r\n", 2); |
2246b732 | 222 | } |
223 | ||
224 | #if UNUSED_CODE | |
225 | void | |
190154cf | 226 | httpRequestSetHeaders(HttpRequest * req, method_t method, const char *uri, const char *header_str) |
2246b732 | 227 | { |
2246b732 | 228 | assert(req && uri && header_str); |
229 | assert(!req->header.len); | |
5999b776 | 230 | httpHeaderParse(&req->header, header_str, header_str + strlen(header_str)); |
99edd1c3 | 231 | } |
eeb423fb | 232 | |
2246b732 | 233 | #endif |
234 | ||
235 | /* returns the length of request line + headers + crlf */ | |
236 | int | |
190154cf | 237 | httpRequestPrefixLen(const HttpRequest * req) |
2246b732 | 238 | { |
239 | assert(req); | |
240 | return strlen(RequestMethodStr[req->method]) + 1 + | |
62e76326 | 241 | req->urlpath.size() + 1 + |
242 | 4 + 1 + 3 + 2 + | |
243 | req->header.len + 2; | |
2246b732 | 244 | } |
99edd1c3 | 245 | |
6bccf575 | 246 | /* |
247 | * Returns true if HTTP allows us to pass this header on. Does not | |
248 | * check anonymizer (aka header_access) configuration. | |
249 | */ | |
99edd1c3 | 250 | int |
5999b776 | 251 | httpRequestHdrAllowed(const HttpHeaderEntry * e, String * strConn) |
99edd1c3 | 252 | { |
253 | assert(e); | |
97474590 | 254 | /* check connection header */ |
62e76326 | 255 | |
528b2c61 | 256 | if (strConn && strListIsMember(strConn, e->name.buf(), ',')) |
62e76326 | 257 | return 0; |
258 | ||
99edd1c3 | 259 | return 1; |
260 | } | |
e429f975 | 261 | |
190154cf | 262 | /* sync this routine when you update HttpRequest struct */ |
528b2c61 | 263 | static void |
190154cf | 264 | httpRequestHdrCacheInit(HttpRequest * req) |
528b2c61 | 265 | { |
266 | const HttpHeader *hdr = &req->header; | |
62e76326 | 267 | /* const char *str; */ |
528b2c61 | 268 | req->content_length = httpHeaderGetInt(hdr, HDR_CONTENT_LENGTH); |
269 | /* TODO: canonicalise these into an HttpEntity */ | |
270 | #if 0 | |
62e76326 | 271 | |
528b2c61 | 272 | req->date = httpHeaderGetTime(hdr, HDR_DATE); |
273 | req->last_modified = httpHeaderGetTime(hdr, HDR_LAST_MODIFIED); | |
274 | str = httpHeaderGetStr(hdr, HDR_CONTENT_TYPE); | |
62e76326 | 275 | |
528b2c61 | 276 | if (str) |
62e76326 | 277 | stringLimitInit(&req->content_type, str, strcspn(str, ";\t ")); |
528b2c61 | 278 | else |
650c4b88 | 279 | req->content_type = String(); |
62e76326 | 280 | |
528b2c61 | 281 | #endif |
62e76326 | 282 | |
528b2c61 | 283 | req->cache_control = httpHeaderGetCc(hdr); |
62e76326 | 284 | |
528b2c61 | 285 | req->range = httpHeaderGetRange(hdr); |
62e76326 | 286 | |
528b2c61 | 287 | #if 0 |
62e76326 | 288 | |
528b2c61 | 289 | req->keep_alive = httpMsgIsPersistent(req->http_ver, &req->header); |
290 | ||
291 | /* be sure to set expires after date and cache-control */ | |
292 | req->expires = httpReplyHdrExpirationTime(req); | |
62e76326 | 293 | |
528b2c61 | 294 | #endif |
295 | } | |
296 | ||
e429f975 | 297 | /* request_flags */ |
298 | bool | |
299 | request_flags::resetTCP() const | |
300 | { | |
301 | return reset_tcp != 0; | |
302 | } | |
303 | ||
304 | void | |
305 | request_flags::setResetTCP() | |
306 | { | |
307 | debug (73, 9) ("request_flags::setResetTCP\n"); | |
308 | reset_tcp = 1; | |
309 | } | |
310 | ||
311 | void | |
312 | request_flags::clearResetTCP() | |
313 | { | |
314 | debug(73, 9) ("request_flags::clearResetTCP\n"); | |
315 | reset_tcp = 0; | |
316 | } | |
528b2c61 | 317 | |
318 | bool | |
190154cf | 319 | HttpRequest::multipartRangeRequest() const |
528b2c61 | 320 | { |
321 | return (range && range->specs.count > 1); | |
322 | } | |
8000a965 | 323 | |
324 | void | |
325 | request_flags::destinationIPLookupCompleted() | |
326 | { | |
327 | destinationIPLookedUp_ = true; | |
328 | } | |
329 | ||
330 | bool | |
331 | request_flags::destinationIPLookedUp() const | |
332 | { | |
333 | return destinationIPLookedUp_; | |
334 | } |