2004-04-13
2004-04-13 16:02:37 by Henrik Grubbström (Grubba) <grubba@grubba.org>
-
29abe62ecc66427cd7aa579bf4a36a8ff9ee4910
(105 lines)
(+67/-38)
[
Show
| Annotate
]
Branch: 5.2
Added some support for the If-None-Match header.
Moved around some code from the HTTP/0.9 case.
Rev: server/protocols/http.pike:1.426
2:
// Modified by Francesco Chemolli to add throttling capabilities.
// Copyright © 1996 - 2001, Roxen IS.
- constant cvs_version = "$Id: http.pike,v 1.425 2004/04/13 09:54:06 grubba Exp $";
+ constant cvs_version = "$Id: http.pike,v 1.426 2004/04/13 16:02:37 grubba Exp $";
// #define REQUEST_DEBUG
#define MAGIC_ERROR
61:
private static int wanted_data, have_data;
private static object(String.Buffer) data_buffer;
+ private static multiset(string) none_match;
+
int kept_alive;
#ifdef DEBUG
693:
case "authorization": rawauth = contents; break;
case "referer": referer = ({contents}); break;
case "if-modified-since": since=contents; break;
+ case "if-match": break; // Not supported yet.
+ case "if-none-match":
+ none_match = (multiset)((contents-" ")/",");
+ break;
case "proxy-authorization":
array y;
1566:
else if(!file->type) file->type="text/plain";
}
- if(!file->raw)
+ if(!file->raw && (prot != "HTTP/0.9"))
{
-
+ // Generate the headers.
heads = ([]);
-
+
if (!file->stat) file->stat = misc->stat;
if(objectp(file->file)) {
if(!file->stat)
1612:
// misc->last_modified,
// misc->cacheable);
- if(since && (!file->error || file->error == 200) && misc->last_modified)
+ #ifdef RAM_CACHE
+ if (!(misc->etag = heads->ETag) && file->len &&
+ (file->data || file->file) &&
+ (file->len < conf->datacache->max_file_size)) {
+ string data = "";
+ if (file->file) {
+ data = file->file->read(file->len);
+ if (file->data && (sizeof(data) < file->len)) {
+ data += file->data[..file->len - (sizeof(data)+1)];
+ }
+ m_delete(file, file);
+ } else if (file->data) {
+ data = file->data[..file->len - 1];
+ }
+ file->data = data;
+ heads->ETag = misc->etag =
+ Crypto.string_to_hex(Crypto.md5()->update(data)->digest());
+ heads->Vary = "ETag";
+ }
+ #endif /* RAM_CACHE */
+
+ if (!file->error || file->error == 200) {
+ if (none_match && misc->etag &&
+ (none_match[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).
+ file->error = 304;
+ } else {
+ file->error = 412;
+ }
+ file->file = file->data = 0;
+ } else if(since && misc->last_modified)
{
/* ({ time, len }) */
array(int) since_info = Roxen.parse_since( since );
1634:
)
{
file->error = 304;
- file->file = file->data = file->type = 0;
+ file->file = file->data = 0;
}
}
-
+ }
- if(prot != "HTTP/0.9")
+
{
string h, charset="";
1764:
heads->Connection = "close";
misc->connection = "close";
}
- #ifdef RAM_CACHE
- if (!(misc->etag = heads->eTag) && file->len &&
- (file->data || file->file) &&
- (file->len < conf->datacache->max_file_size)) {
- string data = "";
- if (file->file) {
- data = file->file->read(file->len);
- if (file->data && (sizeof(data) < file->len)) {
- data += file->data[..file->len - (sizeof(data)+1)];
- }
- m_delete(file, file);
- } else if (file->data) {
- data = file->data[..file->len - 1];
- }
- file->data = data;
- heads->eTag = misc->etag =
- Crypto.string_to_hex(Crypto.md5()->update(data)->digest());
- }
- #endif /* RAM_CACHE */
+
if( mixed err = catch( head_string += Roxen.make_http_headers( heads ) ) )
{
#ifdef DEBUG
1837: Inside #if defined(RAM_CACHE)
// We have to handle the date header.
"hs":head_string,
"key":misc->cachekey,
+ "etag":misc->etag,
"callbacks":misc->_cachecallbacks,
"len":file->len,
// fix non-keep-alive when sending from cache