You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by Roy Fielding <fi...@hyperreal.com> on 1996/11/06 11:30:41 UTC
cvs commit: apache/src Makefile.tmpl http_protocol.c util.c
fielding 96/11/06 02:30:40
Modified: src Makefile.tmpl http_protocol.c util.c
Log:
Replaced existing code for If-Modified-Since, If-Unmodified-Since,
If-Match, and If-None-Match in order to correct the order of preference
regarding ETags and to make use of the parseHTTPdate routine. Also
modified the comparison for last-modification time so that it changes
Last-Modified only if it is greater than the current time, rather than
the request_time. We also now check to be sure that the incoming
If-Modified-Since value is not greater than the request_time, which was
the last non-compliant bit for HTTP/1.1.
Finally, I updated the Makefile dependency list, since it was woefully
out-of-date and hard to read in its prior form.
Revision Changes Path
1.32 +69 -36 apache/src/Makefile.tmpl
Index: Makefile.tmpl
===================================================================
RCS file: /export/home/cvs/apache/src/Makefile.tmpl,v
retrieving revision 1.31
retrieving revision 1.32
diff -C3 -r1.31 -r1.32
*** Makefile.tmpl 1996/11/03 20:56:03 1.31
--- Makefile.tmpl 1996/11/06 10:30:37 1.32
***************
*** 51,94 ****
$(CC) -c $(INCLUDES) $(CFLAGS) $(BROKEN_BPRINTF_FLAGS) http_bprintf.c
#Dependencies
- #Core code
- $(OBJS): Makefile httpd.h alloc.h buff.h conf.h
! http_config.o http_core.o http_main.o util.o: http_conf_globals.h
! http_config.o http_core.o http_main.o: http_config.h http_log.h
! http_log.o http_protocol.o http_request.o modules.o: http_config.h
! http_config.o http_core.o http_log.o http_main.o http_protocol.o: http_core.h
! http_request.o: http_core.h
! http_protocol.o http_request.o util_script.o rfc1413.o: http_log.h
! http_core.o http_main.o http_protocol.o http_request.o: http_main.h
! http_core.o http_main.o http_protocol.o http_request.o: http_protocol.h
! http_config.o http_main.o http_request.o: http_request.h
! http_main.o: scoreboard.h
! http_core.o rfc1413.o: rfc1413.h
! #Modules
! $(MODULES): http_config.h httpd.h
! mod_dld.o: http_conf_globals.h
! mod_ai_backcompat.o mod_auth.o mod_auth_dbm.o mod_cgi.o mod_dir.o: http_core.h
! mod_access.o mod_imap.o mod_include.o mod_negotiation.o: http_core.h
! mod_asis.o mod_auth.o mod_auth_dbm.o mod_cgi.o mod_dir.o: http_core.h
! mod_status.o mod_cookies.o mod_log_common.o: http_core.h
! mod_access.o mod_imap.o mod_include.o mod_negotiation.o: http_log.h
! mod_asis.o mod_cgi.o mod_dir.o mod_imap.o: http_main.h
! mod_status.o mod_include.o: http_main.h
! mod_asis.o mod_auth.o mod_auth_dbm.o mod_cgi.o: http_protocol.h
! mod_status.o mod_dir.o: http_protocol.h
! mod_imap.o mod_include.o: http_protocol.h
! mod_cgi.o mod_dir.o mod_imap.o mod_include.o mod_negotiation.o: http_request.h
! mod_status.o: util_script.h
! mod_asis.o mod_cgi.o mod_dir.o mod_imap.o mod_include.o: util_script.h
! mod_digest.o: util_md5.h
! mod_status.o: scoreboard.h
!
! #Utils
md5c.o: md5.h
! util.o: http_conf_globals.h
! util_script.o: http_core.h http_main.h http_protocol.h util_script.h
! util_md5.o: md5.h
util_date.o: util_date.h
--- 51,127 ----
$(CC) -c $(INCLUDES) $(CFLAGS) $(BROKEN_BPRINTF_FLAGS) http_bprintf.c
#Dependencies
! $(OBJS): Makefile
! alloc.o: conf.h alloc.h
! buff.o: conf.h alloc.h buff.h
! explain.o: explain.h
! http_bprintf.o: conf.h alloc.h buff.h
! http_config.o: httpd.h http_config.h http_core.h http_log.h http_request.h \
! http_conf_globals.h explain.h
! http_core.o: httpd.h http_config.h http_core.h http_protocol.h scoreboard.h \
! http_conf_globals.h http_main.h http_log.h rfc1413.h util_md5.h
! http_log.o: httpd.h http_config.h http_core.h http_log.h
! http_main.o: httpd.h http_config.h http_core.h http_log.h http_request.h \
! http_conf_globals.h http_protocol.h http_main.h scoreboard.h \
! explain.h
! http_protocol.o: httpd.h http_config.h http_core.h http_protocol.h \
! http_main.h http_log.h util_date.h
! http_request.o: httpd.h http_config.h http_request.h http_core.h \
! http_protocol.h http_log.h http_main.h scoreboard.h
md5c.o: md5.h
! mod_access.o: httpd.h http_core.h http_config.h http_log.h
! mod_actions.o: httpd.h http_config.h http_request.h http_core.h \
! http_protocol.h http_main.h http_log.h util_script.h
! mod_alias.o: httpd.h http_config.h
! mod_asis.o: httpd.h http_config.h http_protocol.h http_log.h util_script.h \
! http_main.h http_request.h
! mod_auth.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h
! mod_auth_anon.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h
! mod_auth_db.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h
! mod_auth_dbm.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h
! mod_auth_msql.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h
! mod_browser.o: httpd.h http_config.h
! mod_cern_meta.o: httpd.h http_config.h util_script.h http_log.h
! mod_cgi.o: httpd.h http_config.h http_request.h http_core.h http_protocol.h \
! http_main.h http_log.h util_script.h
! mod_digest.o: httpd.h http_config.h http_core.h http_log.h http_protocol.h \
! util_md5.h
! mod_dir.o: httpd.h http_config.h http_core.h http_request.h http_protocol.h \
! http_log.h http_main.h util_script.h
! mod_dld.o: httpd.h http_config.h http_conf_globals.h
! mod_env.o: httpd.h http_config.h
! mod_expires.o: httpd.h http_config.h http_log.h
! mod_fastcgi.o: httpd.h http_config.h http_request.h http_core.h http_log.h \
! http_protocol.h http_main.h util_script.h http_conf_globals.h
! mod_headers.o: httpd.h http_config.h
! mod_imap.o: httpd.h http_config.h http_request.h http_core.h http_protocol.h \
! http_main.h http_log.h util_script.h
! mod_include.o: httpd.h http_config.h http_request.h http_core.h http_log.h \
! http_protocol.h http_main.h util_script.h
! mod_info.o: httpd.h http_config.h http_core.h http_log.h http_main.h \
! http_protocol.h util_script.h
! mod_log_agent.o: httpd.h http_config.h
! mod_log_config.o: httpd.h http_config.h http_core.h
! mod_log_referer.o: httpd.h http_config.h
! mod_mime.o: httpd.h http_config.h
! mod_negotiation.o: httpd.h http_config.h http_request.h http_core.h http_log.h
! mod_rewrite.o: httpd.h http_config.h http_request.h http_core.h http_log.h \
! mod_rewrite.h
! mod_status.o: httpd.h http_config.h http_core.h http_protocol.h http_main.h \
! util_script.h scoreboard.h
! mod_userdir.o: httpd.h http_config.h
! mod_usertrack.o: httpd.h http_config.h http_core.h
! modules.o: httpd.h http_config.h
! rfc1413.o: httpd.h http_log.h rfc1413.h
! util.o: httpd.h http_conf_globals.h
util_date.o: util_date.h
+ util_md5.o: httpd.h util_md5.h
+ util_script.o: httpd.h http_config.h http_conf_globals.h http_main.h \
+ http_log.h http_protocol.h http_core.h http_request.h \
+ util_script.h
+ httpd.h: conf.h alloc.h buff.h
+ mod_rewrite.h: regexp/regexp.h
+ util_md5.h: md5.h
1.71 +75 -118 apache/src/http_protocol.c
Index: http_protocol.c
===================================================================
RCS file: /export/home/cvs/apache/src/http_protocol.c,v
retrieving revision 1.70
retrieving revision 1.71
diff -C3 -r1.70 -r1.71
*** http_protocol.c 1996/11/04 01:06:09 1.70
--- http_protocol.c 1996/11/06 10:30:38 1.71
***************
*** 1,5 ****
/* ====================================================================
! * Copyright (c) 1995 The Apache Group. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
--- 1,5 ----
/* ====================================================================
! * Copyright (c) 1995, 1996 The Apache Group. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
***************
*** 51,60 ****
*/
/*
! * http_protocol.c --- routines which directly communicate with the
! * client.
*
! * Code originally by Rob McCool; much redone by rst.
*/
#define CORE_PRIVATE
--- 51,60 ----
*/
/*
! * http_protocol.c --- routines which directly communicate with the client.
*
! * Code originally by Rob McCool; much redone by Robert S. Thau
! * and the Apache Group.
*/
#define CORE_PRIVATE
***************
*** 66,72 ****
#include "http_log.h" /* For errors detected in basic auth
* common support code...
*/
!
#include <stdarg.h>
#define SET_BYTES_SENT(r) \
--- 66,72 ----
#include "http_log.h" /* For errors detected in basic auth
* common support code...
*/
! #include "util_date.h" /* For parseHTTPdate and BAD_DATE */
#include <stdarg.h>
#define SET_BYTES_SENT(r) \
***************
*** 74,148 ****
bgetopt (r->connection->client, BO_BYTECT, &r->bytes_sent); \
} while (0)
- /* Handling of conditional gets (if-modified-since); Roy owes Rob beer.
- * This would be considerably easier if strptime or timegm were portable...
- */
-
- const char month_snames[12][4] = {
- "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
- };
-
- int find_month(char *mon) {
- register int x;
-
- for(x=0;x<12;x++)
- if(!strcmp(month_snames[x],mon))
- return x;
- return -1;
- }
-
- int later_than(struct tm *lms, char *ims) {
- char *ip;
- char mname[MAX_STRING_LEN];
- int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0, x;
-
- /* Whatever format we're looking at, it will start with weekday. */
- /* Skip to first space. */
- if(!(ip = strchr(ims,' ')))
- return 0;
- else
- while(isspace(*ip))
- ++ip;
-
- if(isalpha(*ip)) {
- /* ctime */
- sscanf(ip,"%s %d %d:%d:%d %d",mname,&day,&hour,&min,&sec,&year);
- }
- else if(ip[2] == '-') {
- /* RFC 850 (normal HTTP) */
- char t[MAX_STRING_LEN];
- sscanf(ip,"%s %d:%d:%d",t,&hour,&min,&sec);
- t[2] = '\0';
- day = atoi(t);
- t[6] = '\0';
- strcpy(mname,&t[3]);
- x = atoi(&t[7]);
- /* Prevent wraparound from ambiguity */
- if(x < 70)
- x += 100;
- year = 1900 + x;
- }
- else {
- /* RFC 822 */
- sscanf(ip,"%d %s %d %d:%d:%d",&day,mname,&year,&hour,&min,&sec);
- }
- month = find_month(mname);
-
- if((x = (1900+lms->tm_year) - year))
- return x < 0;
- if((x = lms->tm_mon - month))
- return x < 0;
- if((x = lms->tm_mday - day))
- return x < 0;
- if((x = lms->tm_hour - hour))
- return x < 0;
- if((x = lms->tm_min - min))
- return x < 0;
- if((x = lms->tm_sec - sec))
- return x < 0;
-
- return 1;
- }
static int parse_byterange (char *range, long clength, long *start, long *end)
{
--- 74,79 ----
***************
*** 175,185 ****
return 1;
}
- /* This is a string I made up. Pounded on the keyboard a couple of times.
- * It's a good a way as any, I suppose, if you can't parse the document
- * beforehand (which we can't).
- */
-
int set_byterange (request_rec *r)
{
char *range = table_get (r->headers_in, "Range");
--- 106,111 ----
***************
*** 320,335 ****
int set_last_modified(request_rec *r, time_t mtime)
{
! char *ts, *etag, weak_etag[MAX_STRING_LEN];
! char *if_modified_since = table_get (r->headers_in, "If-Modified-Since");
! char *if_unmodified = table_get (r->headers_in, "If-Unmodified-Since");
! char *if_nonematch = table_get (r->headers_in, "If-None-Match");
! char *if_match = table_get (r->headers_in, "If-Match");
! ts = gm_timestr_822(r->pool, (mtime > r->request_time) ? r->request_time : mtime);
! table_set (r->headers_out, "Last-Modified", ts);
! /* Make an ETag header out of various peices of information. We use
* the last-modified date and, if we have a real file, the
* length and inode number - note that this doesn't have to match
* the content-length (i.e. includes), it just has to be unique
--- 246,262 ----
int set_last_modified(request_rec *r, time_t mtime)
{
! char *etag, weak_etag[MAX_STRING_LEN];
! char *if_modified_since = table_get(r->headers_in, "If-Modified-Since");
! char *if_unmodified = table_get(r->headers_in, "If-Unmodified-Since");
! char *if_nonematch = table_get(r->headers_in, "If-None-Match");
! char *if_match = table_get(r->headers_in, "If-Match");
! time_t now = time(NULL);
! table_set(r->headers_out, "Last-Modified",
! gm_timestr_822(r->pool, (mtime > now) ? now : mtime));
! /* Make an ETag header out of various pieces of information. We use
* the last-modified date and, if we have a real file, the
* length and inode number - note that this doesn't have to match
* the content-length (i.e. includes), it just has to be unique
***************
*** 343,391 ****
if (r->finfo.st_mode != 0)
sprintf(weak_etag, "W/\"%lx-%lx-%lx\"", (unsigned long)r->finfo.st_ino,
! (unsigned long)r->finfo.st_size, mtime);
else
! sprintf(weak_etag, "W/\"%lx\"", mtime);
etag = weak_etag + ((r->request_time - mtime > 1) ? 2 : 0);
table_set (r->headers_out, "ETag", etag);
! /* We now do the no_cache stuff using an Expires: header (we used to
! * withhold Last-modified). However, we still want to enforce this by
! * not allowing conditional GETs.
*/
! if (r->no_local_copy) return OK;
! /* Check for conditional GETs --- note that we only want this check
! * to succeed if the GET was successful; ErrorDocuments *always* get sent.
*/
-
- if (!is_HTTP_SUCCESS(r->status))
- return OK;
! if (if_modified_since && !r->header_only &&
! later_than(gmtime(&mtime), if_modified_since))
! return USE_LOCAL_COPY;
! else if (if_unmodified && !later_than(gmtime(&mtime), if_unmodified))
! return PRECONDITION_FAILED;
! else if (if_nonematch && ((if_nonematch[0] == '*') ||
! find_token(r->pool, if_nonematch, etag)))
! return (r->method_number == M_GET) ?
! USE_LOCAL_COPY : PRECONDITION_FAILED;
! else if (if_match && !((if_match[0] == '*') ||
! find_token(r->pool, if_match, etag)))
! return PRECONDITION_FAILED;
! else
! return OK;
! }
! /*
! * Finally, real protocol stuff.
! */
! static char *
! getline(char *s, int n, BUFF *in)
{
int retval = bgets (s, n, in);
--- 270,348 ----
if (r->finfo.st_mode != 0)
sprintf(weak_etag, "W/\"%lx-%lx-%lx\"", (unsigned long)r->finfo.st_ino,
! (unsigned long)r->finfo.st_size, (unsigned long)mtime);
else
! sprintf(weak_etag, "W/\"%lx\"", (unsigned long)mtime);
etag = weak_etag + ((r->request_time - mtime > 1) ? 2 : 0);
table_set (r->headers_out, "ETag", etag);
! /* Check for conditional requests --- note that we only want to do
! * this if we are successful so far and we are not processing a
! * subrequest or an ErrorDocument.
! *
! * The order of the checks is important, since etag checks are supposed
! * to be more accurate than checks relative to the modification time.
! */
!
! if (!is_HTTP_SUCCESS(r->status) || r->no_local_copy)
! return OK;
!
! /* If an If-Match request-header field was given and
! * if our ETag does not match any of the entity tags in that field
! * and the field value is not "*" (meaning match anything), then
! * respond with a status of 412 (Precondition Failed).
*/
! if (if_match &&
! !((if_match[0] == '*') || find_token(r->pool, if_match, etag)))
! return HTTP_PRECONDITION_FAILED;
!
! /* If an If-None-Match request-header field was given and
! * if our ETag matches any of the entity tags in that field or
! * if the field value is "*" (meaning match anything), then
! * if the request method was GET or HEAD, the server SHOULD
! * respond with a 304 (Not Modified) response.
! * For all other request methods, the server MUST
! * respond with a status of 412 (Precondition Failed).
! */
! if (if_nonematch &&
! ((if_nonematch[0] == '*') || find_token(r->pool, if_nonematch, etag)))
! return ((r->method_number == M_GET) || r->header_only) ?
! HTTP_NOT_MODIFIED : HTTP_PRECONDITION_FAILED;
!
! /* If a valid If-Unmodified-Since request-header field was given
! * and the requested resource has been modified since the time
! * specified in this field, then the server MUST
! * respond with a status of 412 (Precondition Failed).
*/
! if (if_unmodified) {
! time_t ius = parseHTTPdate(if_unmodified);
! if ((ius != BAD_DATE) && (mtime > ius))
! return HTTP_PRECONDITION_FAILED;
! }
!
! /* If a valid If-Modified-Since request-header field was given on a GET
! * and the requested resource has not been modified since the time
! * specified in this field, then the server MUST
! * respond with a status of 304 (Not Modified).
! * A date later than the server's current request time is invalid.
! */
!
! if (if_modified_since && (r->method_number == M_GET)) {
! time_t ims = parseHTTPdate(if_modified_since);
!
! if ((ims >= mtime) && (ims <= r->request_time))
! return HTTP_NOT_MODIFIED;
! }
!
! return OK;
! }
! static char *getline(char *s, int n, BUFF *in)
{
int retval = bgets (s, n, in);
1.29 +4 -0 apache/src/util.c
Index: util.c
===================================================================
RCS file: /export/home/cvs/apache/src/util.c,v
retrieving revision 1.28
retrieving revision 1.29
diff -C3 -r1.28 -r1.29
*** util.c 1996/10/27 07:23:21 1.28
--- util.c 1996/11/06 10:30:38 1.29
***************
*** 61,66 ****
--- 61,70 ----
#include "httpd.h"
#include "http_conf_globals.h" /* for user_id & group_id */
+ const char month_snames[12][4] = {
+ "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
+ };
+
char *get_time() {
time_t t;
char *time_string;