2006-09-21
2006-09-21 14:56:04 by Henrik Grubbström (Grubba) <grubba@grubba.org>
-
45119892ddc9b9470df4acbfa041d7fa909b3a8c
(237 lines)
(+100/-137)
[
Show
| Annotate
]
Branch: 5.2
Now caches more in the protocol cache.
Rev: server/protocols/http.pike:1.507
2:
// Modified by Francesco Chemolli to add throttling capabilities.
// Copyright © 1996 - 2004, Roxen IS.
- constant cvs_version = "$Id: http.pike,v 1.506 2006/09/21 14:44:42 wellhard Exp $";
+ constant cvs_version = "$Id: http.pike,v 1.507 2006/09/21 14:56:04 grubba Exp $";
// #define REQUEST_DEBUG
#define MAGIC_ERROR
1950:
m_delete(heads, "Connection");
m_delete(heads, "Expires");
- if (file->error == 200) {
- // FIXME: This code probably ought to move to after the store
- // to the RAM cache.
- // /grubba 2005-12-20
- int conditional;
- if (none_match) {
- // NOTE: misc->etag may be zero below, but that's ok.
- if (none_match[misc->etag] || (misc->etag && none_match["*"])) {
- // We have a if-none-match header that matches our etag.
- if ((<"HEAD", "GET">)[method]) {
- // RFC 2616 14.26:
- // Instead, if the request method was GET or HEAD, the server
- // SHOULD respond with a 304 (Not Modified) response, including
- // the cache- related header fields (particularly ETag) of one
- // of the entities that matched. For all other request methods,
- // the server MUST respond with a status of 412 (Precondition
- // Failed).
- conditional = 304;
- } else {
- conditional = 412;
- }
- } else {
- conditional = -1;
- }
- }
- if(since && misc->last_modified && (conditional >= 0))
- {
- /* ({ time, len }) */
- array(int) since_info = Roxen.parse_since( since );
- // werror("since: %{%O, %}\n"
- // "lm: %O\n"
- // "cacheable: %O\n",
- // since_info,
- // misc->last_modified,
- // misc->cacheable);
- if ( ((since_info[0] >= misc->last_modified) &&
- ((since_info[1] == -1) || (since_info[1] == file->len)))
- // never say 'not modified' if cacheable has been lowered.
- && (zero_type(misc->cacheable) ||
- (misc->cacheable >= INITIAL_CACHEABLE))
- // actually ok, or...
- // || ((misc->cacheable>0)
- // && (since_info[0] + misc->cacheable<= predef::time(1))
- // // cacheable, and not enough time has passed.
- )
- {
- conditional = conditional || 304;
- } else {
- conditional = -1;
- }
- }
- if (conditional > 0) {
- // All conditionals apply.
- file->error = conditional;
- file->file = file->data = file->len = 0;
- NO_PROTO_CACHE();
- }
- }
-
+
// FIXME: prot.
head_string = sprintf(" %s\r\n",
head_status || errors[file->error] || "");
- // Must update the content length after the modifications of the
- // data to send that might have been done above for 206 or 304.
- variant_heads["Content-Length"] = (string)file->len;
-
- // Some browsers, e.g. Netscape 4.7, don't trust a zero
- // content length when using keep-alive. So let's force a
- // close in that case.
- if( file->error/100 == 2 && file->len <= 0 )
- {
- variant_heads->Connection = "close";
- misc->connection = "close";
- }
-
- #if 0
- // Check for wide or 8-bit headers.
- // FIXME: Assumes no header names are wide.
- //
- // This is disabled since it doesn't work for all headers. It
- // therefore has to be the responsibility of whatever code makes
- // the header to ensure it's correctly encoded. /mast
- foreach(heads; string header_name; string content) {
- string encoded;
- if (content != (encoded = string_to_utf8(content))) {
- array(array(string)|int) tokenized =
- MIME.decode_words_tokenized(encoded);
- foreach(tokenized, array(string)|int token) {
- if (arrayp(token)) {
- string raw = utf8_to_string(token[0]);
- if (raw == token[0]) {
- if (token[1]) {
- // Should not happen in normal circumstances.
- catch {
- // Attempt to recode in UTF-8.
- token[0] = string_to_utf8(Locale.Charset.
- decoder(token[1])->
- feed(raw)->drain());
- };
- }
- token[1] = "utf-8";
- }
- }
- }
- string q = MIME.encode_words_quoted(tokenized, "q");
- string b = MIME.encode_words_quoted(tokenized, "b");
- // Prefer QP to BASE-64 if they are the same length.
- heads[header_name] = (sizeof(b)<sizeof(q))?b:q;
- }
- }
- #endif
-
+
if (mixed err = catch(head_string += Roxen.make_http_headers(heads, 1)))
{
#ifdef DEBUG
2093:
}
int varies = misc->vary && (sizeof(misc->vary) - misc->vary["Host"]);
- if( (method == "HEAD") || (file->error == 204) || (file->error == 304) ||
- (file->error < 200))
- {
- // RFC 2068 4.4.1
- // Any response message which MUST NOT include a message-body
- // (such as the 1xx, 204, and 304 responses and any response
- // to a HEAD request) is always terminated by the first empty
- // line after the header fields, regardless of the entity-header
- // fields present in the message.
-
- file->len = 1; // Keep those alive, please...
- file->data = "";
- file->file = 0;
- if (varies && (prot == "HTTP/1.0")) {
- // The Vary header is new in HTTP/1.1.
- // It expired a year ago.
- variant_heads["Expires"] =
- Roxen->http_date(predef::time(1)-31557600);
- }
- } else {
+
#ifdef RAM_CACHE
if( (misc->cacheable > 0) && !misc->no_proto_cache)
{
-
+ if ((<"HEAD","GET">)[method]) {
if( file->len>0 && // known length.
((file->len + sizeof(head_string)) <
conf->datacache->max_file_size)
2157: Inside #if defined(RAM_CACHE)
cache_status["protstore"] = 1;
}
}
+ }
#endif
-
+
+ // Some browsers, e.g. Netscape 4.7, don't trust a zero
+ // content length when using keep-alive. So let's force a
+ // close in that case.
+ if( file->error/100 == 2 && file->len <= 0 )
+ {
+ variant_heads->Connection = "close";
+ misc->connection = "close";
+ }
+
+ if (file->error == 200) {
+ int conditional;
+ if (none_match) {
+ // NOTE: misc->etag may be zero below, but that's ok.
+ if (none_match[misc->etag] || (misc->etag && none_match["*"])) {
+ // We have a if-none-match header that matches our etag.
+ if ((<"HEAD", "GET">)[method]) {
+ // RFC 2616 14.26:
+ // Instead, if the request method was GET or HEAD, the server
+ // SHOULD respond with a 304 (Not Modified) response, including
+ // the cache- related header fields (particularly ETag) of one
+ // of the entities that matched. For all other request methods,
+ // the server MUST respond with a status of 412 (Precondition
+ // Failed).
+ conditional = 304;
+ } else {
+ conditional = 412;
+ }
+ } else {
+ conditional = -1;
+ }
+ }
+ if(since && misc->last_modified && (conditional >= 0))
+ {
+ /* ({ time, len }) */
+ array(int) since_info = Roxen.parse_since( since );
+ // werror("since: %{%O, %}\n"
+ // "lm: %O\n"
+ // "cacheable: %O\n",
+ // since_info,
+ // misc->last_modified,
+ // misc->cacheable);
+ if ( ((since_info[0] >= misc->last_modified) &&
+ ((since_info[1] == -1) || (since_info[1] == file->len)))
+ // never say 'not modified' if cacheable has been lowered.
+ && (zero_type(misc->cacheable) ||
+ (misc->cacheable >= INITIAL_CACHEABLE))
+ // actually ok, or...
+ // || ((misc->cacheable>0)
+ // && (since_info[0] + misc->cacheable<= predef::time(1))
+ // // cacheable, and not enough time has passed.
+ )
+ {
+ conditional = conditional || 304;
+ } else {
+ conditional = -1;
+ }
+ }
+ if (conditional > 0) {
+ // All conditionals apply.
+ file->error = conditional;
+ file->file = file->data = file->len = 0;
+ // Must update the content length after the modifications of the
+ // data to send that might have been done above for 206 or 304.
+ variant_heads["Content-Length"] = "0";
+ }
+ }
+
if (varies && (prot == "HTTP/1.0")) {
// The Vary header is new in HTTP/1.1.
// It expired a year ago.
- variant_heads["Expires"] =
- Roxen->http_date(predef::time(1)-31557600);
+ variant_heads["Expires"] = Roxen->http_date(predef::time(1)-31557600);
}
-
+ if( (method == "HEAD") || (file->error == 204) || (file->error == 304) ||
+ (file->error < 200))
+ {
+ // RFC 2068 4.4.1
+ // Any response message which MUST NOT include a message-body
+ // (such as the 1xx, 204, and 304 responses and any response
+ // to a HEAD request) is always terminated by the first empty
+ // line after the header fields, regardless of the entity-header
+ // fields present in the message.
+
+ file->len = 1; // Keep those alive, please...
+ file->data = "";
+ file->file = 0;
+ } else {
if (misc->range) {
// Handle byte ranges.
int skip;
2608: Inside #if defined(RAM_CACHE)
file->expires)) {
variant_heads["Expires"] = expires;
}
+ // Some browsers, e.g. Netscape 4.7, don't trust a zero
+ // content length when using keep-alive. So let's force a
+ // close in that case.
+ if( file->error/100 == 2 && file->len <= 0 )
+ {
+ variant_heads->Connection = "close";
+ misc->connection = "close";
+ }
if (misc->range) {
// Handle byte ranges.
int skip;