Branch: Tag:

2006-09-21

2006-09-21 14:56:04 by Henrik Grubbström (Grubba) <grubba@grubba.org>

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;