Branch: Tag:

2005-10-28

2005-10-28 11:58:55 by Henrik Grubbström (Grubba) <grubba@grubba.org>

Ported fix for [bug 4040 (#4040)] from Roxen 4.0.

Rev: server/protocols/http.pike:1.476

2:   // Modified by Francesco Chemolli to add throttling capabilities.   // Copyright © 1996 - 2004, Roxen IS.    - constant cvs_version = "$Id: http.pike,v 1.475 2005/10/10 14:37:10 jonasw Exp $"; + constant cvs_version = "$Id: http.pike,v 1.476 2005/10/28 11:58:55 grubba Exp $";   // #define REQUEST_DEBUG   #define MAGIC_ERROR   
1511:    foreach(indices(heads), string h)    {    if(lower_case(h) == "content-type") { -  type = heads[h]; +  array(string)|string t = heads[h];    m_delete(heads, h); -  +  if (arrayp(t)) type = t[-1]; +  else type = t;    }    }    if(id->request_headers["request-range"])
1665:       array err;    int tmp; -  string head_string=""; +     if (result)    file = result;   #ifdef PROFILE
1725:    if(file->type == "raw") file->raw = 1;    }    +  // Invariant part of header. (Cached) +  // Contains the result line except for the protocol part. +  // Note: Only a single CRLF as terminator. +  string head_string=""; +  +  // Variant part of header. +  // Currently the Date and Connection headers. +  // Note: Terminated with a double CRLF. +  string variant_string=""; +  +  // The full header block (prot + head_string + variant_string). +  string full_headers=""; +     if(!file->raw && (prot != "HTTP/0.9"))    {    if (!sizeof (file) && multi_status)
1760:       mapping(string:string) heads = make_response_headers (file);    +  mapping(string:string) variant_heads = ([ "Date":"", +  "Connection":"" ]) & heads; +  m_delete(heads, "Date"); +  m_delete(heads, "Connection"); +     if (file->error == 200) {    int conditional;    if (none_match) {
1860:    }    }    -  head_string = sprintf("%s %d %s\r\n", prot, file->error, +  // FIXME: prot. +  head_string = sprintf(" %d %s\r\n", file->error,    head_status || errors[file->error] || "");       // Must update the content length after the modifications of the
1872:    // close in that case.    if( file->error/100 == 2 && file->len <= 0 )    { -  heads->Connection = "close"; +  variant_heads->Connection = "close";    misc->connection = "close";    }   
1913:    }   #endif    -  if( mixed err = catch( head_string += Roxen.make_http_headers( heads ) ) ) +  if (mixed err = catch(head_string += Roxen.make_http_headers(heads, 1)))    {   #ifdef DEBUG    report_debug ("Roxen.make_http_headers failed: " +
1936:    }    head_string += "\r\n";    } -  conf->hsent += strlen(head_string); +  +  variant_string = Roxen.make_http_headers(variant_heads); +  full_headers = prot + head_string + variant_string; +  conf->hsent += strlen(full_headers);    }    else    if(!file->type) file->type="text/plain";
1955: Inside #if defined(RAM_CACHE)
   (prot != "HTTP/0.9") && !misc->no_proto_cache)    {    if( file->len>0 && // known length. -  ((file->len + strlen( head_string )) < +  ((file->len + sizeof(head_string)) <    conf->datacache->max_file_size)    // vvv Relying on the interpreter lock from here.    && misc->cachekey )
1969: Inside #if defined(RAM_CACHE)
   MY_TRACE_LEAVE ("");    conf->datacache->set( raw_url, data,    ([ -  // We have to handle the date header. +     "hs":head_string,    "key":misc->cachekey,    "etag":misc->etag,
1988:   #endif    if(!kept_alive &&    (file->len > 0) && -  ((sizeof(head_string) + file->len) < (HTTP_BLOCKING_SIZE_THRESHOLD))) +  ((sizeof(full_headers) + file->len) < (HTTP_BLOCKING_SIZE_THRESHOLD)))    {    // The first time we get a request, the output buffers will    // be empty. We can thus just do a single blocking write()
1996:    int s;    TIMER_END(send_result);    TIMER_START(blocking_write); -  string data = head_string; +  string data = full_headers;    if (file->data)    data += file->data[..file->len-1];    if (file->file)
2015:    do_log( s );    return;    } -  if(strlen(head_string)) send(head_string); +  if(strlen(full_headers)) send(full_headers);    if(file->data && strlen(file->data)) send(file->data, file->len);    if(file->file) send(file->file, file->len);    }    else    {    if( !kept_alive && -  (strlen(head_string) < (HTTP_BLOCKING_SIZE_THRESHOLD))) +  (strlen(full_headers) < (HTTP_BLOCKING_SIZE_THRESHOLD)))    {   #ifdef CONNECTION_DEBUG    werror ("HTTP: Response =================================================\n"    "%s\n", -  replace (sprintf ("%O", head_string), +  replace (sprintf ("%O", full_headers),    ({"\\r\\n", "\\n", "\\t"}),    ({"\n", "\n", "\t"})));   #else -  REQUEST_WERR (sprintf ("HTTP: Send headers blocking %O", head_string)); +  REQUEST_WERR (sprintf ("HTTP: Send headers blocking %O", +  full_headers));   #endif -  do_log( my_fd->write( head_string ) ); +  do_log( my_fd->write( full_headers ) );    return;    } -  send(head_string); +  send(full_headers);    file->len = 1; // Keep those alive, please...    }   
2398: Inside #if defined(RAM_CACHE)
   ((st = file_stat( file->rf )) && st->mtime == file->mtime ))   #endif    { -  string fix_date( string headers ) -  { -  string a, b; -  if( sscanf( headers, "%sDate: %*s\n%s", a, b ) == 3 ) -  return a+"Date: "+Roxen.http_date( predef::time(1) ) +"\r\n"+b; -  return headers; -  }; +  string full_headers = prot + file->hs + +  Roxen.make_http_headers(([ +  "Date":Roxen.http_date(predef::time(1)), +  "Connection":misc->connection || +  ([ "HTTP/1.1":"keep-alive" ])[prot] || "close", +  ]));       MY_TRACE_LEAVE ("Using entry from ram cache"); -  conf->hsent += strlen(file->hs); +  conf->hsent += strlen(full_headers);    cache_status["protcache"] = 1; -  if( strlen( d ) < (HTTP_BLOCKING_SIZE_THRESHOLD) ) +  if( (sizeof(full_headers) + strlen(d)) < +  (HTTP_BLOCKING_SIZE_THRESHOLD) )    {    TIMER_END(cache_lookup); -  do_log( my_fd->write( fix_date(file->hs)+d ) ); +  do_log( my_fd->write( ({ full_headers, d }) ));    }    else    {    TIMER_END(cache_lookup); -  send( fix_date(file->hs)+d ); +  send( full_headers ); +  send( d );    start_sender( );    }    return;