=== modified file 'configure.ac' --- configure.ac 2012-06-12 08:50:53 +0000 +++ configure.ac 2012-06-15 03:45:44 +0000 @@ -3544,6 +3544,7 @@ src/esi/Makefile \ src/eui/Makefile \ src/format/Makefile \ + src/http/Makefile \ src/icmp/Makefile \ src/ident/Makefile \ src/ip/Makefile \ === modified file 'src/AccessLogEntry.h' --- src/AccessLogEntry.h 2012-07-19 00:12:22 +0000 +++ src/AccessLogEntry.h 2012-07-23 06:36:57 +0000 @@ -79,7 +79,7 @@ { public: - HttpDetails() : method(METHOD_NONE), code(0), content_type(NULL), + HttpDetails() : method(Http::METHOD_NONE), code(0), content_type(NULL), timedout(false), aborted(false) {} HttpRequestMethod method; === modified file 'src/HttpReply.cc' --- src/HttpReply.cc 2012-06-12 07:01:02 +0000 +++ src/HttpReply.cc 2012-06-15 03:45:44 +0000 @@ -426,7 +426,7 @@ { if (sline.version.major < 1) return -1; - else if (method.id() == METHOD_HEAD) + else if (method.id() == Http::METHOD_HEAD) return 0; else if (sline.status == HTTP_OK) (void) 0; /* common case, continue */ @@ -530,7 +530,7 @@ { bool expectBody = true; - if (req_method == METHOD_HEAD) + if (req_method == Http::METHOD_HEAD) expectBody = false; else if (sline.status == HTTP_NO_CONTENT) expectBody = false; === modified file 'src/HttpRequest.cc' --- src/HttpRequest.cc 2012-07-22 03:15:02 +0000 +++ src/HttpRequest.cc 2012-07-23 06:36:57 +0000 @@ -74,6 +74,7 @@ void HttpRequest::initHTTP(const HttpRequestMethod& aMethod, AnyP::ProtocolType aProtocol, const char *aUrlpath) { + maybeCacheable_ = -1; method = aMethod; protocol = aProtocol; urlpath = aUrlpath; @@ -82,7 +83,8 @@ void HttpRequest::init() { - method = METHOD_NONE; + maybeCacheable_ = -1; + method = Http::METHOD_NONE; protocol = AnyP::PROTO_NONE; urlpath = NULL; login[0] = '\0'; @@ -288,7 +290,7 @@ } /* See if the request buffer starts with a known HTTP request method. */ - if (HttpRequestMethod(buf->content(),NULL) == METHOD_NONE) { + if (HttpRequestMethod(buf->content(),NULL) == Http::METHOD_NONE) { debugs(73, 3, "HttpRequest::sanityCheckStartLine: did not find HTTP request method"); *error = HTTP_INVALID_HEADER; return false; @@ -303,7 +305,7 @@ const char *t = start + strcspn(start, w_space); method = HttpRequestMethod(start, t); - if (method == METHOD_NONE) + if (method == Http::METHOD_NONE) return false; start = t + strspn(t, w_space); @@ -605,44 +607,56 @@ HttpRequest * HttpRequest::CreateFromUrl(char * url) { - return urlParse(METHOD_GET, url, NULL); + return urlParse(Http::METHOD_GET, url, NULL); } -/* +/** * Are responses to this request possible cacheable ? * If false then no matter what the response must not be cached. */ bool -HttpRequest::cacheable() const +HttpRequest::maybeCacheable() { + if (maybeCacheable_ >= 0) + return (maybeCacheable_ == 1); + // Intercepted request with Host: header which cannot be trusted. // Because it failed verification, or someone bypassed the security tests // we cannot cache the reponse for sharing between clients. // TODO: update cache to store for particular clients only (going to same Host: and destination IP) - if (!flags.hostVerified && (flags.intercepted || flags.spoof_client_ip)) - return false; - - if (protocol == AnyP::PROTO_HTTP) - return httpCachable(method); - - /* - * The below looks questionable: what non HTTP protocols use connect, - * trace, put and post? RC - */ - - if (!method.isCacheble()) - return false; - - /* - * XXX POST may be cached sometimes.. ignored - * for now - */ - if (protocol == AnyP::PROTO_GOPHER) - return gopherCachable(this); - - if (protocol == AnyP::PROTO_CACHE_OBJECT) - return false; - + if (!flags.hostVerified && (flags.intercepted || flags.spoof_client_ip)) { + maybeCacheable_ = 0; + return false; + } + + switch(protocol) + { + case AnyP::PROTO_HTTP: + if (!method.respMaybeCacheable()) { + maybeCacheable_ = 0; + return false; + } + // XXX: this would seem the correct place to detect request cache-controls + // no-cache, no-store, private and related which block cacheability + break; + + case AnyP::PROTO_GOPHER: + if (!gopherCachable(this)) { + maybeCacheable_ = 0; + return false; + } + break; + + case AnyP::PROTO_CACHE_OBJECT: + maybeCacheable_ = 0; + return false; + + //case AnyP::PROTO_FTP: + default: + break; + } + + maybeCacheable_ = 1; return true; } === modified file 'src/HttpRequest.h' --- src/HttpRequest.h 2012-07-22 03:15:02 +0000 +++ src/HttpRequest.h 2012-07-23 06:36:57 +0000 @@ -77,8 +77,10 @@ virtual HttpRequest *clone() const; - /* are responses to this request potentially cachable */ - bool cacheable() const; + /// Whether response to this request is potentially cachable + /// \retval false Not cacheable. + /// \retval true Possibly cacheable. Response factors will determine. + bool maybeCacheable(); bool conditional() const; ///< has at least one recognized If-* header @@ -136,6 +138,7 @@ char login[MAX_LOGIN_SZ]; private: + volatile int8_t maybeCacheable_; char host[SQUIDHOSTNAMELEN]; int host_is_numeric; === modified file 'src/HttpRequestMethod.cc' --- src/HttpRequestMethod.cc 2012-01-20 18:55:04 +0000 +++ src/HttpRequestMethod.cc 2012-07-04 02:38:54 +0000 @@ -1,91 +1,21 @@ - -/* - * $Id$ - * - * DEBUG: section 73 HTTP Request - * AUTHOR: Duane Wessels - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - * Copyright (c) 2003, Robert Collins - */ - #include "squid-old.h" #include "HttpRequestMethod.h" #include "wordlist.h" -const char* HttpRequestMethod::RequestMethodStr[] = { - "NONE", - "GET", - "POST", - "PUT", - "HEAD", - "CONNECT", - "TRACE", - "PURGE", - "OPTIONS", - "DELETE", - "PROPFIND", - "PROPPATCH", - "MKCOL", - "COPY", - "MOVE", - "LOCK", - "UNLOCK", - "BMOVE", - "BDELETE", - "BPROPFIND", - "BPROPPATCH", - "BCOPY", - "SEARCH", - "SUBSCRIBE", - "UNSUBSCRIBE", - "POLL", - "REPORT", - "MKACTIVITY", - "CHECKOUT", - "MERGE", - "ERROR" -}; - static -_method_t &operator++ (_method_t &aMethod) +Http::MethodType &operator++ (Http::MethodType &aMethod) { int tmp = (int)aMethod; - aMethod = (_method_t)(++tmp); + aMethod = (Http::MethodType)(++tmp); return aMethod; } -/* +/** * Construct a HttpRequestMethod from a NULL terminated string such as "GET" * or from a range of chars, * such as "GET" from "GETFOOBARBAZ" * (pass in pointer to G and pointer to F.) */ -HttpRequestMethod::HttpRequestMethod(char const *begin, char const *end) : theMethod (METHOD_NONE) +HttpRequestMethod::HttpRequestMethod(char const *begin, char const *end) : theMethod (Http::METHOD_NONE) { if (begin == NULL) return; @@ -108,73 +38,26 @@ end = begin + strcspn(begin, w_space); if (end == begin) { - theMethod = METHOD_NONE; + theMethod = Http::METHOD_NONE; return; } - for (++theMethod; theMethod < METHOD_ENUM_END; ++theMethod) { - if (0 == strncasecmp(begin, RequestMethodStr[theMethod], end-begin)) { + for (++theMethod; theMethod < Http::METHOD_ENUM_END; ++theMethod) { + if (0 == strncasecmp(begin, Http::MethodType_str[theMethod], end-begin)) { return; } } // if method not found and method string is not null then it is other method - theMethod = METHOD_OTHER; + theMethod = Http::METHOD_OTHER; theImage.limitInit(begin,end-begin); } -/** \todo AYJ: this _should_ be obsolete. Since all such methods fit nicely into METHOD_OTHER now. */ -void -HttpRequestMethod::AddExtension(const char *mstr) -{ -#if 0 /* obsolete now that we have METHOD_OTHER always enabled */ - _method_t method = METHOD_NONE; - - for (++method; method < METHOD_ENUM_END; ++method) { - if (0 == strcmp(mstr, RequestMethodStr[method])) { - debugs(23, 2, "Extension method '" << mstr << "' already exists"); - return; - } - - if (0 != strncmp("%EXT", RequestMethodStr[method], 4)) - continue; - - /* Don't free statically allocated "%EXTnn" string */ - RequestMethodStr[method] = xstrdup(mstr); - - debugs(23, 1, "Extension method '" << mstr << "' added, enum=" << method); - - return; - } - - debugs(23, 1, "WARNING: Could not add new extension method '" << mstr << "' due to lack of array space"); -#endif -} - -void -HttpRequestMethod::Configure(SquidConfig &cfg) -{ -#if 0 /* extension methods obsolete now that we have METHOD_OTHER always enabled */ - wordlist *w = cfg.ext_methods; - - while (w) { - char *s; - - for (s = w->key; *s; s++) - *s = xtoupper(*s); - - AddExtension(w->key); - - w = w->next; - } -#endif -} - char const* HttpRequestMethod::image() const { - if (METHOD_OTHER != theMethod) { - return RequestMethodStr[theMethod]; + if (Http::METHOD_OTHER != theMethod) { + return Http::MethodType_str[theMethod]; } else { if (theImage.size()>0) { return theImage.termedBuf(); @@ -185,60 +68,163 @@ } bool -HttpRequestMethod::isCacheble() const -{ - // TODO: optimize the lookup with a precomputed flags array - // XXX: the list seems wrong; e.g., Is METHOD_DELETE really cachable? - // see also http.cc::httpCachable() - - if (theMethod == METHOD_CONNECT) - return false; - - if (theMethod == METHOD_TRACE) - return false; - - if (theMethod == METHOD_PUT) - return false; - - if (theMethod == METHOD_POST) - return false; - - if (theMethod == METHOD_OTHER) - return false; - - return true; -} - -bool -HttpRequestMethod::purgesOthers() const -{ - // TODO: optimize the lookup with a precomputed flags array - +HttpRequestMethod::isHttpSafe() const +{ + // Only a few methods are defined as safe. All others are "unsafe" + + // NOTE: + // All known RFCs which register methods are listed in comments. + // if there is one not listed which defines methods, it needs + // checking and adding. If only to say it is known to define none. + + switch(theMethod) + { + // RFC 2068 - none + + // RFC 2616 section 9.1.1 + case Http::METHOD_GET: + case Http::METHOD_HEAD: + case Http::METHOD_OPTIONS: + + // RFC 3253 section 3.6 + case Http::METHOD_REPORT: + + // RFC 3648 - none + // RFC 3744 - none + // RFC 4437 - none + // RFC 4791 - none + + // RFC 4918 section 9.1 + case Http::METHOD_PROPFIND: + + // RFC 5323 section 2 + case Http::METHOD_SEARCH: + + // RFC 5789 - none + // RFC 5842 - none + + return true; + + default: + return false; + } +} + +bool +HttpRequestMethod::isIdempotent() const +{ + // Only a few methods are defined as idempotent. + + // NOTE: + // All known RFCs which register methods are listed in comments. + // if there is one not listed which defines methods, it needs + // checking and adding. If only to say it is known to define none. + + switch(theMethod) + { + // RFC 2068 - TODO check LINK/UNLINK definition + + // RFC 2616 section 9.1.2 + case Http::METHOD_GET: + case Http::METHOD_HEAD: + case Http::METHOD_PUT: + case Http::METHOD_DELETE: + case Http::METHOD_OPTIONS: + case Http::METHOD_TRACE: + + // RFC 3253 - TODO check + // RFC 3648 - TODO check + // RFC 3744 - TODO check + // RFC 4437 - TODO check + // RFC 4791 - TODO check + + // RFC 4918 section 9 + case Http::METHOD_PROPFIND: + case Http::METHOD_PROPPATCH: + case Http::METHOD_MKCOL: + case Http::METHOD_COPY: + case Http::METHOD_MOVE: + case Http::METHOD_UNLOCK: + + // RFC 5323 - TODO check + // RFC 5789 - TODO check + // RFC 5842 - TODO check + + return true; + + default: + return false; + } +} + +bool +HttpRequestMethod::respMaybeCacheable() const +{ + // Only a few methods are defined as cacheable. + // All other methods from the below RFC are "MUST NOT cache" + switch(theMethod) + { + // RFC 2616 section 9 + case Http::METHOD_GET: + case Http::METHOD_HEAD: + return true; +#if WHEN_POST_CACHE_SUPPORTED + case Http::METHOD_POST: // Special case. + // RFC 2616 specifies POST as possibly cacheable + // However, Squid does not implement the required checks yet + return true; +#endif + + // RFC 4918 section 9 +#if WHEN_PROPFIND_CACHE_SUPPORTED + case Http::METHOD_PROPFIND: // Special case. + // RFC 4918 specifies PROPFIND as possibly cacheable + // However, Squid does not implement the required checks yet + return true; +#endif + + // RFC 5323 section 2 - defines no cacheable methods + + // RFC 3253 +#if WHEN_CC_NOCACHE_DOES_REVALIDATES_IS_CONFIRMED + case Http::METHOD_CHECKOUT: + case Http::METHOD_CHECKIN: + case Http::METHOD_UNCHECKOUT: + case Http::METHOD_MKWORKSPACE: + case Http::METHOD_VERSION_CONTROL: + case Http::METHOD_UPDATE: + case Http::METHOD_LABEL: + case Http::METHOD_MERGE: + case Http::METHOD_BASELINE_CONTROL: + case Http::METHOD_MKACTIVITY: + // RFC 3253 defines these methods using "MUST include Cache-Control: no-cache". + // + // XXX: follow RFC 2616 definition of "no-cache" meaning "MAY cache, always revalidate" + // XXX: or treat as unregistered/undefined methods ?? + // However, Squid may not implement the required revalidation checks yet + return ??; +#endif + + // Special Squid method tokens are not cacheable. + // RFC 2616 defines all unregistered or unspecified methods as non-cacheable + // until such time as an RFC defines them cacheable. + default: + return false; + } +} + +bool +HttpRequestMethod::shouldInvalidate() const +{ switch (theMethod) { - /* common sense suggests purging is not required? */ - case METHOD_GET: // XXX: but we do purge HEAD on successful GET - case METHOD_HEAD: - case METHOD_NONE: - case METHOD_CONNECT: - case METHOD_TRACE: - case METHOD_OPTIONS: - case METHOD_PROPFIND: - case METHOD_BPROPFIND: - case METHOD_COPY: - case METHOD_BCOPY: - case METHOD_LOCK: - case METHOD_UNLOCK: - case METHOD_SEARCH: - return false; - - /* purging mandated by RFC 2616 */ - case METHOD_POST: - case METHOD_PUT: - case METHOD_DELETE: + /* RFC 2616 section 13.10 - "MUST invalidate" */ + case Http::METHOD_POST: + case Http::METHOD_PUT: + case Http::METHOD_DELETE: return true; - /* purging suggested by common sense */ - case METHOD_PURGE: + /* Squid extension to force invalidation */ + case Http::METHOD_PURGE: return true; /* @@ -247,10 +233,37 @@ * understand SHOULD invalidate any entities referred to by the * Request-URI. */ - case METHOD_OTHER: - default: - return true; - } - - return true; // not reached, but just in case + case Http::METHOD_OTHER: + return true; + + default: + // Methods which are known but not required to invalidate. + return false; + } +} + +bool +HttpRequestMethod::purgesOthers() const +{ + if (shouldInvalidate()) + return true; + + switch (theMethod) { + /* common sense suggests purging is not required? */ + case Http::METHOD_GET: // XXX: but we do purge HEAD on successful GET + case Http::METHOD_HEAD: + case Http::METHOD_NONE: + case Http::METHOD_CONNECT: + case Http::METHOD_TRACE: + case Http::METHOD_OPTIONS: + case Http::METHOD_PROPFIND: + case Http::METHOD_COPY: + case Http::METHOD_LOCK: + case Http::METHOD_UNLOCK: + case Http::METHOD_SEARCH: + return false; + + default: + return true; + } } === modified file 'src/HttpRequestMethod.h' --- src/HttpRequestMethod.h 2012-01-20 18:55:04 +0000 +++ src/HttpRequestMethod.h 2012-07-10 11:10:38 +0000 @@ -1,95 +1,26 @@ -/* - * $Id$ - * - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - #ifndef SQUID_HTTPREQUESTMETHOD_H #define SQUID_HTTPREQUESTMETHOD_H -#include "squid-old.h" +#include "http/MethodType.h" +#include "SquidString.h" + #include -#include "SquidString.h" - -enum _method_t { - METHOD_NONE, /* 000 */ - METHOD_GET, /* 001 */ - METHOD_POST, /* 010 */ - METHOD_PUT, /* 011 */ - METHOD_HEAD, /* 100 */ - METHOD_CONNECT, /* 101 */ - METHOD_TRACE, /* 110 */ - METHOD_PURGE, /* 111 */ - METHOD_OPTIONS, - METHOD_DELETE, /* RFC2616 section 9.7 */ - METHOD_PROPFIND, - METHOD_PROPPATCH, - METHOD_MKCOL, - METHOD_COPY, - METHOD_MOVE, - METHOD_LOCK, - METHOD_UNLOCK, - METHOD_BMOVE, - METHOD_BDELETE, - METHOD_BPROPFIND, - METHOD_BPROPPATCH, - METHOD_BCOPY, - METHOD_SEARCH, - METHOD_SUBSCRIBE, - METHOD_UNSUBSCRIBE, - METHOD_POLL, - METHOD_REPORT, - METHOD_MKACTIVITY, - METHOD_CHECKOUT, - METHOD_MERGE, - METHOD_OTHER, - METHOD_ENUM_END // MUST be last, (yuck) this is used as an array-initialization index constant! -}; - /** * This class represents an HTTP Request METHOD * - i.e. PUT, POST, GET etc. * It has a runtime extension facility to allow it to * efficiently support new methods - \ingroup POD */ class HttpRequestMethod { public: - static void AddExtension(const char *methodString); - static void Configure(SquidConfig &Config); - - HttpRequestMethod() : theMethod(METHOD_NONE), theImage() {} - - HttpRequestMethod(_method_t const aMethod) : theMethod(aMethod), theImage() {} +// static void Configure(SquidConfig &Config); + + HttpRequestMethod() : theMethod(Http::METHOD_NONE), theImage() {} + + HttpRequestMethod(Http::MethodType const aMethod) : theMethod(aMethod), theImage() {} /** \param begin string to convert to request method. @@ -105,19 +36,19 @@ return *this; } - HttpRequestMethod & operator = (_method_t const aMethod) { + HttpRequestMethod & operator = (Http::MethodType const aMethod) { theMethod = aMethod; theImage.clean(); return *this; } - bool operator == (_method_t const & aMethod) const { return theMethod == aMethod; } + bool operator == (Http::MethodType const & aMethod) const { return theMethod == aMethod; } bool operator == (HttpRequestMethod const & aMethod) const { return theMethod == aMethod.theMethod && - (theMethod != METHOD_OTHER || theImage == aMethod.theImage); + (theMethod != Http::METHOD_OTHER || theImage == aMethod.theImage); } - bool operator != (_method_t const & aMethod) const { return theMethod != aMethod; } + bool operator != (Http::MethodType const & aMethod) const { return theMethod != aMethod; } bool operator != (HttpRequestMethod const & aMethod) const { return !operator==(aMethod); } @@ -126,30 +57,62 @@ HttpRequestMethod& operator++() { // TODO: when this operator is used in more than one place, // replace it with HttpRequestMethods::Iterator API - // XXX: this interface can create METHOD_OTHER without an image - assert(theMethod < METHOD_ENUM_END); - theMethod = (_method_t)(1 + (int)theMethod); + // XXX: this interface can create Http::METHOD_OTHER without an image + assert(theMethod < Http::METHOD_ENUM_END); + theMethod = (Http::MethodType)(1 + (int)theMethod); return *this; } /** Get an ID representation of the method. - \retval METHOD_NONE the method is unset - \retval METHOD_OTHER the method is not recognized and has no unique ID - \retval * the method is on of the recognized HTTP methods. + * \retval Http::METHOD_NONE the method is unset + * \retval Http::METHOD_OTHER the method is not recognized and has no unique ID + * \retval * the method is on of the recognized HTTP methods. */ - _method_t id() const { return theMethod; } + Http::MethodType id() const { return theMethod; } /** Get a char string representation of the method. */ char const * image() const; - bool isCacheble() const; + /// Whether this method is defined as a "safe" in HTTP/1.1 + /// see RFC 2616 section 9.1.1 + bool isHttpSafe() const; + + /// Whether this method is defined as "idempotent" in HTTP/1.1 + /// see RFC 2616 section 9.1.2 + bool isIdempotent() const; + + /** Whether responses to this method MAY be cached. + * \retval false Not cacheable. + * \retval true Possibly cacheable. Other details will determine. + */ + bool respMaybeCacheable() const; + + /** Whether this method SHOULD (or MUST) invalidate existing cached entries. + * Invalidation is always determined by the response + * + * RFC 2616 defines invalidate as either immediate purge + * or delayed explicit revalidate all stored copies on next use. + * + * \retval true SHOULD invalidate. Response details can raise this to a MUST. + * \retval false Other details will determine. Method is not a factor. + */ + bool shouldInvalidate() const; + + /* Whether this method invalidates existing cached entries. + * Kept for backward-compatibility. This is the old 2.x-3.2 invalidation behaviour. + * + * NOTE: + * purgesOthers differs from shouldInvalidate() in that purgesOthers() returns + * true on any methods the MAY invalidate (Squid opts to do so). + * shouldInvalidate() only returns true on methods which SHOULD invalidate. + */ bool purgesOthers() const; private: static const char *RequestMethodStr[]; - _method_t theMethod; ///< Method type - String theImage; ///< Used for store METHOD_OTHER only + Http::MethodType theMethod; ///< Method type + String theImage; ///< Used for storing the Http::METHOD_OTHER only. A copy of the parsed method text. }; inline std::ostream & @@ -160,7 +123,7 @@ } inline const char* -RequestMethodStr(const _method_t m) +RequestMethodStr(const Http::MethodType m) { return HttpRequestMethod(m).image(); } === modified file 'src/Makefile.am' --- src/Makefile.am 2012-07-18 16:21:47 +0000 +++ src/Makefile.am 2012-07-23 06:36:57 +0000 @@ -43,8 +43,8 @@ endif DIST_SUBDIRS += auth -SUBDIRS += ip icmp ident log ipc mgr -DIST_SUBDIRS += ip icmp ident log ipc mgr +SUBDIRS += http ip icmp ident log ipc mgr +DIST_SUBDIRS += http ip icmp ident log ipc mgr if ENABLE_SSL SUBDIRS += ssl @@ -572,6 +572,7 @@ anyp/libanyp.la \ comm/libcomm.la \ eui/libeui.la \ + http/libsquid-http.la \ icmp/libicmp.la icmp/libicmp-core.la \ log/liblog.la \ format/libformat.la \ @@ -1221,6 +1222,7 @@ nodist_tests_testACLMaxUserIP_SOURCES= \ $(TESTSOURCES) tests_testACLMaxUserIP_LDADD= \ + http/libsquid-http.la \ $(AUTH_ACL_LIBS) \ ident/libident.la \ acl/libacls.la \ @@ -1413,6 +1415,7 @@ $(DISKIO_GEN_SOURCE) # comm.cc only requires comm/libcomm.la until fdc_table is dead. tests_testCacheManager_LDADD = \ + http/libsquid-http.la \ $(AUTH_ACL_LIBS) \ ident/libident.la \ acl/libacls.la \ @@ -1561,6 +1564,7 @@ SquidMath.h \ swap_log_op.cc tests_testDiskIO_LDADD = \ + http/libsquid-http.la \ SquidConfig.o \ CommCalls.o \ DnsLookupDetails.o \ @@ -1751,6 +1755,7 @@ $(BUILT_SOURCES) \ $(DISKIO_GEN_SOURCE) tests_testEvent_LDADD = \ + http/libsquid-http.la \ $(AUTH_ACL_LIBS) \ ident/libident.la \ acl/libacls.la \ @@ -1942,6 +1947,7 @@ $(BUILT_SOURCES) \ $(DISKIO_GEN_SOURCE) tests_testEventLoop_LDADD = \ + http/libsquid-http.la \ $(AUTH_ACL_LIBS) \ ident/libident.la \ acl/libacls.la \ @@ -2128,6 +2134,7 @@ $(BUILT_SOURCES) \ $(DISKIO_GEN_SOURCE) tests_test_http_range_LDADD = \ + http/libsquid-http.la \ $(AUTH_ACL_LIBS) \ ident/libident.la \ acl/libacls.la \ @@ -2191,6 +2198,7 @@ nodist_tests_testHttpParser_SOURCES = \ $(TESTSOURCES) tests_testHttpParser_LDADD= \ + http/libsquid-http.la \ SquidConfig.o \ base/libbase.la \ ip/libip.la \ @@ -2368,6 +2376,7 @@ comm/libcomm.la \ log/liblog.la \ format/libformat.la \ + http/libsquid-http.la \ $(REPL_OBJS) \ $(ADAPTATION_LIBS) \ $(ESI_LIBS) \ @@ -2501,6 +2510,7 @@ swap_log_op.cc tests_testStore_LDADD= \ + http/libsquid-http.la \ $(AUTH_ACL_LIBS) \ ident/libident.la \ acl/libacls.la \ @@ -2690,6 +2700,7 @@ SquidMath.h \ swap_log_op.cc tests_testUfs_LDADD = \ + http/libsquid-http.la \ CommCalls.o \ DnsLookupDetails.o \ $(AUTH_ACL_LIBS) \ @@ -2825,6 +2836,7 @@ SquidMath.h \ $(TESTSOURCES) tests_testRock_LDADD = \ + http/libsquid-http.la \ libsquid.la \ comm/libcomm.la \ anyp/libanyp.la \ @@ -3269,6 +3281,7 @@ nodist_tests_testURL_SOURCES = \ $(BUILT_SOURCES) tests_testURL_LDADD = \ + http/libsquid-http.la \ anyp/libanyp.la \ $(AUTH_ACL_LIBS) \ ident/libident.la \ === modified file 'src/acl/Asn.cc' --- src/acl/Asn.cc 2012-07-02 12:28:10 +0000 +++ src/acl/Asn.cc 2012-07-03 01:48:15 +0000 @@ -249,8 +249,8 @@ assert(NULL != req); asState->request = HTTPMSGLOCK(req); - if ((e = storeGetPublic(asres, METHOD_GET)) == NULL) { - e = storeCreateEntry(asres, asres, request_flags(), METHOD_GET); + if ((e = storeGetPublic(asres, Http::METHOD_GET)) == NULL) { + e = storeCreateEntry(asres, asres, request_flags(), Http::METHOD_GET); asState->sc = storeClientListAdd(e, asState); FwdState::fwdStart(Comm::ConnectionPointer(), e, asState->request); } else { === modified file 'src/adaptation/ecap/MessageRep.cc' --- src/adaptation/ecap/MessageRep.cc 2012-06-11 06:03:50 +0000 +++ src/adaptation/ecap/MessageRep.cc 2012-06-15 03:45:44 +0000 @@ -228,7 +228,7 @@ const int id = aMethod.hostId(); Must(METHOD_NONE < id && id < METHOD_ENUM_END); Must(id != METHOD_OTHER); - theMessage.method = HttpRequestMethod(static_cast<_method_t>(id)); + theMessage.method = HttpRequestMethod(static_cast(id)); } else { const std::string &image = aMethod.image(); theMessage.method = HttpRequestMethod(image.data(), === modified file 'src/adaptation/icap/ModXact.cc' --- src/adaptation/icap/ModXact.cc 2012-07-19 00:12:22 +0000 +++ src/adaptation/icap/ModXact.cc 2012-07-23 08:56:52 +0000 @@ -1748,12 +1748,12 @@ else if (HttpRequest *req = dynamic_cast(msg)) method = req->method; else - method = METHOD_NONE; + method = Http::METHOD_NONE; int64_t size; // expectingBody returns true for zero-sized bodies, but we will not // get a pipe for that body, so we treat the message as bodyless - if (method != METHOD_NONE && msg->expectingBody(method, size) && size) { + if (method != Http::METHOD_NONE && msg->expectingBody(method, size) && size) { debugs(93, 6, HERE << "expects virgin body from " << virgin.body_pipe << "; size: " << size); === modified file 'src/auth/digest/UserRequest.cc' --- src/auth/digest/UserRequest.cc 2012-06-19 23:16:13 +0000 +++ src/auth/digest/UserRequest.cc 2012-07-03 01:48:15 +0000 @@ -103,7 +103,7 @@ return; } - if (static_cast(Auth::Config::Find("digest"))->PostWorkaround && request->method != METHOD_GET) { + if (static_cast(Auth::Config::Find("digest"))->PostWorkaround && request->method != Http::METHOD_GET) { /* Ugly workaround for certain very broken browsers using the * wrong method to calculate the request-digest on POST request. * This should be deleted once Digest authentication becomes more @@ -112,7 +112,7 @@ */ DigestCalcResponse(SESSIONKEY, authenticateDigestNonceNonceb64(digest_request->nonce), digest_request->nc, digest_request->cnonce, digest_request->qop, - RequestMethodStr(METHOD_GET), digest_request->uri, HA2, Response); + RequestMethodStr(Http::METHOD_GET), digest_request->uri, HA2, Response); if (strcasecmp(digest_request->response, Response)) { auth_user->credentials(Auth::Failed); === modified file 'src/cache_cf.cc' --- src/cache_cf.cc 2012-07-19 00:12:22 +0000 +++ src/cache_cf.cc 2012-07-23 06:36:57 +0000 @@ -890,7 +890,6 @@ Config2.effectiveGroupID = grp->gr_gid; } - HttpRequestMethod::Configure(Config); #if USE_SSL debugs(3, 1, "Initializing https proxy context"); === modified file 'src/client_side.cc' --- src/client_side.cc 2012-07-22 03:15:02 +0000 +++ src/client_side.cc 2012-07-23 06:36:57 +0000 @@ -842,9 +842,9 @@ { switch (r->method.id()) { - case METHOD_GET: + case Http::METHOD_GET: - case METHOD_HEAD: + case Http::METHOD_HEAD: /* We do not want to see a request entity on GET/HEAD requests */ return (r->content_length <= 0 || Config.onoff.request_entities); @@ -2132,7 +2132,7 @@ int r; /* pre-set these values to make aborting simpler */ - *method_p = METHOD_NONE; + *method_p = Http::METHOD_NONE; /* NP: don't be tempted to move this down or remove again. * It's the only DDoS protection old-String has against long URL */ @@ -2194,7 +2194,7 @@ *method_p = HttpRequestMethod(&hp->buf[hp->req.m_start], &hp->buf[hp->req.m_end]+1); /* deny CONNECT via accelerated ports */ - if (*method_p == METHOD_CONNECT && csd && csd->port && csd->port->accel) { + if (*method_p == Http::METHOD_CONNECT && csd && csd->port && csd->port->accel) { debugs(33, DBG_IMPORTANT, "WARNING: CONNECT method received on " << csd->port->protocol << " Accelerator port " << csd->port->s.GetPort() ); /* XXX need a way to say "this many character length string" */ debugs(33, DBG_IMPORTANT, "WARNING: for request: " << hp->buf); @@ -2202,7 +2202,7 @@ return parseHttpRequestAbort(csd, "error:method-not-allowed"); } - if (*method_p == METHOD_NONE) { + if (*method_p == Http::METHOD_NONE) { /* XXX need a way to say "this many character length string" */ debugs(33, 1, "clientParseRequestMethod: Unsupported method in request '" << hp->buf << "'"); hp->request_parse_status = HTTP_METHOD_NOT_ALLOWED; @@ -2428,7 +2428,7 @@ clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); repContext->setReplyToError(ERR_TOO_BIG, - HTTP_BAD_REQUEST, METHOD_NONE, NULL, + HTTP_BAD_REQUEST, Http::METHOD_NONE, NULL, clientConnection->remote, NULL, NULL, NULL); context->registerWithConn(); context->pullData(); @@ -2698,7 +2698,7 @@ unsupportedTe = te.size() && te != "identity"; } // else implied identity coding - mustReplyToOptions = (method == METHOD_OPTIONS) && + mustReplyToOptions = (method == Http::METHOD_OPTIONS) && (request->header.getInt64(HDR_MAX_FORWARDS) == 0); if (!urlCheckRequest(request) || mustReplyToOptions || unsupportedTe) { clientStreamNode *node = context->getClientReplyContext(); @@ -2746,7 +2746,7 @@ clientSetKeepaliveFlag(http); // Let tunneling code be fully responsible for CONNECT requests - if (http->request->method == METHOD_CONNECT) { + if (http->request->method == Http::METHOD_CONNECT) { context->mayUseConnection(true); conn->flags.readMore = false; } @@ -2774,7 +2774,7 @@ assert (repContext); conn->quitAfterError(request); repContext->setReplyToError(ERR_TOO_BIG, - HTTP_REQUEST_ENTITY_TOO_LARGE, METHOD_NONE, NULL, + HTTP_REQUEST_ENTITY_TOO_LARGE, Http::METHOD_NONE, NULL, conn->clientConnection->remote, http->request, NULL, NULL); assert(context->http->out.offset == 0); context->pullData(); @@ -3202,7 +3202,7 @@ clientReplyContext *repContext = dynamic_cast(node->data.getRaw()); assert (repContext); repContext->setReplyToError(ERR_LIFETIME_EXP, - HTTP_REQUEST_TIMEOUT, METHOD_NONE, "N/A", &peer.sin_addr, + HTTP_REQUEST_TIMEOUT, Http::METHOD_NONE, "N/A", &peer.sin_addr, NULL, NULL, NULL); /* No requests can be outstanded */ assert(chr == NULL); === modified file 'src/client_side_reply.cc' --- src/client_side_reply.cc 2012-07-22 03:15:02 +0000 +++ src/client_side_reply.cc 2012-07-23 06:36:57 +0000 @@ -529,7 +529,7 @@ return; } - if (r->method == METHOD_PURGE) { + if (r->method == Http::METHOD_PURGE) { removeClientStoreReference(&sc, http); e = NULL; purgeRequest(); @@ -632,13 +632,13 @@ } /** Check if its a PURGE request to be actioned. */ - if (r->method == METHOD_PURGE) { + if (r->method == Http::METHOD_PURGE) { purgeRequest(); return; } /** Check if its an 'OTHER' request. Purge all cached entries if so and continue. */ - if (r->method == METHOD_OTHER) { + if (r->method == Http::METHOD_OTHER) { purgeAllCached(); } @@ -777,7 +777,7 @@ // TODO: can we use purgeAllCached() here instead of doing the // getPublicByRequestMethod() dance? - StoreEntry::getPublicByRequestMethod(this, http->request, METHOD_GET); + StoreEntry::getPublicByRequestMethod(this, http->request, Http::METHOD_GET); } // Purges all entries with a given url @@ -793,13 +793,13 @@ bool get_or_head_sent = false; #endif - for (HttpRequestMethod m(METHOD_NONE); m != METHOD_ENUM_END; ++m) { - if (m.isCacheble()) { + for (HttpRequestMethod m(Http::METHOD_NONE); m != Http::METHOD_ENUM_END; ++m) { + if (m.respMaybeCacheable()) { if (StoreEntry *entry = storeGetPublic(url, m)) { debugs(88, 5, "purging " << RequestMethodStr(m) << ' ' << url); #if USE_HTCP neighborsHtcpClear(entry, url, req, m, HTCP_CLR_INVALIDATION); - if (m == METHOD_GET || m == METHOD_HEAD) { + if (m == Http::METHOD_GET || m == Http::METHOD_HEAD) { get_or_head_sent = true; } #endif @@ -810,7 +810,7 @@ #if USE_HTCP if (!get_or_head_sent) { - neighborsHtcpClear(NULL, url, req, HttpRequestMethod(METHOD_GET), HTCP_CLR_INVALIDATION); + neighborsHtcpClear(NULL, url, req, HttpRequestMethod(Http::METHOD_GET), HTCP_CLR_INVALIDATION); } #endif } @@ -842,7 +842,7 @@ { if (newEntry->isNull()) { lookingforstore = 2; - StoreEntry::getPublicByRequestMethod(this, http->request, METHOD_HEAD); + StoreEntry::getPublicByRequestMethod(this, http->request, Http::METHOD_HEAD); } else purgeFoundObject (newEntry); } @@ -921,7 +921,7 @@ { http->logType = LOG_TCP_MISS; lookingforstore = 3; - StoreEntry::getPublicByRequestMethod(this,http->request, METHOD_GET); + StoreEntry::getPublicByRequestMethod(this,http->request, Http::METHOD_GET); } void @@ -935,14 +935,14 @@ /* Release the cached URI */ debugs(88, 4, "clientPurgeRequest: GET '" << newEntry->url() << "'" ); #if USE_HTCP - neighborsHtcpClear(newEntry, NULL, http->request, HttpRequestMethod(METHOD_GET), HTCP_CLR_PURGE); + neighborsHtcpClear(newEntry, NULL, http->request, HttpRequestMethod(Http::METHOD_GET), HTCP_CLR_PURGE); #endif newEntry->release(); purgeStatus = HTTP_OK; } lookingforstore = 4; - StoreEntry::getPublicByRequestMethod(this, http->request, METHOD_HEAD); + StoreEntry::getPublicByRequestMethod(this, http->request, Http::METHOD_HEAD); } void @@ -951,7 +951,7 @@ if (newEntry && !newEntry->isNull()) { debugs(88, 4, "clientPurgeRequest: HEAD '" << newEntry->url() << "'" ); #if USE_HTCP - neighborsHtcpClear(newEntry, NULL, http->request, HttpRequestMethod(METHOD_HEAD), HTCP_CLR_PURGE); + neighborsHtcpClear(newEntry, NULL, http->request, HttpRequestMethod(Http::METHOD_HEAD), HTCP_CLR_PURGE); #endif newEntry->release(); purgeStatus = HTTP_OK; @@ -961,23 +961,23 @@ if (http->request->vary_headers && !strstr(http->request->vary_headers, "=")) { - StoreEntry *entry = storeGetPublic(urlCanonical(http->request), METHOD_GET); + StoreEntry *entry = storeGetPublic(urlCanonical(http->request), Http::METHOD_GET); if (entry) { debugs(88, 4, "clientPurgeRequest: Vary GET '" << entry->url() << "'" ); #if USE_HTCP - neighborsHtcpClear(entry, NULL, http->request, HttpRequestMethod(METHOD_GET), HTCP_CLR_PURGE); + neighborsHtcpClear(entry, NULL, http->request, HttpRequestMethod(Http::METHOD_GET), HTCP_CLR_PURGE); #endif entry->release(); purgeStatus = HTTP_OK; } - entry = storeGetPublic(urlCanonical(http->request), METHOD_HEAD); + entry = storeGetPublic(urlCanonical(http->request), Http::METHOD_HEAD); if (entry) { debugs(88, 4, "clientPurgeRequest: Vary HEAD '" << entry->url() << "'" ); #if USE_HTCP - neighborsHtcpClear(entry, NULL, http->request, HttpRequestMethod(METHOD_HEAD), HTCP_CLR_PURGE); + neighborsHtcpClear(entry, NULL, http->request, HttpRequestMethod(Http::METHOD_HEAD), HTCP_CLR_PURGE); #endif entry->release(); purgeStatus = HTTP_OK; @@ -1705,14 +1705,14 @@ return; } - if (context->http->request->method == METHOD_PURGE) { + if (context->http->request->method == Http::METHOD_PURGE) { context->purgeRequest(); return; } // OPTIONS with Max-Forwards:0 handled in clientProcessRequest() - if (context->http->request->method == METHOD_TRACE) { + if (context->http->request->method == Http::METHOD_TRACE) { if (context->http->request->header.getInt64(HDR_MAX_FORWARDS) == 0) { context->traceReply(aNode); return; @@ -1916,8 +1916,8 @@ void clientReplyContext::sendNotModifiedOrPreconditionFailedError() { - if (http->request->method == METHOD_GET || - http->request->method == METHOD_HEAD) + if (http->request->method == Http::METHOD_GET || + http->request->method == Http::METHOD_HEAD) sendNotModified(); else sendPreconditionFailedError(); @@ -2024,7 +2024,7 @@ #endif - if (http->request->method == METHOD_HEAD) { + if (http->request->method == Http::METHOD_HEAD) { /* do not forward body for HEAD replies */ body_size = 0; http->flags.done_copying = 1; === modified file 'src/client_side_request.cc' --- src/client_side_request.cc 2012-07-19 00:12:22 +0000 +++ src/client_side_request.cc 2012-07-23 06:59:55 +0000 @@ -568,7 +568,7 @@ { // IP address validation for Host: failed. Admin wants to ignore them. // NP: we do not yet handle CONNECT tunnels well, so ignore for them - if (!Config.onoff.hostStrictVerify && http->request->method != METHOD_CONNECT) { + if (!Config.onoff.hostStrictVerify && http->request->method != Http::METHOD_CONNECT) { debugs(85, 3, "SECURITY ALERT: Host header forgery detected on " << http->getConn()->clientConnection << " (" << A << " does not match " << B << ") on URL: " << urlCanonical(http->request)); @@ -678,7 +678,7 @@ // Verify forward-proxy requested URL domain matches the Host: header debugs(85, 3, HERE << "FAIL on validate URL port " << http->request->port << " matches Host: port " << portStr); hostHeaderVerifyFailed("URL port", portStr); - } else if (!portStr && http->request->method != METHOD_CONNECT && http->request->port != urlDefaultPort(http->request->protocol)) { + } else if (!portStr && http->request->method != Http::METHOD_CONNECT && http->request->port != urlDefaultPort(http->request->protocol)) { // Verify forward-proxy requested URL domain matches the Host: header // Special case: we don't have a default-port to check for CONNECT. Assume URL is correct. debugs(85, 3, HERE << "FAIL on validate URL port " << http->request->port << " matches Host: default port " << urlDefaultPort(http->request->protocol)); @@ -929,10 +929,10 @@ if (request->flags.auth) return 0; - if (method == METHOD_TRACE) + if (method == Http::METHOD_TRACE) return 1; - if (method != METHOD_GET) + if (method != Http::METHOD_GET) return 0; /* scan hierarchy_stoplist */ @@ -944,7 +944,7 @@ return 0; if (request->protocol == AnyP::PROTO_HTTP) - return httpCachable(method); + return method.respMaybeCacheable(); if (request->protocol == AnyP::PROTO_GOPHER) return gopherCachable(request); @@ -1069,7 +1069,7 @@ } } - if (request->method == METHOD_OTHER) { + if (request->method == Http::METHOD_OTHER) { no_cache++; } @@ -1087,7 +1087,7 @@ } /* ignore range header in non-GETs or non-HEADs */ - if (request->method == METHOD_GET || request->method == METHOD_HEAD) { + if (request->method == Http::METHOD_GET || request->method == Http::METHOD_HEAD) { // XXX: initialize if we got here without HttpRequest::parseHeader() if (!request->range) request->range = req_hdr->getRange(); @@ -1158,7 +1158,7 @@ #endif - request->flags.cachable = http->request->cacheable(); + request->flags.cachable = http->request->maybeCacheable(); if (clientHierarchical(http)) request->flags.hierarchical = 1; @@ -1300,7 +1300,7 @@ // Bumping here can only start with a CONNECT request on a bumping port // (bumping of intercepted SSL conns is decided before we get 1st request). // We also do not bump redirected CONNECT requests. - if (http->request->method != METHOD_CONNECT || http->redirect.status || + if (http->request->method != Http::METHOD_CONNECT || http->redirect.status || !Config.accessList.ssl_bump || !http->getConn()->port->sslBump) { http->al->ssl.bumpMode = Ssl::bumpEnd; // SslBump does not apply; log - debugs(85, 5, HERE << "cannot SslBump this request"); @@ -1361,7 +1361,7 @@ { debugs(85, 4, "clientProcessRequest: " << RequestMethodStr(request->method) << " '" << uri << "'"); - if (request->method == METHOD_CONNECT && !redirect.status) { + if (request->method == Http::METHOD_CONNECT && !redirect.status) { #if USE_SSL if (sslBumpNeeded()) { sslBumpStart(); === modified file 'src/errorpage.cc' --- src/errorpage.cc 2012-07-18 16:21:47 +0000 +++ src/errorpage.cc 2012-07-23 06:36:57 +0000 @@ -1158,7 +1158,7 @@ status = httpStatus; else { // Use 307 for HTTP/1.1 non-GET/HEAD requests. - if (request->method != METHOD_GET && request->method != METHOD_HEAD && request->http_ver >= HttpVersion(1,1)) + if (request->method != Http::METHOD_GET && request->method != Http::METHOD_HEAD && request->http_ver >= HttpVersion(1,1)) status = HTTP_TEMPORARY_REDIRECT; } === modified file 'src/esi/Include.cc' --- src/esi/Include.cc 2012-01-20 18:55:04 +0000 +++ src/esi/Include.cc 2012-07-23 09:06:33 +0000 @@ -338,10 +338,9 @@ /* tempUrl is eaten by the request */ char const *tempUrl = vars->extractChar (); - debugs(86, 5, "ESIIncludeStart: Starting subrequest with url '" << tempUrl << - "'"); + debugs(86, 5, "ESIIncludeStart: Starting subrequest with url '" << tempUrl << "'"); - if (clientBeginRequest(METHOD_GET, tempUrl, esiBufferRecipient, esiBufferDetach, stream.getRaw(), &tempheaders, stream->localbuffer->buf, HTTP_REQBUF_SZ)) { + if (clientBeginRequest(Http::METHOD_GET, tempUrl, esiBufferRecipient, esiBufferDetach, stream.getRaw(), &tempheaders, stream->localbuffer->buf, HTTP_REQBUF_SZ)) { debugs(86, 0, "starting new ESI subrequest failed"); } === modified file 'src/forward.cc' --- src/forward.cc 2012-07-23 00:12:14 +0000 +++ src/forward.cc 2012-07-23 06:36:57 +0000 @@ -541,29 +541,8 @@ bool FwdState::checkRetriable() { - /* RFC2616 9.1 Safe and Idempotent Methods */ - switch (request->method.id()) { - /* 9.1.1 Safe Methods */ - - case METHOD_GET: - - case METHOD_HEAD: - /* 9.1.2 Idempotent Methods */ - - case METHOD_PUT: - - case METHOD_DELETE: - - case METHOD_OPTIONS: - - case METHOD_TRACE: - break; - - default: - return false; - } - - return true; + // RFC2616 9.1 Safe and Idempotent Methods + return (request->method.isHttpSafe() || request->method.isIdempotent()); } void === modified file 'src/ftp.cc' --- src/ftp.cc 2012-07-18 16:21:47 +0000 +++ src/ftp.cc 2012-07-23 06:36:57 +0000 @@ -499,7 +499,7 @@ AsyncCall::Pointer closer = JobCallback(9, 5, Dialer, this, FtpStateData::ctrlClosed); ctrl.opened(conn, closer); - if (request->method == METHOD_PUT) + if (request->method == Http::METHOD_PUT) flags.put = 1; } @@ -1326,7 +1326,7 @@ { debugs(9, 3, HERE << "FtpStateData::processReplyBody starting."); - if (request->method == METHOD_HEAD && (flags.isdir || theSize != -1)) { + if (request->method == Http::METHOD_HEAD && (flags.isdir || theSize != -1)) { serverComplete(); return; } @@ -2520,7 +2520,7 @@ /** \par * Checks for 'HEAD' method request and passes off for special handling by FtpStateData::processHeadResponse(). */ - if (ftpState->request->method == METHOD_HEAD && (ftpState->flags.isdir || ftpState->theSize != -1)) { + if (ftpState->request->method == Http::METHOD_HEAD && (ftpState->flags.isdir || ftpState->theSize != -1)) { ftpState->processHeadResponse(); // may call serverComplete return; } === modified file 'src/htcp.cc' --- src/htcp.cc 2012-07-22 03:15:02 +0000 +++ src/htcp.cc 2012-07-23 06:36:57 +0000 @@ -742,7 +742,7 @@ */ method = HttpRequestMethod(s->method, NULL); - s->request = HttpRequest::CreateFromUrlAndMethod(s->uri, method == METHOD_NONE ? HttpRequestMethod(METHOD_GET) : method); + s->request = HttpRequest::CreateFromUrlAndMethod(s->uri, method == Http::METHOD_NONE ? HttpRequestMethod(Http::METHOD_GET) : method); if (s->request) HTTPMSGLOCK(s->request); === added directory 'src/http' === modified file 'src/http.cc' --- src/http.cc 2012-07-22 03:15:02 +0000 +++ src/http.cc 2012-07-23 06:36:57 +0000 @@ -164,19 +164,6 @@ mustStop("HttpStateData::httpStateConnClosed"); } -int -httpCachable(const HttpRequestMethod& method) -{ - /* GET and HEAD are cachable. Others are not. */ - - // TODO: replase to HttpRequestMethod::isCachable() ? - if (method != METHOD_GET && method != METHOD_HEAD) - return 0; - - /* else cachable */ - return 1; -} - void HttpStateData::httpTimeout(const CommTimeoutCbParams ¶ms) { @@ -271,14 +258,14 @@ * changed. */ if (e->mem_obj->request) - pe = storeGetPublicByRequestMethod(e->mem_obj->request, METHOD_HEAD); + pe = storeGetPublicByRequestMethod(e->mem_obj->request, Http::METHOD_HEAD); else - pe = storeGetPublic(e->mem_obj->url, METHOD_HEAD); + pe = storeGetPublic(e->mem_obj->url, Http::METHOD_HEAD); if (pe != NULL) { assert(e != pe); #if USE_HTCP - neighborsHtcpClear(e, NULL, e->mem_obj->request, HttpRequestMethod(METHOD_HEAD), HTCP_CLR_INVALIDATION); + neighborsHtcpClear(e, NULL, e->mem_obj->request, HttpRequestMethod(Http::METHOD_HEAD), HTCP_CLR_INVALIDATION); #endif pe->release(); } @@ -1889,7 +1876,7 @@ case HDR_MAX_FORWARDS: /** \par Max-Forwards: * pass only on TRACE or OPTIONS requests */ - if (request->method == METHOD_TRACE || request->method == METHOD_OPTIONS) { + if (request->method == Http::METHOD_TRACE || request->method == Http::METHOD_OPTIONS) { const int64_t hops = e->getInt64(); if (hops > 0) === added file 'src/http/Makefile.am' --- src/http/Makefile.am 1970-01-01 00:00:00 +0000 +++ src/http/Makefile.am 2012-02-22 05:54:32 +0000 @@ -0,0 +1,14 @@ +include $(top_srcdir)/src/Common.am +include $(top_srcdir)/src/TestHeaders.am + +noinst_LTLIBRARIES = libsquid-http.la + +libsquid_http_la_SOURCES = \ + MethodType.cc \ + MethodType.h + +MethodType.cc: MethodType.h $(top_srcdir)/src/mk-string-arrays.awk + ($(AWK) -f $(top_srcdir)/src/mk-string-arrays.awk < $(srcdir)/MethodType.h | sed -e 's%METHOD_%%' | \ + sed -e 's%_C%-C%' >$@) || ($(RM) -f $@ && exit 1) + +CLEANFILES += MethodType.cc === added file 'src/http/MethodType.h' --- src/http/MethodType.h 1970-01-01 00:00:00 +0000 +++ src/http/MethodType.h 2012-07-03 02:09:07 +0000 @@ -0,0 +1,94 @@ +#ifndef SQUID_SRC_HTTP_METHODTYPE_H +#define SQUID_SRC_HTTP_METHODTYPE_H + +namespace Http +{ + +// see IANA registry: +// also: https://datatracker.ietf.org/doc/draft-ietf-httpbis-method-registrations +typedef enum _method_t { + METHOD_NONE = 0, + +#if NO_SPECIAL_HANDLING + // RFC 2068 + METHOD_LINK, + METHOD_UNLINK, +#endif + + // RFC 2616 (HTTP) + METHOD_GET, + METHOD_POST, + METHOD_PUT, + METHOD_HEAD, + METHOD_CONNECT, + METHOD_TRACE, + METHOD_OPTIONS, + METHOD_DELETE, + + // RFC 3253 + METHOD_CHECKOUT, + METHOD_CHECKIN, + METHOD_UNCHECKOUT, + METHOD_MKWORKSPACE, + METHOD_VERSION_CONTROL, + METHOD_REPORT, + METHOD_UPDATE, + METHOD_LABEL, + METHOD_MERGE, + METHOD_BASELINE_CONTROL, + METHOD_MKACTIVITY, + +#if NO_SPECIAL_HANDLING + // RFC 3648 + METHOD_ORDERPATCH, + + // RFC 3744 + METHOD_ACL, + + // RFC 4437 + METHOD_MKREDIRECTREF, + METHOD_UPDATEREDIRECTREF, + + // RFC 4791 + METHOD_MKCALENDAR, +#endif + + // RFC 4918 (WebDAV) + METHOD_PROPFIND, + METHOD_PROPPATCH, + METHOD_MKCOL, + METHOD_COPY, + METHOD_MOVE, + METHOD_LOCK, + METHOD_UNLOCK, + + // RFC 5323 + METHOD_SEARCH, + +#if NO_SPECIAL_HANDLING + // RFC 5789 + METHOD_PATCH, + + // RFC 5842 + METHOD_BIND, + METHOD_REBIND, + METHOD_UNBIND, +#endif + + // Squid extension methods + METHOD_PURGE, + METHOD_OTHER, + METHOD_ENUM_END // MUST be last, (yuck) this is used as an array-initialization index constant! +} MethodType; + +extern const char *MethodType_str[]; + +inline const char* +MethodStr(const MethodType m) +{ + return MethodType_str[m]; +} + +}; // namespace Http + +#endif /* SQUID_SRC_HTTP_METHODTYPE_H */ === modified file 'src/icmp/net_db.cc' --- src/icmp/net_db.cc 2012-01-20 18:55:04 +0000 +++ src/icmp/net_db.cc 2012-07-23 08:37:51 +0000 @@ -1321,7 +1321,7 @@ assert(NULL != ex->r); ex->r->http_ver = HttpVersion(1,1); ex->connstate = STATE_HEADER; - ex->e = storeCreateEntry(uri, uri, request_flags(), METHOD_GET); + ex->e = storeCreateEntry(uri, uri, request_flags(), Http::METHOD_GET); ex->buf_sz = NETDB_REQBUF_SZ; assert(NULL != ex->e); ex->sc = storeClientListAdd(ex->e, ex); === modified file 'src/icp_v2.cc' --- src/icp_v2.cc 2012-07-17 14:11:24 +0000 +++ src/icp_v2.cc 2012-07-23 06:36:57 +0000 @@ -497,7 +497,7 @@ state->src_rtt = src_rtt; - StoreEntry::getPublic (state, url, METHOD_GET); + StoreEntry::getPublic (state, url, Http::METHOD_GET); HTTPMSGUNLOCK(icp_request); } @@ -840,5 +840,5 @@ if (neighbors_do_private_keys && reqnum) return queried_keys[reqnum & N_QUERIED_KEYS_MASK]; - return storeKeyPublic(url, METHOD_GET); + return storeKeyPublic(url, Http::METHOD_GET); } === modified file 'src/icp_v3.cc' --- src/icp_v3.cc 2012-01-20 18:55:04 +0000 +++ src/icp_v3.cc 2012-02-29 09:18:25 +0000 @@ -80,7 +80,7 @@ state->url = xstrdup (url); - StoreEntry::getPublic (state, url, METHOD_GET); + StoreEntry::getPublic (state, url, Http::METHOD_GET); } ICP3State::~ICP3State() === modified file 'src/mgr/ActionParams.cc' --- src/mgr/ActionParams.cc 2012-01-20 18:55:04 +0000 +++ src/mgr/ActionParams.cc 2012-07-10 11:16:20 +0000 @@ -10,7 +10,7 @@ #include "ipc/TypedMsgHdr.h" #include "mgr/ActionParams.h" -Mgr::ActionParams::ActionParams(): httpMethod(METHOD_NONE) +Mgr::ActionParams::ActionParams(): httpMethod(Http::METHOD_NONE) { } @@ -19,8 +19,10 @@ msg.getString(httpUri); const int m = msg.getInt(); - Must(METHOD_NONE <= m && m < METHOD_ENUM_END); - httpMethod = static_cast<_method_t>(m); + Must(Http::METHOD_NONE <= m && m < Http::METHOD_ENUM_END); + String method; + msg.getString(method); + httpMethod = HttpRequestMethod(method.termedBuf(), NULL); msg.getPod(httpFlags); msg.getString(httpOrigin); @@ -35,7 +37,8 @@ Mgr::ActionParams::pack(Ipc::TypedMsgHdr &msg) const { msg.putString(httpUri); - msg.putInt(httpMethod); + String foo(httpMethod.image()); + msg.putString(foo); msg.putPod(httpFlags); msg.putString(httpOrigin); === modified file 'src/mgr/ActionParams.h' --- src/mgr/ActionParams.h 2011-12-30 03:42:50 +0000 +++ src/mgr/ActionParams.h 2012-07-10 09:08:09 +0000 @@ -11,6 +11,8 @@ #include "HttpRequestMethod.h" #include "ipc/forward.h" #include "mgr/QueryParams.h" +// for request_flags +#include "structs.h" namespace Mgr { @@ -27,7 +29,7 @@ public: /* details of the client HTTP request that caused the action */ String httpUri; ///< HTTP request URI - _method_t httpMethod; ///< HTTP request method + HttpRequestMethod httpMethod; ///< HTTP request method request_flags httpFlags; ///< HTTP request flags String httpOrigin; ///< HTTP Origin: header (if any) === modified file 'src/mime.cc' --- src/mime.cc 2012-01-20 18:55:04 +0000 +++ src/mime.cc 2012-02-29 09:18:25 +0000 @@ -405,7 +405,7 @@ if (type == NULL) fatal("Unknown icon format while reading mime.conf\n"); - StoreEntry::getPublic(this, url, METHOD_GET); + StoreEntry::getPublic(this, url, Http::METHOD_GET); } void @@ -444,10 +444,7 @@ } flags.cachable = 1; - StoreEntry *e = storeCreateEntry(url, - url, - flags, - METHOD_GET); + StoreEntry *e = storeCreateEntry(url,url,flags,Http::METHOD_GET); assert(e != NULL); EBIT_SET(e->flags, ENTRY_SPECIAL); e->setPublicKey(); === modified file 'src/neighbors.cc' --- src/neighbors.cc 2012-04-25 05:29:20 +0000 +++ src/neighbors.cc 2012-05-01 13:31:39 +0000 @@ -168,7 +168,7 @@ // CONNECT requests are proxy requests. Not to be forwarded to origin servers. // Unless the destination port matches, in which case we MAY perform a 'DIRECT' to this peer. - if (p->options.originserver && request->method == METHOD_CONNECT && request->port != p->in_addr.GetPort()) + if (p->options.originserver && request->method == Http::METHOD_CONNECT && request->port != p->in_addr.GetPort()) return false; if (p->peer_domain == NULL && p->access == NULL) @@ -1375,7 +1375,7 @@ snprintf(url, MAX_URL, "http://"); p->in_addr.ToURL(url+7, MAX_URL -8 ); strcat(url, "/"); - fake = storeCreateEntry(url, url, request_flags(), METHOD_GET); + fake = storeCreateEntry(url, url, request_flags(), Http::METHOD_GET); HttpRequest *req = HttpRequest::CreateFromUrl(url); psstate = new ps_state; psstate->request = HTTPMSGLOCK(req); === modified file 'src/store.cc' --- src/store.cc 2012-07-18 16:21:47 +0000 +++ src/store.cc 2012-07-23 06:36:57 +0000 @@ -631,9 +631,9 @@ { StoreEntry *e = storeGetPublicByRequestMethod(req, req->method); - if (e == NULL && req->method == METHOD_HEAD) + if (e == NULL && req->method == Http::METHOD_HEAD) /* We can generate a HEAD reply from a cached GET object */ - e = storeGetPublicByRequestMethod(req, METHOD_GET); + e = storeGetPublicByRequestMethod(req, Http::METHOD_GET); return e; } @@ -677,7 +677,7 @@ mem_obj->id = getKeyCounter(); newkey = storeKeyPrivate(mem_obj->url, mem_obj->method, mem_obj->id); } else { - newkey = storeKeyPrivate("JUNK", METHOD_NONE, getKeyCounter()); + newkey = storeKeyPrivate("JUNK", Http::METHOD_NONE, getKeyCounter()); } assert(hash_lookup(store_table, newkey) == NULL); @@ -972,7 +972,7 @@ { #if CACHE_ALL_METHODS - if (mem_obj->method != METHOD_GET) { + if (mem_obj->method != Http::METHOD_GET) { debugs(20, 2, "StoreEntry::checkCachable: NO: non-GET method"); store_check_cachable_hist.no.non_get++; } else @@ -1377,7 +1377,7 @@ return 1; } - if (mem_obj->method == METHOD_HEAD) { + if (mem_obj->method == Http::METHOD_HEAD) { debugs(20, 5, "storeEntryValidLength: HEAD request: " << getMD5Text()); return 1; } @@ -1962,7 +1962,7 @@ const String reqETags = request.header.getList(HDR_IF_NONE_MATCH); // weak comparison is allowed only for HEAD or full-body GET requests const bool allowWeakMatch = !request.flags.range && - (request.method == METHOD_GET || request.method == METHOD_HEAD); + (request.method == Http::METHOD_GET || request.method == Http::METHOD_HEAD); return hasOneOfEtags(reqETags, allowWeakMatch); } === modified file 'src/store_digest.cc' --- src/store_digest.cc 2012-01-20 18:55:04 +0000 +++ src/store_digest.cc 2012-07-23 09:13:08 +0000 @@ -389,7 +389,7 @@ /* make new store entry */ url = internalLocalUri("/squid-internal-periodic/", StoreDigestFileName); flags.cachable = 1; - e = storeCreateEntry(url, url, flags, METHOD_GET); + e = storeCreateEntry(url, url, flags, Http::METHOD_GET); assert(e); sd_state.rewrite_lock = e; debugs(71, 3, "storeDigestRewrite: url: " << url << " key: " << e->getMD5Text()); === modified file 'src/tests/testHttpRequest.cc' --- src/tests/testHttpRequest.cc 2012-01-20 18:55:04 +0000 +++ src/tests/testHttpRequest.cc 2012-04-21 13:50:29 +0000 @@ -35,11 +35,11 @@ /* vanilla url */ unsigned short expected_port; char * url = xstrdup("http://foo:90/bar"); - HttpRequest *aRequest = HttpRequest::CreateFromUrlAndMethod(url, METHOD_GET); + HttpRequest *aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_GET); expected_port = 90; HttpRequest *nullRequest = NULL; CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port); - CPPUNIT_ASSERT(aRequest->method == METHOD_GET); + CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET); CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->GetHost())); CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest->urlpath); CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, aRequest->protocol); @@ -48,10 +48,10 @@ /* vanilla url, different method */ url = xstrdup("http://foo/bar"); - aRequest = HttpRequest::CreateFromUrlAndMethod(url, METHOD_PUT); + aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_PUT); expected_port = 80; CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port); - CPPUNIT_ASSERT(aRequest->method == METHOD_PUT); + CPPUNIT_ASSERT(aRequest->method == Http::METHOD_PUT); CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->GetHost())); CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest->urlpath); CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, aRequest->protocol); @@ -59,16 +59,16 @@ /* a connect url with non-CONNECT data */ url = xstrdup(":foo/bar"); - aRequest = HttpRequest::CreateFromUrlAndMethod(url, METHOD_CONNECT); + aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_CONNECT); xfree(url); CPPUNIT_ASSERT_EQUAL(nullRequest, aRequest); /* a CONNECT url with CONNECT data */ url = xstrdup("foo:45"); - aRequest = HttpRequest::CreateFromUrlAndMethod(url, METHOD_CONNECT); + aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_CONNECT); expected_port = 45; CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port); - CPPUNIT_ASSERT(aRequest->method == METHOD_CONNECT); + CPPUNIT_ASSERT(aRequest->method == Http::METHOD_CONNECT); CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->GetHost())); CPPUNIT_ASSERT_EQUAL(String(""), aRequest->urlpath); CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_NONE, aRequest->protocol); @@ -88,7 +88,7 @@ HttpRequest *aRequest = HttpRequest::CreateFromUrl(url); expected_port = 90; CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port); - CPPUNIT_ASSERT(aRequest->method == METHOD_GET); + CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET); CPPUNIT_ASSERT_EQUAL(String("foo"), String(aRequest->GetHost())); CPPUNIT_ASSERT_EQUAL(String("/bar"), aRequest->urlpath); CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, aRequest->protocol); @@ -108,10 +108,10 @@ /* valid IPv6 address without port */ url = xstrdup("http://[2000:800::45]/foo"); - aRequest = HttpRequest::CreateFromUrlAndMethod(url, METHOD_GET); + aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_GET); expected_port = 80; CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port); - CPPUNIT_ASSERT(aRequest->method == METHOD_GET); + CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET); CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->GetHost())); CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest->urlpath); CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, aRequest->protocol); @@ -120,10 +120,10 @@ /* valid IPv6 address with port */ url = xstrdup("http://[2000:800::45]:90/foo"); - aRequest = HttpRequest::CreateFromUrlAndMethod(url, METHOD_GET); + aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_GET); expected_port = 90; CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port); - CPPUNIT_ASSERT(aRequest->method == METHOD_GET); + CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET); CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->GetHost())); CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest->urlpath); CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, aRequest->protocol); @@ -132,10 +132,10 @@ /* IPv6 address as invalid (bug trigger) */ url = xstrdup("http://2000:800::45/foo"); - aRequest = HttpRequest::CreateFromUrlAndMethod(url, METHOD_GET); + aRequest = HttpRequest::CreateFromUrlAndMethod(url, Http::METHOD_GET); expected_port = 80; CPPUNIT_ASSERT_EQUAL(expected_port, aRequest->port); - CPPUNIT_ASSERT(aRequest->method == METHOD_GET); + CPPUNIT_ASSERT(aRequest->method == Http::METHOD_GET); CPPUNIT_ASSERT_EQUAL(String("[2000:800::45]"), String(aRequest->GetHost())); CPPUNIT_ASSERT_EQUAL(String("/foo"), aRequest->urlpath); CPPUNIT_ASSERT_EQUAL(AnyP::PROTO_HTTP, aRequest->protocol); === modified file 'src/tests/testHttpRequestMethod.cc' --- src/tests/testHttpRequestMethod.cc 2012-01-20 18:55:04 +0000 +++ src/tests/testHttpRequestMethod.cc 2012-04-22 01:22:31 +0000 @@ -20,11 +20,11 @@ void testHttpRequestMethod::testConstructCharStart() { - /* parse an empty string -> METHOD_NONE */ - CPPUNIT_ASSERT(HttpRequestMethod(NULL,NULL) == METHOD_NONE); + /* parse an empty string -> Http::METHOD_NONE */ + CPPUNIT_ASSERT(HttpRequestMethod(NULL,NULL) == Http::METHOD_NONE); /* parsing a literal should work */ - CPPUNIT_ASSERT(HttpRequestMethod("GET", NULL) == METHOD_GET); - CPPUNIT_ASSERT(HttpRequestMethod("QWERTY", NULL) == METHOD_OTHER); + CPPUNIT_ASSERT(HttpRequestMethod("GET", NULL) == Http::METHOD_GET); + CPPUNIT_ASSERT(HttpRequestMethod("QWERTY", NULL) == Http::METHOD_OTHER); } /* @@ -34,48 +34,48 @@ testHttpRequestMethod::testConstructCharStartEnd() { char const * buffer; - /* parse an empty string -> METHOD_NONE */ - CPPUNIT_ASSERT(HttpRequestMethod(NULL, NULL) == METHOD_NONE); + /* parse an empty string -> Http::METHOD_NONE */ + CPPUNIT_ASSERT(HttpRequestMethod(NULL, NULL) == Http::METHOD_NONE); /* parsing a literal should work */ - CPPUNIT_ASSERT(HttpRequestMethod("GET", NULL) == METHOD_GET); + CPPUNIT_ASSERT(HttpRequestMethod("GET", NULL) == Http::METHOD_GET); /* parsing with an explicit end should work */ buffer = "POSTPLUS"; - CPPUNIT_ASSERT(HttpRequestMethod(buffer, buffer + 4) == METHOD_POST); + CPPUNIT_ASSERT(HttpRequestMethod(buffer, buffer + 4) == Http::METHOD_POST); } /* - * we should be able to assign a method_t to a HttpRequestMethod + * we should be able to assign a Http::MethodType to a HttpRequestMethod */ void testHttpRequestMethod::testAssignFrommethod_t() { HttpRequestMethod method; - method = METHOD_NONE; - CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(METHOD_NONE), method); - method = METHOD_POST; - CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(METHOD_POST), method); + method = Http::METHOD_NONE; + CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_NONE), method); + method = Http::METHOD_POST; + CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_POST), method); } /* - * a default constructed HttpRequestMethod is == METHOD_NONE + * a default constructed HttpRequestMethod is == Http::METHOD_NONE */ void testHttpRequestMethod::testDefaultConstructor() { HttpRequestMethod lhs; - HttpRequestMethod rhs(METHOD_NONE); + HttpRequestMethod rhs(Http::METHOD_NONE); CPPUNIT_ASSERT_EQUAL(lhs, rhs); } /* - * we should be able to construct a HttpRequestMethod from a method_t + * we should be able to construct a HttpRequestMethod from a Http::MethodType */ void testHttpRequestMethod::testConstructmethod_t() { - CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(METHOD_NONE), HttpRequestMethod(METHOD_NONE)); - CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(METHOD_POST), HttpRequestMethod(METHOD_POST)); - CPPUNIT_ASSERT(HttpRequestMethod(METHOD_NONE) != HttpRequestMethod(METHOD_POST)); + CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_NONE), HttpRequestMethod(Http::METHOD_NONE)); + CPPUNIT_ASSERT_EQUAL(HttpRequestMethod(Http::METHOD_POST), HttpRequestMethod(Http::METHOD_POST)); + CPPUNIT_ASSERT(HttpRequestMethod(Http::METHOD_NONE) != HttpRequestMethod(Http::METHOD_POST)); } /* @@ -88,16 +88,16 @@ } /* - * an HttpRequestMethod should be comparable to a method_t without false + * an HttpRequestMethod should be comparable to a Http::MethodType without false * matches */ void testHttpRequestMethod::testEqualmethod_t() { - CPPUNIT_ASSERT(HttpRequestMethod(METHOD_NONE) == METHOD_NONE); - CPPUNIT_ASSERT(not (HttpRequestMethod(METHOD_POST) == METHOD_GET)); - CPPUNIT_ASSERT(HttpRequestMethod(METHOD_GET) == METHOD_GET); - CPPUNIT_ASSERT(not (HttpRequestMethod(METHOD_TRACE) == METHOD_SEARCH)); + CPPUNIT_ASSERT(HttpRequestMethod(Http::METHOD_NONE) == Http::METHOD_NONE); + CPPUNIT_ASSERT(not (HttpRequestMethod(Http::METHOD_POST) == Http::METHOD_GET)); + CPPUNIT_ASSERT(HttpRequestMethod(Http::METHOD_GET) == Http::METHOD_GET); + CPPUNIT_ASSERT(not (HttpRequestMethod(Http::METHOD_TRACE) == Http::METHOD_SEARCH)); } /* @@ -106,10 +106,10 @@ void testHttpRequestMethod::testNotEqualmethod_t() { - CPPUNIT_ASSERT(HttpRequestMethod(METHOD_NONE) != METHOD_GET); - CPPUNIT_ASSERT(not (HttpRequestMethod(METHOD_POST) != METHOD_POST)); - CPPUNIT_ASSERT(HttpRequestMethod(METHOD_GET) != METHOD_NONE); - CPPUNIT_ASSERT(not (HttpRequestMethod(METHOD_SEARCH) != METHOD_SEARCH)); + CPPUNIT_ASSERT(HttpRequestMethod(Http::METHOD_NONE) != Http::METHOD_GET); + CPPUNIT_ASSERT(not (HttpRequestMethod(Http::METHOD_POST) != Http::METHOD_POST)); + CPPUNIT_ASSERT(HttpRequestMethod(Http::METHOD_GET) != Http::METHOD_NONE); + CPPUNIT_ASSERT(not (HttpRequestMethod(Http::METHOD_SEARCH) != Http::METHOD_SEARCH)); } /* === modified file 'src/tests/testRock.cc' --- src/tests/testRock.cc 2012-01-20 18:55:04 +0000 +++ src/tests/testRock.cc 2012-04-22 10:58:56 +0000 @@ -164,7 +164,7 @@ snprintf(url, sizeof(url), "dummy url %i", i); url[sizeof(url) - 1] = '\0'; StoreEntry *const pe = - storeCreateEntry(url, "dummy log url", flags, METHOD_GET); + storeCreateEntry(url, "dummy log url", flags, Http::METHOD_GET); HttpReply *const rep = const_cast(pe->getReply()); rep->setHeaders(HTTP_OK, "dummy test object", "x-squid-internal/test", -1, -1, squid_curtime + 100000); === modified file 'src/tests/testUfs.cc' --- src/tests/testUfs.cc 2012-01-20 18:55:04 +0000 +++ src/tests/testUfs.cc 2012-04-23 05:42:28 +0000 @@ -140,7 +140,7 @@ /* Create "vary" base object */ request_flags flags; flags.cachable = 1; - StoreEntry *pe = storeCreateEntry("dummy url", "dummy log url", flags, METHOD_GET); + StoreEntry *pe = storeCreateEntry("dummy url", "dummy log url", flags, Http::METHOD_GET); HttpReply *rep = (HttpReply *) pe->getReply(); // bypass const rep->setHeaders(HTTP_OK, "dummy test object", "x-squid-internal/test", -1, -1, squid_curtime + 100000); === modified file 'src/url.cc' --- src/url.cc 2012-07-18 15:19:04 +0000 +++ src/url.cc 2012-05-30 11:06:55 +0000 @@ -200,7 +200,7 @@ * This abuses HttpRequest as a way of representing the parsed url * and its components. * method is used to switch parsers and to init the HttpRequest. - * If method is METHOD_CONNECT, then rather than a URL a hostname:port is + * If method is Http::METHOD_CONNECT, then rather than a URL a hostname:port is * looked for. * The url is non const so that if its too long we can NULL-terminate it in place. */ @@ -235,14 +235,14 @@ debugs(23, 1, "urlParse: URL too large (" << l << " bytes)"); return NULL; } - if (method == METHOD_CONNECT) { + if (method == Http::METHOD_CONNECT) { port = CONNECT_PORT; if (sscanf(url, "[%[^]]]:%d", host, &port) < 1) if (sscanf(url, "%[^:]:%d", host, &port) < 1) return NULL; - } else if ((method == METHOD_OPTIONS || method == METHOD_TRACE) && + } else if ((method == Http::METHOD_OPTIONS || method == Http::METHOD_TRACE) && strcmp(url, "*") == 0) { protocol = AnyP::PROTO_HTTP; port = urlDefaultPort(protocol); @@ -488,7 +488,6 @@ urlCanonical(HttpRequest * request) { LOCAL_ARRAY(char, portbuf, 32); -/// \todo AYJ: Performance: making this a ptr and allocating when needed will be better than a write and future xstrdup(). LOCAL_ARRAY(char, urlbuf, MAX_URL); if (request->canonical) @@ -497,31 +496,22 @@ if (request->protocol == AnyP::PROTO_URN) { snprintf(urlbuf, MAX_URL, "urn:" SQUIDSTRINGPH, SQUIDSTRINGPRINT(request->urlpath)); + } else if (request->method.id() == Http::METHOD_CONNECT) { + snprintf(urlbuf, MAX_URL, "%s:%d", request->GetHost(), request->port); } else { -/// \todo AYJ: this could use "if..else and method == METHOD_CONNECT" easier. - switch (request->method.id()) { - - case METHOD_CONNECT: - snprintf(urlbuf, MAX_URL, "%s:%d", request->GetHost(), request->port); - break; - - default: - portbuf[0] = '\0'; - - if (request->port != urlDefaultPort(request->protocol)) - snprintf(portbuf, 32, ":%d", request->port); - - const URLScheme sch = request->protocol; // temporary, until bug 1961 URL handling is fixed. - snprintf(urlbuf, MAX_URL, "%s://%s%s%s%s" SQUIDSTRINGPH, - sch.const_str(), - request->login, - *request->login ? "@" : null_string, - request->GetHost(), - portbuf, - SQUIDSTRINGPRINT(request->urlpath)); - - break; - } + portbuf[0] = '\0'; + + if (request->port != urlDefaultPort(request->protocol)) + snprintf(portbuf, 32, ":%d", request->port); + + const URLScheme sch = request->protocol; // temporary, until bug 1961 URL handling is fixed. + snprintf(urlbuf, MAX_URL, "%s://%s%s%s%s" SQUIDSTRINGPH, + sch.const_str(), + request->login, + *request->login ? "@" : null_string, + request->GetHost(), + portbuf, + SQUIDSTRINGPRINT(request->urlpath)); } return (request->canonical = xstrdup(urlbuf)); @@ -542,50 +532,39 @@ if (request->protocol == AnyP::PROTO_URN) { snprintf(buf, MAX_URL, "urn:" SQUIDSTRINGPH, SQUIDSTRINGPRINT(request->urlpath)); + } else if (request->method.id() == Http::METHOD_CONNECT) { + snprintf(buf, MAX_URL, "%s:%d", request->GetHost(), request->port); } else { -/// \todo AYJ: this could use "if..else and method == METHOD_CONNECT" easier. - switch (request->method.id()) { - - case METHOD_CONNECT: - snprintf(buf, MAX_URL, "%s:%d", - request->GetHost(), - request->port); - break; - - default: - portbuf[0] = '\0'; - - if (request->port != urlDefaultPort(request->protocol)) - snprintf(portbuf, 32, ":%d", request->port); - - loginbuf[0] = '\0'; - - if ((int) strlen(request->login) > 0) { - strcpy(loginbuf, request->login); - - if ((t = strchr(loginbuf, ':'))) - *t = '\0'; - - strcat(loginbuf, "@"); - } - - const URLScheme sch = request->protocol; // temporary, until bug 1961 URL handling is fixed. - snprintf(buf, MAX_URL, "%s://%s%s%s" SQUIDSTRINGPH, - sch.const_str(), - loginbuf, - request->GetHost(), - portbuf, - SQUIDSTRINGPRINT(request->urlpath)); - /* - * strip arguments AFTER a question-mark - */ - - if (Config.onoff.strip_query_terms) - if ((t = strchr(buf, '?'))) - *(++t) = '\0'; - - break; + portbuf[0] = '\0'; + + if (request->port != urlDefaultPort(request->protocol)) + snprintf(portbuf, 32, ":%d", request->port); + + loginbuf[0] = '\0'; + + if ((int) strlen(request->login) > 0) { + strcpy(loginbuf, request->login); + + if ((t = strchr(loginbuf, ':'))) + *t = '\0'; + + strcat(loginbuf, "@"); } + + const URLScheme sch = request->protocol; // temporary, until bug 1961 URL handling is fixed. + snprintf(buf, MAX_URL, "%s://%s%s%s" SQUIDSTRINGPH, + sch.const_str(), + loginbuf, + request->GetHost(), + portbuf, + SQUIDSTRINGPRINT(request->urlpath)); + /* + * strip arguments AFTER a question-mark + */ + + if (Config.onoff.strip_query_terms) + if ((t = strchr(buf, '?'))) + *(++t) = '\0'; } if (stringHasCntl(buf)) @@ -596,7 +575,7 @@ /** * Yet another alternative to urlCanonical. - * This one addes the https:// parts to METHOD_CONNECT URL + * This one adds the https:// parts to Http::METHOD_CONNECT URL * for use in error page outputs. * Luckily we can leverage the others instead of duplicating. */ @@ -606,7 +585,7 @@ LOCAL_ARRAY(char, buf, MAX_URL); // method CONNECT and port HTTPS - if (request->method == METHOD_CONNECT && request->port == 443) { + if (request->method == Http::METHOD_CONNECT && request->port == 443) { snprintf(buf, MAX_URL, "https://%s/*", request->GetHost()); return buf; } @@ -659,7 +638,7 @@ urlMakeAbsolute(const HttpRequest * req, const char *relUrl) { - if (req->method.id() == METHOD_CONNECT) { + if (req->method.id() == Http::METHOD_CONNECT) { return (NULL); } @@ -830,15 +809,15 @@ * do not have a default protocol from the client side of HTTP. */ - if (r->method == METHOD_CONNECT) + if (r->method == Http::METHOD_CONNECT) return 1; // we support OPTIONS and TRACE directed at us (with a 501 reply, for now) // we also support forwarding OPTIONS and TRACE, except for the *-URI ones - if (r->method == METHOD_OPTIONS || r->method == METHOD_TRACE) + if (r->method == Http::METHOD_OPTIONS || r->method == Http::METHOD_TRACE) return (r->header.getInt64(HDR_MAX_FORWARDS) == 0 || r->urlpath != "*"); - if (r->method == METHOD_PURGE) + if (r->method == Http::METHOD_PURGE) return 1; /* does method match the protocol? */ @@ -854,7 +833,7 @@ case AnyP::PROTO_FTP: - if (r->method == METHOD_PUT) + if (r->method == Http::METHOD_PUT) rc = 1; case AnyP::PROTO_GOPHER: @@ -862,9 +841,9 @@ case AnyP::PROTO_WAIS: case AnyP::PROTO_WHOIS: - if (r->method == METHOD_GET) + if (r->method == Http::METHOD_GET) rc = 1; - else if (r->method == METHOD_HEAD) + else if (r->method == Http::METHOD_HEAD) rc = 1; break; === modified file 'src/urn.cc' --- src/urn.cc 2012-01-20 18:55:04 +0000 +++ src/urn.cc 2012-03-02 02:03:51 +0000 @@ -245,7 +245,7 @@ if (urlres_r == NULL) return; - StoreEntry::getPublic (this, urlres, METHOD_GET); + StoreEntry::getPublic (this, urlres, Http::METHOD_GET); } void @@ -254,7 +254,7 @@ urlres_e = newEntry; if (urlres_e->isNull()) { - urlres_e = storeCreateEntry(urlres, urlres, request_flags(), METHOD_GET); + urlres_e = storeCreateEntry(urlres, urlres, request_flags(), Http::METHOD_GET); sc = storeClientListAdd(urlres_e, this); FwdState::fwdStart(Comm::ConnectionPointer(), urlres_e, urlres_r); } else {