]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/HttpRequest.cc
3 * $Id: HttpRequest.cc,v 1.69 2006/10/31 23:30:56 wessels Exp $
5 * DEBUG: section 73 HTTP Request
6 * AUTHOR: Duane Wessels
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
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.
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.
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.
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
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
34 * Copyright (c) 2003, Robert Collins <robertc@squid-cache.org>
38 #include "HttpRequest.h"
39 #include "AuthUserRequest.h"
40 #include "HttpHeaderRange.h"
44 HttpRequest::HttpRequest() : HttpMsg(hoRequest
)
49 HttpRequest::HttpRequest(method_t aMethod
, protocol_t aProtocol
, const char *aUrlpath
) : HttpMsg(hoRequest
)
52 initHTTP(aMethod
, aProtocol
, aUrlpath
);
55 HttpRequest::~HttpRequest()
61 HttpRequest::initHTTP(method_t aMethod
, protocol_t aProtocol
, const char *aUrlpath
)
72 protocol
= PROTO_NONE
;
76 auth_user_request
= NULL
;
79 memset(&flags
, '\0', sizeof(flags
));
85 client_addr
= no_addr
;
92 peer_login
= NULL
; // not allocated/deallocated by this class
93 peer_domain
= NULL
; // not allocated/deallocated by this class
96 extacl_user
= null_string
;
97 extacl_passwd
= null_string
;
98 extacl_log
= null_string
;
99 pstate
= psReadyToParseStartLine
;
105 if (body_reader
!= NULL
)
106 fatal ("request being destroyed with body reader intact\n");
108 if (auth_user_request
) {
109 auth_user_request
->unlock();
110 auth_user_request
= NULL
;
113 safe_free(canonical
);
115 safe_free(vary_headers
);
122 httpHdrCcDestroy(cache_control
);
123 cache_control
= NULL
;
135 extacl_passwd
.clean();
148 HttpRequest::sanityCheckStartLine(MemBuf
*buf
, http_status
*error
)
151 * Just see if the request buffer starts with a known
152 * HTTP request method. NOTE this whole function is somewhat
153 * superfluous and could just go away.
156 if (METHOD_NONE
== HttpRequestMethod(buf
->content())) {
157 debug(73, 3)("HttpRequest::sanityCheckStartLine: did not find HTTP request method\n");
165 HttpRequest::parseFirstLine(const char *start
, const char *end
)
167 const char *t
= start
+ strcspn(start
, w_space
);
168 method
= HttpRequestMethod(start
, t
);
170 if (METHOD_NONE
== method
)
173 start
= t
+ strspn(t
, w_space
);
175 const char *ver
= findTrailingHTTPVersion(start
, end
);
180 while (xisspace(*end
)) // find prev non-space
183 end
++; // back to space
185 if (2 != sscanf(ver
+ 5, "%d.%d", &http_ver
.major
, &http_ver
.minor
)) {
186 debug(73, 1) ("parseRequestLine: Invalid HTTP identifier.\n");
194 if (end
< start
) // missing URI
199 * (char *) end
= '\0'; // temp terminate URI, XXX dangerous?
201 HttpRequest
*tmp
= urlParse(method
, (char *) start
, this);
203 * (char *) end
= save
;
212 HttpRequest::parseHeader(const char *parse_start
, int len
)
214 const char *blk_start
, *blk_end
;
216 if (!httpMsgIsolateHeaders(&parse_start
, len
, &blk_start
, &blk_end
))
219 int result
= header
.parse(blk_start
, blk_end
);
227 /* swaps out request using httpRequestPack */
229 HttpRequest::swapOut(StoreEntry
* e
)
233 packerToStoreInit(&p
, e
);
238 /* packs request-line and headers, appends <crlf> terminator */
240 HttpRequest::pack(Packer
* p
)
243 /* pack request-line */
244 packerPrintf(p
, "%s %s HTTP/1.0\r\n",
245 RequestMethodStr
[method
], urlpath
.buf());
249 packerAppend(p
, "\r\n", 2);
253 * A wrapper for debugObj()
256 httpRequestPack(void *obj
, Packer
*p
)
258 HttpRequest
*request
= static_cast<HttpRequest
*>(obj
);
262 /* returns the length of request line + headers + crlf */
264 HttpRequest::prefixLen()
266 return strlen(RequestMethodStr
[method
]) + 1 +
273 * Returns true if HTTP allows us to pass this header on. Does not
274 * check anonymizer (aka header_access) configuration.
277 httpRequestHdrAllowed(const HttpHeaderEntry
* e
, String
* strConn
)
280 /* check connection header */
282 if (strConn
&& strListIsMember(strConn
, e
->name
.buf(), ','))
288 /* sync this routine when you update HttpRequest struct */
290 HttpRequest::hdrCacheInit()
292 HttpMsg::hdrCacheInit();
294 range
= header
.getRange();
299 request_flags::resetTCP() const
301 return reset_tcp
!= 0;
305 request_flags::setResetTCP()
307 debug (73, 9) ("request_flags::setResetTCP\n");
312 request_flags::clearResetTCP()
314 debug(73, 9) ("request_flags::clearResetTCP\n");
319 HttpRequest::multipartRangeRequest() const
321 return (range
&& range
->specs
.count
> 1);
325 request_flags::destinationIPLookupCompleted()
327 destinationIPLookedUp_
= true;
331 request_flags::destinationIPLookedUp() const
333 return destinationIPLookedUp_
;
336 const char *HttpRequest::packableURI(bool full_uri
) const
339 return urlCanonical((HttpRequest
*)this);
342 return urlpath
.buf();
347 void HttpRequest::packFirstLineInto(Packer
* p
, bool full_uri
) const
349 // form HTTP request-line
350 packerPrintf(p
, "%s %s HTTP/%d.%d\r\n",
351 RequestMethodStr
[method
],
352 packableURI(full_uri
),
353 http_ver
.major
, http_ver
.minor
);
357 * Indicate whether or not we would usually expect an entity-body
358 * along with this request
361 HttpRequest::expectingBody(method_t unused
, ssize_t
& theSize
) const
363 bool expectBody
= false;
366 * GET and HEAD don't usually have bodies, but we should be prepared
367 * to accept one if the request_entities directive is set
370 if (method
== METHOD_GET
|| method
== METHOD_HEAD
)
371 expectBody
= Config
.onoff
.request_entities
? true : false;
372 else if (method
== METHOD_PUT
|| method
== METHOD_POST
)
374 else if (header
.hasListMember(HDR_TRANSFER_ENCODING
, "chunked", ','))
376 else if (content_length
>= 0)
382 if (header
.hasListMember(HDR_TRANSFER_ENCODING
, "chunked", ','))
384 else if (content_length
>= 0)
385 theSize
= content_length
;
394 * Create a Request from a URL and METHOD.
396 * If the METHOD is CONNECT, then a host:port pair is looked for instead of a URL.
397 * If the request cannot be created cleanly, NULL is returned
400 HttpRequest::CreateFromUrlAndMethod(char * url
, method_t method
)
402 return urlParse(method
, url
, NULL
);
406 * Create a Request from a URL.
408 * If the request cannot be created cleanly, NULL is returned
411 HttpRequest::CreateFromUrl(char * url
)
413 return urlParse(METHOD_GET
, url
, NULL
);
417 * Are responses to this request possible cacheable ?
418 * If false then no matter what the response must not be cached.
421 HttpRequest::cacheable() const
423 if (protocol
== PROTO_HTTP
)
424 return httpCachable(method
);
426 /* FTP is always cachable */
428 /* WAIS is never cachable */
429 if (protocol
== PROTO_WAIS
)
433 * The below looks questionable: what non HTTP protocols use connect,
434 * trace, put and post? RC
436 if (method
== METHOD_CONNECT
)
439 if (method
== METHOD_TRACE
)
442 if (method
== METHOD_PUT
)
445 if (method
== METHOD_POST
)
449 * XXX POST may be cached sometimes.. ignored
452 if (protocol
== PROTO_GOPHER
)
453 return gopherCachable(this);
455 if (protocol
== PROTO_CACHEOBJ
)