diff --git a/panda/src/downloader/documentSpec.I b/panda/src/downloader/documentSpec.I index 4b64d6ccef..bfb5770b90 100644 --- a/panda/src/downloader/documentSpec.I +++ b/panda/src/downloader/documentSpec.I @@ -25,6 +25,7 @@ INLINE DocumentSpec:: DocumentSpec() { _request_mode = RM_any; + _cache_control = CC_allow_cache; _flags = 0; } @@ -38,6 +39,7 @@ DocumentSpec(const string &url) : _url(url) { _request_mode = RM_any; + _cache_control = CC_allow_cache; _flags = 0; } @@ -51,6 +53,7 @@ DocumentSpec(const URLSpec &url) : _url(url) { _request_mode = RM_any; + _cache_control = CC_allow_cache; _flags = 0; } @@ -65,6 +68,7 @@ DocumentSpec(const DocumentSpec ©) : _tag(copy._tag), _date(copy._date), _request_mode(copy._request_mode), + _cache_control(copy._cache_control), _flags(copy._flags) { } @@ -80,6 +84,7 @@ operator = (const DocumentSpec ©) { _tag = copy._tag; _date = copy._date; _request_mode = copy._request_mode; + _cache_control = copy._cache_control; _flags = copy._flags; } @@ -290,6 +295,44 @@ get_request_mode() const { return _request_mode; } +//////////////////////////////////////////////////////////////////// +// Function: DocumentSpec::set_cache_control +// Access: Published +// Description: Specifies what kind of cached value is acceptable for +// this document. Warning: some HTTP proxies may not +// respect this setting and may return a cached result +// anyway. +// +// CC_allow_cache: the normal HTTP behavior; the +// server may return a cached value if it believes it +// is valid. +// +// CC_revalidate: a proxy is forced to contact the +// origin server and verify that is cached value is in +// fact still valid before it returns it. +// +// CC_no_cache: a proxy must not return its cached +// value at all, but is forced to go all the way back +// to the origin server for the official document. +// +// The default mode is CC_allow_cache. +//////////////////////////////////////////////////////////////////// +INLINE void DocumentSpec:: +set_cache_control(DocumentSpec::CacheControl cache_control) { + _cache_control = cache_control; +} + +//////////////////////////////////////////////////////////////////// +// Function: DocumentSpec::get_cache_control +// Access: Published +// Description: Returns the request mode of this DocumentSpec. See +// set_cache_control(). +//////////////////////////////////////////////////////////////////// +INLINE DocumentSpec::CacheControl DocumentSpec:: +get_cache_control() const { + return _cache_control; +} + INLINE istream & operator >> (istream &in, DocumentSpec &doc) { if (!doc.input(in)) { diff --git a/panda/src/downloader/documentSpec.h b/panda/src/downloader/documentSpec.h index 06884a3824..53e586a36b 100644 --- a/panda/src/downloader/documentSpec.h +++ b/panda/src/downloader/documentSpec.h @@ -70,6 +70,15 @@ PUBLISHED: INLINE void set_request_mode(RequestMode request_mode); INLINE RequestMode get_request_mode() const; + enum CacheControl { + CC_allow_cache, + CC_revalidate, + CC_no_cache, + }; + + INLINE void set_cache_control(CacheControl cache_control); + INLINE CacheControl get_cache_control() const; + bool input(istream &in); void output(ostream &out) const; void write(ostream &out, int indent_level = 0) const; @@ -79,6 +88,7 @@ private: HTTPEntityTag _tag; HTTPDate _date; RequestMode _request_mode; + CacheControl _cache_control; enum Flags { F_has_tag = 0x0001, diff --git a/panda/src/downloader/httpChannel.cxx b/panda/src/downloader/httpChannel.cxx index fc09f84f7e..69e997346d 100644 --- a/panda/src/downloader/httpChannel.cxx +++ b/panda/src/downloader/httpChannel.cxx @@ -813,6 +813,8 @@ run_proxy_reading_header() { } _redirect = get_header_value("Location"); + // We can take the proxy's word for it that this is the actual URL + // for the redirect. _server_response_has_no_body = (get_status_code() / 100 == 1 || @@ -1164,6 +1166,13 @@ run_reading_header() { } _redirect = get_header_value("Location"); + // The server might have given us just a filename for the redirect. + // In that case, it's relative to the same server. + if (!_redirect.has_authority()) { + _redirect.set_scheme(_document_spec.get_url().get_scheme()); + _redirect.set_authority(_document_spec.get_url().get_authority()); + } + _state = S_read_header; if (_server_response_has_no_body && will_close_connection()) { @@ -1230,7 +1239,7 @@ run_reading_header() { new_url.set_username(_request.get_url().get_username()); } reset_url(_request.get_url(), new_url); - _document_spec.set_url(new_url); + _request.set_url(new_url); make_header(); make_request_text(); @@ -2379,6 +2388,25 @@ make_header() { break; } + switch (_request.get_cache_control()) { + case DocumentSpec::CC_allow_cache: + // Normal, caching behavior. + break; + + case DocumentSpec::CC_revalidate: + // Request the server to revalidate its cache before returning it. + stream + << "Cache-Control: max-age=0\r\n"; + break; + + case DocumentSpec::CC_no_cache: + // Request the server to get a fresh copy regardless of its cache. + stream + << "Cache-Control: no-cache\r\n" + << "Pragma: no-cache\r\n"; + break; + } + if (!_body.empty()) { stream << "Content-Type: application/x-www-form-urlencoded\r\n"