]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
- Added binary http headers to requests
authorrousskov <>
Tue, 12 May 1998 00:44:23 +0000 (00:44 +0000)
committerrousskov <>
Tue, 12 May 1998 00:44:23 +0000 (00:44 +0000)
        - request_t objects are now created and destroyed in a consistent way
        - Fixed cache control printf bug
        - Added a lot of new http header ids
        - Improved Connection: header handling; now both Connection and
          Proxy-Connection headers are checked
        - Connection request header is now handled correctly regardless
          of its position and the number of entries
        - Better handling of persistent connection "clues" in HTTP headers
        - Removed handling of "length=" directive in IMS headers;
          the directive is not in the HTTP/1.1 standard;
          standing by for objections
        - allowed/denied headers are now checked using bit masks instead of
          strcmp loops
        - removed Uri: from allowed headers; Uri is deprecated in RFC 2068
        - removed processing of Request-Range header (no in specs?)

note: binary headers for requests are not completed:
request_t still keeps and ascii image of the headers

31 files changed:
ChangeLog
src/CacheDigest.cc
src/HttpHdrCc.cc
src/HttpHdrRange.cc
src/HttpHeader.cc
src/HttpHeaderTools.cc
src/HttpReply.cc
src/HttpRequest.cc [new file with mode: 0644]
src/Makefile.in
src/MemBuf.cc
src/String.cc
src/acl.cc
src/asn.cc
src/cache_manager.cc
src/client.cc
src/client_side.cc
src/defines.h
src/enums.h
src/ftp.cc
src/http.cc
src/icp_v2.cc
src/icp_v3.cc
src/main.cc
src/neighbors.cc
src/net_db.cc
src/peer_digest.cc
src/protos.h
src/structs.h
src/url.cc
src/urn.cc
src/wais.cc

index 1f13b32b9c02b4c67c60a593e6773ef2e823112e..f528687c410cf127fd5a38dbd7d7a5cd4d59686c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
        - Changed URN menu output to be sorted.
        - Added fast select(2) timeouts when using ASYNC_IO.
        - Added ARP ACL support for Linux (David Luyer).
+        - Added binary http headers to requests
+        - request_t objects are now created and destroyed in a consistent way
+        - Fixed cache control printf bug
+        - Added a lot of new http header ids
+        - Improved Connection: header handling; now both Connection and
+          Proxy-Connection headers are checked
+        - Connection request header is now handled correctly regardless
+          of its position and the number of entries
+        - Better handling of persistent connection "clues" in HTTP headers
+        - Removed handling of "length=" directive in IMS headers;
+          the directive is not in the HTTP/1.1 standard;
+          standing by for objections
+        - allowed/denied headers are now checked using bit masks instead of
+          strcmp loops
+        - removed Uri: from allowed headers; Uri is deprecated in RFC 2068
+       - removed processing of Request-Range header (no in specs?)
+       
 
 Changes to squid-1.2.beta20 (April 24, 1998):
 
index 84619c9f4fc6f4d985afa4608e8ad191d3b413cd..960101c3562f40079e9ecb8b766ed2b4d6c17ded 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: CacheDigest.cc,v 1.17 1998/04/24 07:09:26 wessels Exp $
+ * $Id: CacheDigest.cc,v 1.18 1998/05/11 18:44:24 rousskov Exp $
  *
  * DEBUG: section 70    Cache Digest
  * AUTHOR: Alex Rousskov
@@ -56,7 +56,7 @@ cacheDigestInit(CacheDigest * cd, int capacity, int bpe)
     cd->bits_per_entry = bpe;
     cd->mask_size = mask_size;
     cd->mask = xcalloc(cd->mask_size, 1);
-    debug(70, 2) ("cacheDigestInit: capacity: %d entries, pbe: %d; size: %d bytes\n",
+    debug(70, 2) ("cacheDigestInit: capacity: %d entries, bpe: %d; size: %d bytes\n",
        cd->capacity, cd->bits_per_entry, cd->mask_size);
 }
 
index 45d4d7b4a8c33f398458e4c048e9c1b13b4b0e78..1bf513abf1cb7668ca687e2c06a3f31cc29c9330 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: HttpHdrCc.cc,v 1.9 1998/03/23 22:17:46 wessels Exp $
+ * $Id: HttpHdrCc.cc,v 1.10 1998/05/11 18:44:25 rousskov Exp $
  *
  * DEBUG: section 65    HTTP Cache Control Header
  * AUTHOR: Alex Rousskov
@@ -51,7 +51,7 @@ HttpHeaderFieldInfo *CcFieldsInfo = NULL;
 static int CcParsedCount = 0;
 
 /* local prototypes */
-static int httpHdrCcParseInit(HttpHdrCc * cc, const char *str);
+static int httpHdrCcParseInit(HttpHdrCc * cc, const String *str);
 
 
 /* module initialization */
@@ -81,7 +81,7 @@ httpHdrCcCreate()
 
 /* creates an cc object from a 0-terminating string */
 HttpHdrCc *
-httpHdrCcParseCreate(const char *str)
+httpHdrCcParseCreate(const String *str)
 {
     HttpHdrCc *cc = httpHdrCcCreate();
     if (!httpHdrCcParseInit(cc, str)) {
@@ -93,7 +93,7 @@ httpHdrCcParseCreate(const char *str)
 
 /* parses a 0-terminating string and inits cc */
 static int
-httpHdrCcParseInit(HttpHdrCc * cc, const char *str)
+httpHdrCcParseInit(HttpHdrCc * cc, const String *str)
 {
     const char *item;
     const char *p;             /* '=' parameter */
@@ -112,12 +112,12 @@ httpHdrCcParseInit(HttpHdrCc * cc, const char *str)
        type = httpHeaderIdByName(item, ilen,
            CcFieldsInfo, CC_ENUM_END);
        if (type < 0) {
-           debug(65, 2) ("hdr cc: unknown cache-directive: near '%s' in '%s'\n", item, str);
+           debug(65, 2) ("hdr cc: unknown cache-directive: near '%s' in '%s'\n", item, strBuf(*str));
            type = CC_OTHER;
        }
        if (EBIT_TEST(cc->mask, type)) {
            if (type != CC_OTHER)
-               debug(65, 2) ("hdr cc: ignoring duplicate cache-directive: near '%s' in '%s'\n", item, str);
+               debug(65, 2) ("hdr cc: ignoring duplicate cache-directive: near '%s' in '%s'\n", item, strBuf(*str));
            CcFieldsInfo[type].stat.repCount++;
            continue;
        }
@@ -164,13 +164,13 @@ httpHdrCcPackInto(const HttpHdrCc * cc, Packer * p)
     http_hdr_cc_type flag;
     int pcount = 0;
     assert(cc && p);
-    if (cc->max_age >= 0) {
-       packerPrintf(p, "max-age=%d", (int) cc->max_age);
-       pcount++;
-    }
     for (flag = 0; flag < CC_ENUM_END; flag++) {
+       if (flag == CC_MAX_AGE && cc->max_age >= 0) {
+           packerPrintf(p, "max-age=%d", (int) cc->max_age);
+           pcount++;
+       } else
        if (EBIT_TEST(cc->mask, flag) && flag != CC_OTHER) {
-           packerPrintf(p, pcount ? ", %s" : "%s", CcFieldsInfo[flag].name);
+           packerPrintf(p, (pcount ? ", %s" : "%s"), strBuf(CcFieldsInfo[flag].name));
            pcount++;
        }
     }
@@ -185,6 +185,18 @@ httpHdrCcJoinWith(HttpHdrCc * cc, const HttpHdrCc * new_cc)
     cc->mask |= new_cc->mask;
 }
 
+/* negative max_age will clean old max_Age setting */
+void
+httpHdrCcSetMaxAge(HttpHdrCc * cc, int max_age)
+{
+    assert(cc);
+    cc->max_age = max_age;
+    if (max_age >= 0)
+       EBIT_SET(cc->mask, CC_MAX_AGE);
+    else
+       EBIT_CLR(cc->mask, CC_MAX_AGE);
+}
+
 void
 httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist)
 {
index 1940445857f3e944e9c4c158e2f60befa0a3bbfd..09b9c7c4515b726da682e216b8e06d04008d216e 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: HttpHdrRange.cc,v 1.6 1998/04/06 22:32:07 wessels Exp $
+ * $Id: HttpHdrRange.cc,v 1.7 1998/05/11 18:44:25 rousskov Exp $
  *
  * DEBUG: section 64    HTTP Range Header
  * AUTHOR: Alex Rousskov
@@ -172,7 +172,7 @@ httpHdrRangeCreate()
 }
 
 HttpHdrRange *
-httpHdrRangeParseCreate(const char *str)
+httpHdrRangeParseCreate(const String *str)
 {
     HttpHdrRange *r = httpHdrRangeCreate();
     if (!httpHdrRangeParseInit(r, str)) {
@@ -184,18 +184,20 @@ httpHdrRangeParseCreate(const char *str)
 
 /* returns true if ranges are valid; inits HttpHdrRange */
 int
-httpHdrRangeParseInit(HttpHdrRange * range, const char *str)
+httpHdrRangeParseInit(HttpHdrRange * range, const String *str)
 {
     const char *item;
     const char *pos = NULL;
     int ilen;
+    int count = 0;
     assert(range && str);
     RangeParsedCount++;
-    debug(64, 8) ("parsing range field: '%s'\n", str);
+    debug(64, 8) ("parsing range field: '%s'\n", strBuf(*str));
     /* check range type */
-    if (strncasecmp(str, "bytes=", 6))
+    if (strNCaseCmp(*str, "bytes=", 6))
        return 0;
-    str += 6;
+    /* skip "bytes="; hack! */
+    pos = strBuf(*str)+5;
     /* iterate through comma separated list */
     while (strListGetItem(str, ',', &item, &ilen, &pos)) {
        HttpHdrRangeSpec *spec = httpHdrRangeSpecParseCreate(item, ilen);
@@ -205,6 +207,7 @@ httpHdrRangeParseInit(HttpHdrRange * range, const char *str)
         */
        if (spec)
            stackPush(&range->specs, spec);
+       count++;
     }
     debug(68, 8) ("parsed range range count: %d\n", range->specs.count);
     return range->specs.count;
index 3bcc0821fd5a863ee3dea6bd6151c5c8ce7e0c10..cf7dae6467d75ae1d10fb47a5a0028180a431185 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: HttpHeader.cc,v 1.32 1998/04/22 16:23:41 rousskov Exp $
+ * $Id: HttpHeader.cc,v 1.33 1998/05/11 18:44:26 rousskov Exp $
  *
  * DEBUG: section 55    HTTP Header
  * AUTHOR: Alex Rousskov
@@ -67,10 +67,6 @@ typedef struct {
 } HttpHeaderStat;
 
 
-/* use this and only this to initialize HttpHeaderPos */
-#define HttpHeaderInitPos (-1)
-
-
 /*
  * local constants and vars
  */
@@ -88,9 +84,12 @@ static const HttpHeaderFieldAttrs HeadersAttrs[] =
     {"Accept-Language", HDR_ACCEPT_LANGUAGE, ftStr},
     {"Accept-Ranges", HDR_ACCEPT_RANGES, ftStr},
     {"Age", HDR_AGE, ftInt},
+    {"Age", HDR_ALLOW, ftStr},
+    {"Authorization", HDR_AUTHORIZATION, ftStr}, /* for now */
     {"Cache-Control", HDR_CACHE_CONTROL, ftPCc},
     {"Connection", HDR_CONNECTION, ftStr},     /* for now */
     {"Content-Encoding", HDR_CONTENT_ENCODING, ftStr},
+    {"Content-Language", HDR_CONTENT_LANGUAGE, ftStr},
     {"Content-Length", HDR_CONTENT_LENGTH, ftInt},
     {"Content-MD5", HDR_CONTENT_MD5, ftStr},   /* for now */
     {"Content-Range", HDR_CONTENT_RANGE, ftPContRange},
@@ -98,24 +97,33 @@ static const HttpHeaderFieldAttrs HeadersAttrs[] =
     {"Date", HDR_DATE, ftDate_1123},
     {"ETag", HDR_ETAG, ftStr}, /* for now */
     {"Expires", HDR_EXPIRES, ftDate_1123},
+    {"From", HDR_FROM, ftStr},
     {"Host", HDR_HOST, ftStr},
-    {"If-Modified-Since", HDR_IMS, ftDate_1123},
+    {"If-Modified-Since", HDR_IF_MODIFIED_SINCE, ftDate_1123},
     {"Last-Modified", HDR_LAST_MODIFIED, ftDate_1123},
+    {"Link", HDR_LINK, ftStr},
     {"Location", HDR_LOCATION, ftStr},
     {"Max-Forwards", HDR_MAX_FORWARDS, ftInt},
     {"Mime-Version", HDR_MIME_VERSION, ftStr}, /* for now */
+    {"Pragma", HDR_PRAGMA, ftStr},
     {"Proxy-Authenticate", HDR_PROXY_AUTHENTICATE, ftStr},
+    {"Proxy-Authorization", HDR_PROXY_AUTHORIZATION, ftStr},
     {"Proxy-Connection", HDR_PROXY_CONNECTION, ftStr},
     {"Public", HDR_PUBLIC, ftStr},
     {"Range", HDR_RANGE, ftPRange},
-    {"Retry-After", HDR_RETRY_AFTER, ftStr},   /* for now */
+    {"Referer", HDR_REFERER, ftStr},
+    {"Retry-After", HDR_RETRY_AFTER, ftStr},   /* for now (ftDate_1123 or ftInt!) */
     {"Server", HDR_SERVER, ftStr},
     {"Set-Cookie", HDR_SET_COOKIE, ftStr},
+    {"Title", HDR_TITLE, ftStr},
     {"Upgrade", HDR_UPGRADE, ftStr},   /* for now */
+    {"User-Agent", HDR_USER_AGENT, ftStr},
+    {"Via", HDR_VIA, ftStr},   /* for now */
     {"Warning", HDR_WARNING, ftStr},   /* for now */
     {"WWW-Authenticate", HDR_WWW_AUTHENTICATE, ftStr},
     {"X-Cache", HDR_X_CACHE, ftStr},
     {"X-Cache-Lookup", HDR_X_CACHE_LOOKUP, ftStr},
+    {"X-Forwarded-For", HDR_X_FORWARDED_FOR, ftStr},
     {"Other:", HDR_OTHER, ftStr}       /* ':' will not allow matches */
 };
 static HttpHeaderFieldInfo *Headers = NULL;
@@ -129,35 +137,57 @@ static http_hdr_type ListHeadersArr[] =
 {
     HDR_ACCEPT,
     HDR_ACCEPT_CHARSET, HDR_ACCEPT_ENCODING, HDR_ACCEPT_LANGUAGE,
-    HDR_ACCEPT_RANGES,
-    /* HDR_ALLOW, */
+    HDR_ACCEPT_RANGES, HDR_ALLOW,
     HDR_CACHE_CONTROL,
     HDR_CONTENT_ENCODING,
-    /* HDR_CONTENT_LANGUAGE, */
-    /*  HDR_IF_MATCH, HDR_IF_NONE_MATCH, HDR_PRAGMA, */
+    HDR_CONTENT_LANGUAGE,
+    HDR_CONNECTION,
+    /*  HDR_IF_MATCH, HDR_IF_NONE_MATCH, */
+    HDR_LINK, HDR_PRAGMA,
     /* HDR_TRANSFER_ENCODING, */
     HDR_UPGRADE,               /* HDR_VARY, */
-    /* HDR_VIA, HDR_WARNING, */
+    HDR_VIA, 
+    /* HDR_WARNING, */
     HDR_WWW_AUTHENTICATE,
     /* HDR_EXPECT, HDR_TE, HDR_TRAILER */
+    HDR_X_FORWARDED_FOR
+};
+
+/* general-headers */
+static http_hdr_type GeneralHeadersArr[] =
+{
+    HDR_CACHE_CONTROL, HDR_CONNECTION, HDR_DATE, HDR_PRAGMA,
+    /* HDR_TRANSFER_ENCODING, */
+    HDR_UPGRADE,
+    /* HDR_TRAILER, */
+    HDR_VIA
+};
+
+/* entity-headers */
+static http_hdr_type EntityHeadersArr[] =
+{
+    HDR_ALLOW, HDR_CONTENT_ENCODING, HDR_CONTENT_LANGUAGE, HDR_CONTENT_LENGTH,
+    HDR_CONTENT_RANGE, HDR_ETAG, HDR_EXPIRES, HDR_LAST_MODIFIED, HDR_LINK, HDR_OTHER
 };
 
 static HttpHeaderMask ReplyHeadersMask;                /* set run-time using ReplyHeaders */
 static http_hdr_type ReplyHeadersArr[] =
 {
     HDR_ACCEPT, HDR_ACCEPT_CHARSET, HDR_ACCEPT_ENCODING, HDR_ACCEPT_LANGUAGE,
-    HDR_ACCEPT_RANGES, HDR_AGE, HDR_CACHE_CONTROL, HDR_CONTENT_LENGTH,
-    HDR_CONTENT_MD5, HDR_CONTENT_RANGE, HDR_CONTENT_TYPE, HDR_DATE, HDR_ETAG,
-    HDR_EXPIRES, HDR_LAST_MODIFIED, HDR_LOCATION, HDR_MAX_FORWARDS,
+    HDR_ACCEPT_RANGES, HDR_AGE,
+    HDR_CONTENT_MD5, HDR_CONTENT_TYPE,
+    HDR_LOCATION, HDR_MAX_FORWARDS,
     HDR_MIME_VERSION, HDR_PUBLIC, HDR_RETRY_AFTER, HDR_SERVER, HDR_SET_COOKIE,
-    HDR_UPGRADE, HDR_WARNING, HDR_PROXY_CONNECTION, HDR_X_CACHE,
-    HDR_X_CACHE_LOOKUP, HDR_OTHER
+    HDR_WARNING, HDR_PROXY_CONNECTION, HDR_X_CACHE,
+    HDR_X_CACHE_LOOKUP
 };
 
 static HttpHeaderMask RequestHeadersMask;      /* set run-time using RequestHeaders */
 static http_hdr_type RequestHeadersArr[] =
 {
-    HDR_RANGE, HDR_OTHER
+    HDR_AUTHORIZATION, HDR_FROM, HDR_HOST, HDR_IF_MODIFIED_SINCE,
+    HDR_MAX_FORWARDS, HDR_PROXY_CONNECTION, HDR_PROXY_AUTHORIZATION,
+    HDR_RANGE, HDR_REFERER, HDR_USER_AGENT, HDR_X_FORWARDED_FOR
 };
 
 /* header accounting */
@@ -181,24 +211,17 @@ static int HeaderEntryParsedCount = 0;
 
 #define assert_eid(id) assert((id) >= 0 && (id) < HDR_ENUM_END)
 
-static HttpHeaderEntry *httpHeaderGetEntry(const HttpHeader * hdr, HttpHeaderPos * pos);
+static int httpHeaderDelById(HttpHeader * hdr, http_hdr_type id);
 static void httpHeaderDelAt(HttpHeader * hdr, HttpHeaderPos pos);
-/* static int httpHeaderDelById(HttpHeader * hdr, http_hdr_type id); */
-static void httpHeaderAddEntry(HttpHeader * hdr, HttpHeaderEntry * e);
-static String httpHeaderJoinEntries(const HttpHeader * hdr, http_hdr_type id);
 
 static HttpHeaderEntry *httpHeaderEntryCreate(http_hdr_type id, const char *name, const char *value);
 static void httpHeaderEntryDestroy(HttpHeaderEntry * e);
 static HttpHeaderEntry *httpHeaderEntryParseCreate(const char *field_start, const char *field_end);
-static HttpHeaderEntry *httpHeaderEntryClone(const HttpHeaderEntry * e);
 static void httpHeaderNoteParsedEntry(http_hdr_type id, String value, int error);
 
 static void httpHeaderStatInit(HttpHeaderStat * hs, const char *label);
 static void httpHeaderStatDump(const HttpHeaderStat * hs, StoreEntry * e);
 
-/* handy to determine the #elements in a static array */
-#define countof(arr) (sizeof(arr)/sizeof(*arr))
-
 /*
  * Module initialization routines
  */
@@ -211,9 +234,16 @@ httpHeaderInitModule()
     assert(8 * sizeof(HttpHeaderMask) >= HDR_ENUM_END);
     Headers = httpHeaderBuildFieldsInfo(HeadersAttrs, HDR_ENUM_END);
     /* create masks */
+    httpHeaderMaskInit(&ListHeadersMask);
     httpHeaderCalcMask(&ListHeadersMask, (const int *) ListHeadersArr, countof(ListHeadersArr));
+    httpHeaderMaskInit(&ReplyHeadersMask);
     httpHeaderCalcMask(&ReplyHeadersMask, (const int *) ReplyHeadersArr, countof(ReplyHeadersArr));
+    httpHeaderCalcMask(&ReplyHeadersMask, (const int *) GeneralHeadersArr, countof(GeneralHeadersArr));
+    httpHeaderCalcMask(&ReplyHeadersMask, (const int *) EntityHeadersArr, countof(EntityHeadersArr));
+    httpHeaderMaskInit(&RequestHeadersMask);
     httpHeaderCalcMask(&RequestHeadersMask, (const int *) RequestHeadersArr, countof(RequestHeadersArr));
+    httpHeaderCalcMask(&RequestHeadersMask, (const int *) GeneralHeadersArr, countof(GeneralHeadersArr));
+    httpHeaderCalcMask(&RequestHeadersMask, (const int *) EntityHeadersArr, countof(EntityHeadersArr));
     /* init header stats */
     for (i = 0; i < HttpHeaderStatCount; i++)
        httpHeaderStatInit(HttpHeaderStats + i, HttpHeaderStats[i].label);
@@ -339,10 +369,7 @@ httpHeaderParse(HttpHeader * hdr, const char *header_start, const char *header_e
     return 1;                  /* even if no fields where found, it is a valid header */
 }
 
-/*
- * packs all the entries into the buffer, 
- * returns number of bytes packed including terminating '\0'
- */
+/* packs all the entries using supplied packer */
 void
 httpHeaderPackInto(const HttpHeader * hdr, Packer * p)
 {
@@ -356,7 +383,7 @@ httpHeaderPackInto(const HttpHeader * hdr, Packer * p)
 }
 
 /* returns next valid entry */
-static HttpHeaderEntry *
+HttpHeaderEntry *
 httpHeaderGetEntry(const HttpHeader * hdr, HttpHeaderPos * pos)
 {
     assert(hdr && pos);
@@ -445,7 +472,6 @@ httpHeaderDelByName(HttpHeader * hdr, const char *name)
     return count;
 }
 
-#if FUTURE_CODE
 static int
 httpHeaderDelById(HttpHeader * hdr, http_hdr_type id)
 {
@@ -465,7 +491,6 @@ httpHeaderDelById(HttpHeader * hdr, http_hdr_type id)
     assert(count);
     return count;
 }
-#endif
 
 /*
  * deletes an entry at pos and leaves a gap; leaving a gap makes it
@@ -478,12 +503,11 @@ httpHeaderDelAt(HttpHeader * hdr, HttpHeaderPos pos)
     hdr->entries.items[pos] = NULL;
 }
 
-/*
- * adds parsed entry (joins entries if neeeded); assumes e.value is dup()-ed and
- * clean()s it if needed. Thus, "e" should be treated as uninitialized after
- * this function returns.
+
+/* appends an entry; 
+ * does not call httpHeaderEntryClone() so one should not reuse "*e"
  */
-static void
+void
 httpHeaderAddEntry(HttpHeader * hdr, HttpHeaderEntry * e)
 {
     assert(hdr && e);
@@ -498,24 +522,30 @@ httpHeaderAddEntry(HttpHeader * hdr, HttpHeaderEntry * e)
     arrayAppend(&hdr->entries, e);
 }
 
-static String
-httpHeaderJoinEntries(const HttpHeader * hdr, http_hdr_type id)
+/* return a list of entries with the same id separated by ',' and ws */
+String
+httpHeaderGetList(const HttpHeader * hdr, http_hdr_type id)
 {
     String s = StringNull;
     HttpHeaderEntry *e;
     HttpHeaderPos pos = HttpHeaderInitPos;
     debug(55, 6) ("%p: joining for id %d\n", hdr, id);
+    /* only fields from ListHeaders array can be "listed" */
     assert(CBIT_TEST(ListHeadersMask, id));
+    if (!CBIT_TEST(hdr->mask, id))
+        return s;
     while ((e = httpHeaderGetEntry(hdr, &pos))) {
-       if (e->id == id) {
-           if (strLen(s)) {
-               stringAppend(&s, ",", 1);
-               stringAppend(&s, strBuf(e->value), strLen(e->value));
-           } else
-               s = stringDup(&e->value);
-       }
+       if (e->id == id)
+           strListAdd(&s, strBuf(e->value), ',');
     }
-    assert(strLen(s));
+    /*
+     * note: we might get an empty (len==0) string if there was an "empty"
+     * header; we must not get a NULL string though.
+     */
+    assert(strBuf(s));
+    /* temporary warning: remove it! @?@ @?@ @?@ */
+    if (!strLen(s))
+       debug(55, 1) ("empty list header: %s (%d)\n", strBuf(Headers[id].name), id);
     debug(55, 6) ("%p: joined for id %d: %s\n", hdr, id, strBuf(s));
     return s;
 }
@@ -570,6 +600,25 @@ httpHeaderPutAuth(HttpHeader * hdr, const char *authScheme, const char *realm)
     memBufClean(&mb);
 }
 
+void
+httpHeaderPutCc(HttpHeader * hdr, const HttpHdrCc *cc)
+{
+    MemBuf mb;
+    Packer p;
+    assert(hdr && cc);
+    /* remove old directives if any */
+    httpHeaderDelById(hdr, HDR_CACHE_CONTROL);
+    /* pack into mb */
+    memBufDefInit(&mb);
+    packerToMemInit(&p, &mb);
+    httpHdrCcPackInto(cc, &p);
+    /* put */
+    httpHeaderAddEntry(hdr, httpHeaderEntryCreate(HDR_CACHE_CONTROL, NULL, mb.buf));
+    /* cleanup */
+    packerClean(&p);
+    memBufClean(&mb);
+}
+
 /* add extension header (these fields are not parsed/analyzed/joined, etc.) */
 void
 httpHeaderPutExt(HttpHeader * hdr, const char *name, const char *value)
@@ -608,7 +657,7 @@ httpHeaderGetTime(const HttpHeader * hdr, http_hdr_type id)
     return value;
 }
 
-/* sync httpHeaderGetLastStr */
+/* sync with httpHeaderGetLastStr */
 const char *
 httpHeaderGetStr(const HttpHeader * hdr, http_hdr_type id)
 {
@@ -643,8 +692,8 @@ httpHeaderGetCc(const HttpHeader * hdr)
     String s;
     if (!CBIT_TEST(hdr->mask, HDR_CACHE_CONTROL))
        return NULL;
-    s = httpHeaderJoinEntries(hdr, HDR_CACHE_CONTROL);
-    cc = httpHdrCcParseCreate(strBuf(s));
+    s = httpHeaderGetList(hdr, HDR_CACHE_CONTROL);
+    cc = httpHdrCcParseCreate(&s);
     /* fix this for req headers @?@ */
     if (cc)
        httpHdrCcUpdateStats(cc, &HttpHeaderStats[0].ccTypeDistr);
@@ -660,8 +709,8 @@ httpHeaderGetRange(const HttpHeader * hdr)
     String s;
     if (!CBIT_TEST(hdr->mask, HDR_RANGE))
        return NULL;
-    s = httpHeaderJoinEntries(hdr, HDR_RANGE);
-    r = httpHdrRangeParseCreate(strBuf(s));
+    s = httpHeaderGetList(hdr, HDR_RANGE);
+    r = httpHdrRangeParseCreate(&s);
     httpHeaderNoteParsedEntry(HDR_RANGE, s, !r);
     stringClean(&s);
     return r;
@@ -679,21 +728,27 @@ httpHeaderGetContRange(const HttpHeader * hdr)
     return cr;
 }
 
-#if FUTURE_CODE
-HttpHdrConn *
-httpHeaderGetConn(const HttpHeader * hdr)
+const char *
+httpHeaderGetAuth(const HttpHeader * hdr, http_hdr_type id, const char *authScheme)
 {
-    HttpHdrConn *conn;
-    String s;
-    if (!CBIT_TEST(hdr->mask, HDR_CONNECTION))
+    const char *field;
+    int l;
+    assert(hdr && authScheme);
+    field = httpHeaderGetStr(hdr, id);
+    if (!field) /* no authorization field */
        return NULL;
-    s = httpHeaderJoinEntries(hdr, HDR_CONNECTION);
-    conn = httpHdrConnParseCreate(s);
-    httpHeaderNoteParsedEntry(HDR_CONNECTION, s, !conn);
-    stringClean(&s);
-    return conn;
+    l = strlen(authScheme);
+    if (!l || strncasecmp(field, authScheme, l)) /* wrong scheme */
+       return NULL;
+    field += l;
+    if (!isspace(*field)) /* wrong scheme */
+       return NULL;
+    /* skip white space */
+    field += xcountws(field);
+    if (!*field) /* no authorization cookie */
+       return NULL;
+    return base64_decode(field);
 }
-#endif
 
 /*
  * HttpHeaderEntry
@@ -774,7 +829,7 @@ httpHeaderEntryParseCreate(const char *field_start, const char *field_end)
     return e;
 }
 
-static HttpHeaderEntry *
+HttpHeaderEntry *
 httpHeaderEntryClone(const HttpHeaderEntry * e)
 {
     return httpHeaderEntryCreate(e->id, strBuf(e->name), strBuf(e->value));
index ffdb7be030218ca2ea800da1fdcea01d9cedf718..8268401d5809d0d4247ae1b42cb542a387b36f18 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: HttpHeaderTools.cc,v 1.10 1998/04/27 19:16:05 wessels Exp $
+ * $Id: HttpHeaderTools.cc,v 1.11 1998/05/11 18:44:27 rousskov Exp $
  *
  * DEBUG: section 66    HTTP Header Tools
  * AUTHOR: Alex Rousskov
@@ -76,14 +76,13 @@ httpHeaderMaskInit(HttpHeaderMask * mask)
     memset(mask, 0, sizeof(*mask));
 }
 
-/* calculates a bit mask of a given array */
+/* calculates a bit mask of a given array; does not reset mask! */
 void
 httpHeaderCalcMask(HttpHeaderMask * mask, const int *enums, int count)
 {
     int i;
     assert(mask && enums);
-    assert(count < sizeof(int) * 8);   /* check for overflow */
-    httpHeaderMaskInit(mask);
+    assert(count < sizeof(*mask) * 8); /* check for overflow */
 
     for (i = 0; i < count; ++i) {
        assert(!CBIT_TEST(*mask, enums[i]));    /* check for duplicates */
@@ -106,6 +105,50 @@ httpHeaderIdByName(const char *name, int name_len, const HttpHeaderFieldInfo * i
     return -1;
 }
 
+/*
+ * return true if a given directive is found in at least one of the "connection" header-fields
+ * note: if HDR_PROXY_CONNECTION is present we ignore HDR_CONNECTION
+ */
+int
+httpHeaderHasConnDir(const HttpHeader *hdr, const char *directive)
+{
+    if (httpHeaderHas(hdr, HDR_PROXY_CONNECTION)) {
+       const char *str = httpHeaderGetStr(hdr, HDR_PROXY_CONNECTION);
+       return str && !strcasecmp(str, directive);
+    }
+    if (httpHeaderHas(hdr, HDR_CONNECTION)) {
+       String str = httpHeaderGetList(hdr, HDR_CONNECTION);
+       const int res = strListIsMember(&str, directive, ',');
+       stringClean(&str);
+       return res;
+    }
+    return 0;
+}
+
+/* returns true iff "m" is a member of the list */
+int
+strListIsMember(const String *list, const char *m, char del)
+{
+    const char *pos = NULL;
+    const char *item;
+    assert(list && m);
+    while (strListGetItem(list, del, &item, NULL, &pos)) {
+       if (!strcasecmp(item, m))
+           return 1;
+    }
+    return 0;
+}
+
+/* appends an item to the list */
+void
+strListAdd(String *str, const char *item, char del)
+{
+    assert(str && item);
+    if (strLen(*str))
+       stringAppend(str, &del, 1);
+    stringAppend(str, item, strlen(item));
+}
+
 /*
  * iterates through a 0-terminated string of items separated by 'del's.
  * white space around 'del' is considered to be a part of 'del'
@@ -115,7 +158,7 @@ httpHeaderIdByName(const char *name, int name_len, const HttpHeaderFieldInfo * i
  * init pos with NULL to start iteration.
  */
 int
-strListGetItem(const char *str, char del, const char **item, int *ilen, const char **pos)
+strListGetItem(const String *str, char del, const char **item, int *ilen, const char **pos)
 {
     size_t len;
     assert(str && item && pos);
@@ -125,7 +168,9 @@ strListGetItem(const char *str, char del, const char **item, int *ilen, const ch
        else
            (*pos)++;
     } else {
-       *pos = str;
+       *pos = strBuf(*str);
+       if (!*pos)
+           return 0;
     }
 
     /* skip leading ws (ltrim) */
index c54733b50e666fc3e396ffee3f2800ef5de96b97..5f542b9c4c892391443ff2bbf0eeaf54cdffc28a 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: HttpReply.cc,v 1.17 1998/04/27 20:03:56 wessels Exp $
+ * $Id: HttpReply.cc,v 1.18 1998/05/11 18:44:27 rousskov Exp $
  *
  * DEBUG: section 58    HTTP Reply (Response)
  * AUTHOR: Alex Rousskov
@@ -41,7 +41,6 @@ static void httpReplyHdrCacheClean(HttpReply * rep);
 static int httpReplyParseStep(HttpReply * rep, const char *parse_start, int atEnd);
 static int httpReplyParseError(HttpReply * rep);
 static int httpReplyIsolateStart(const char **parse_start, const char **blk_start, const char **blk_end);
-static int httpReplyIsolateHeaders(const char **parse_start, const char **blk_start, const char **blk_end);
 
 
 HttpReply *
@@ -270,17 +269,7 @@ httpReplyHdrCacheInit(HttpReply * rep)
        rep->content_type = StringNull;
     rep->cache_control = httpHeaderGetCc(hdr);
     rep->content_range = httpHeaderGetContRange(hdr);
-    str = httpHeaderGetStr(hdr, HDR_PROXY_CONNECTION);
-    if (NULL == str)
-       str = httpHeaderGetStr(hdr, HDR_CONNECTION);    /* @?@ FIX ME */
-    if (str) {
-       rep->keep_alive = (strcasecmp(str, "Keep-Alive") == 0);
-    } else {
-       if (rep->sline.version >= 1.1)
-           rep->keep_alive = 1;        /* 1.1+ defaults to keep-alive */
-       else
-           rep->keep_alive = 0;        /* pre 1.1 default to non-keep-alive */
-    }
+    rep->keep_alive = httpMsgIsPersistent(rep->sline.version, &rep->header);
     /* final adjustments */
     /* The max-age directive takes priority over Expires, check it first */
     if (rep->cache_control && rep->cache_control->max_age >= 0)
@@ -334,12 +323,12 @@ httpReplyParseStep(HttpReply * rep, const char *buf, int atEnd)
        rep->pstate++;
     }
     if (rep->pstate == psReadyToParseHeaders) {
-       if (!httpReplyIsolateHeaders(&parse_start, &blk_start, &blk_end)) {
+       if (!httpMsgIsolateHeaders(&parse_start, &blk_start, &blk_end)) {
            if (atEnd)
                blk_start = parse_start, blk_end = blk_start + strlen(blk_start);
            else
                return 0;
-       }
+        }
        if (!httpHeaderParse(&rep->header, blk_start, blk_end))
            return httpReplyParseError(rep);
 
@@ -352,7 +341,6 @@ httpReplyParseStep(HttpReply * rep, const char *buf, int atEnd)
     return 1;
 }
 
-
 /* handy: resets and returns -1 */
 static int
 httpReplyParseError(HttpReply * rep)
@@ -385,8 +373,8 @@ httpReplyIsolateStart(const char **parse_start, const char **blk_start, const ch
 }
 
 /* find end of headers */
-static int
-httpReplyIsolateHeaders(const char **parse_start, const char **blk_start, const char **blk_end)
+int
+httpMsgIsolateHeaders(const char **parse_start, const char **blk_start, const char **blk_end)
 {
     /* adopted with mods from mime_headers_end() */
     const char *p1 = strstr(*parse_start, "\n\r\n");
@@ -402,6 +390,36 @@ httpReplyIsolateHeaders(const char **parse_start, const char **blk_start, const
        *blk_start = *parse_start;
        *blk_end = end + 1;
        *parse_start = end + (end == p1 ? 3 : 2);
+       return 1;
+    }
+    /* no headers, case 1 */
+    if ((*parse_start)[0] == '\r' && (*parse_start)[1] == '\n') {
+       *blk_start = *parse_start;
+       *blk_end = *blk_start;
+       *parse_start += 2;
+       return 1;
+    }
+    /* no headers, case 2 */
+    if ((*parse_start)[0] == '\n') {
+       /* no headers */
+       *blk_start = *parse_start;
+       *blk_end = *blk_start;
+       *parse_start += 1;
+       return 1;
+    }
+    /* failure */
+    return 0;
+}
+
+/* returns true if connection should be "persistent" after processing this message */
+int
+httpMsgIsPersistent(float http_ver, const HttpHeader *hdr)
+{
+    if (http_ver >= 1.1) {
+       /* for modern versions: persistent if not "close"d */
+       return !httpHeaderHasConnDir(hdr, "close");
+    } else {
+       /* for old versions: persistent if has "keep-alive" */
+       return httpHeaderHasConnDir(hdr, "keep-alive");
     }
-    return end != NULL;
 }
diff --git a/src/HttpRequest.cc b/src/HttpRequest.cc
new file mode 100644 (file)
index 0000000..3b49d8a
--- /dev/null
@@ -0,0 +1,119 @@
+
+/*
+ * $Id: HttpRequest.cc,v 1.2 1998/05/11 18:44:28 rousskov Exp $
+ *
+ * DEBUG: section 73    HTTP Request
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
+ * --------------------------------------------------------
+ *
+ *  Squid is the result of efforts by numerous individuals from the
+ *  Internet community.  Development is led by Duane Wessels of the
+ *  National Laboratory for Applied Network Research and funded by
+ *  the National Science Foundation.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *  
+ */
+
+#include "squid.h"
+
+request_t *
+requestCreate(method_t method, protocol_t protocol, const char *urlpath)
+{
+    request_t * req = memAllocate(MEM_REQUEST_T);
+    req->method = method;
+    req->protocol = protocol;
+    if (urlpath)
+       stringReset(&req->urlpath, urlpath);
+    req->max_age = -1;
+    req->max_forwards = -1;
+    return req;
+}
+
+void
+requestDestroy(request_t * req)
+{
+    assert(req);
+    safe_free(req->prefix);
+    safe_free(req->body);
+    stringClean(&req->urlpath);
+    httpHeaderClean(&req->header);
+    memFree(MEM_REQUEST_T, req);
+}
+
+request_t *
+requestLink(request_t * request)
+{
+    assert(request);
+    request->link_count++;
+    return request;
+}
+
+void
+requestUnlink(request_t * request)
+{
+    if (!request)
+       return;
+    request->link_count--;
+    if (request->link_count > 0)
+       return;
+    requestDestroy(request);
+}
+
+int
+httpRequestParseHeader(request_t *req, const char *parse_start)
+{
+    const char *blk_start, *blk_end;
+    if (!httpMsgIsolateHeaders(&parse_start, &blk_start, &blk_end))
+       return 0;
+    return httpHeaderParse(&req->header, blk_start, blk_end);
+}
+
+void
+httpRequestSetHeaders(request_t *req, method_t method, const char *uri, const char *header_str)
+{
+    MemBuf mb;
+    assert(req && uri && header_str);
+    assert(!req->prefix);
+
+    memBufDefInit(&mb);
+    memBufPrintf(&mb, "%s %s HTTP/%3.1f\r\n%s\r\n",
+       RequestMethodStr[method], uri, req->http_ver, header_str);
+    req->prefix = xstrdup(mb.buf);
+    req->prefix_sz = mb.size;
+    memBufClean(&mb);
+    httpHeaderParse(&req->header, header_str, header_str+strlen(header_str));
+}
+
+/* returns true if header is allowed to be passed on */
+int
+httpRequestHdrAllowed(const HttpHeaderEntry *e, String *strConn)
+{
+    assert(e);
+    /* check connection header first */
+    if (strConn && strListIsMember(strConn, strBuf(e->name), ','))
+       return 0;
+    /* check with anonymizer tables */
+    if (Config.onoff.anonymizer == ANONYMIZER_PARANOID) {
+       return httpAnonHdrAllowed(e->id);
+    } else
+    if (Config.onoff.anonymizer == ANONYMIZER_STANDARD) {
+       return !httpAnonHdrDenied(e->id);
+    }
+    return 1;
+}
+
index 1df50087445cfb1d5597c50abefd0934c3be4d0a..9a6f1670554986147d5d52382fc9865e203a9732 100644 (file)
@@ -1,7 +1,7 @@
 #
 #  Makefile for the Squid Object Cache server
 #
-#  $Id: Makefile.in,v 1.148 1998/05/05 03:49:56 wessels Exp $
+#  $Id: Makefile.in,v 1.149 1998/05/11 18:44:29 rousskov Exp $
 #
 #  Uncomment and customize the following to suit your needs:
 #
@@ -111,6 +111,7 @@ OBJS                = \
                HttpHeaderTools.o \
                HttpBody.o \
                HttpReply.o \
+               HttpRequest.o \
                icmp.o \
                icp_v2.o \
                icp_v3.o \
index 3cf1838417f7b51b419c801a59e9f0e1fa265b0d..0efcd7876df87d2d9f063944f25d8bbfb4b8c3de 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: MemBuf.cc,v 1.7 1998/04/04 00:22:15 wessels Exp $
+ * $Id: MemBuf.cc,v 1.8 1998/05/11 18:44:30 rousskov Exp $
  *
  * DEBUG: section 59    auto-growing Memory Buffer with printf
  * AUTHOR: Alex Rousskov
@@ -29,7 +29,7 @@
  */
 
 /*
- * To-Do: uses memory pools for .buf recycling @?@
+ * To-Do: uses memory pools for .buf recycling @?@ @?@
  */
 
 /*
@@ -259,7 +259,7 @@ memBufGrow(MemBuf * mb, mb_size_t min_cap)
        mb->buf = xmalloc(new_cap);
        mb->freefunc = &xfree;
     } else {
-       assert(mb->freefunc);
+       assert(mb->freefunc == &xfree); /* for now */
        mb->buf = xrealloc(mb->buf, new_cap);
     }
     memset(mb->buf + mb->size, 0, new_cap - mb->size); /* just in case */
index 44075c616f0c4656d981964ea48804197882797a..489c49b033b929b741eed5e71e2a03307bdbb64c 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: String.cc,v 1.4 1998/04/06 22:32:10 wessels Exp $
+ * $Id: String.cc,v 1.5 1998/05/11 18:44:30 rousskov Exp $
  *
  * DEBUG: section 67    String
  * AUTHOR: Duane Wessels
@@ -87,7 +87,8 @@ stringReset(String * s, const char *str)
 void
 stringAppend(String * s, const char *str, int len)
 {
-    assert(s && s->buf);
+    assert(s);
+    assert(str && len >= 0);
     if (s->len + len < s->size) {
        strncat(s->buf, str, len);
        s->len += len;
@@ -95,8 +96,10 @@ stringAppend(String * s, const char *str, int len)
        String snew = StringNull;
        snew.len = s->len + len;
        stringInitBuf(&snew, snew.len + 1);
-       xmemcpy(snew.buf, s->buf, s->len);
-       xmemcpy(snew.buf + s->len, str, len);
+       if (s->buf)
+           xmemcpy(snew.buf, s->buf, s->len);
+       if (len)
+           xmemcpy(snew.buf + s->len, str, len);
        snew.buf[snew.len] = '\0';
        stringClean(s);
        *s = snew;
index 536f792d7ab7ba994167eea428e76e13c45d832a..4444e13d867296b9f323d81851f14976469eb3af 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: acl.cc,v 1.163 1998/05/08 22:58:38 wessels Exp $
+ * $Id: acl.cc,v 1.164 1998/05/11 18:44:31 rousskov Exp $
  *
  * DEBUG: section 28    Access Control
  * AUTHOR: Duane Wessels
@@ -1117,12 +1117,16 @@ static int
 aclMatchProxyAuth(acl_proxy_auth * p, aclCheck_t * checklist)
 {
     LOCAL_ARRAY(char, sent_user, ICP_IDENT_SZ);
-    char *s;
+    const char *s;
     char *cleartext;
     char *sent_auth;
     char *passwd = NULL;
     acl_proxy_auth_user *u;
+#if OLD_CODE
     s = mime_get_header(checklist->request->headers, "Proxy-authorization:");
+#else
+    s = httpHeaderGetStr(&checklist->request->header, HDR_PROXY_AUTHORIZATION);
+#endif
     if (s == NULL)
        return 0;
     if (strlen(s) < SKIP_BASIC_SZ)
@@ -1556,8 +1560,8 @@ aclCheck_t *
 aclChecklistCreate(const acl_access * A,
     request_t * request,
     struct in_addr src_addr,
-    char *user_agent,
-    char *ident)
+    const char *user_agent,
+    const char *ident)
 {
     int i;
     aclCheck_t *checklist = xcalloc(1, sizeof(aclCheck_t));;
index 187601f0277369fb49d487b357aa6776cdb3caea..dd5f844efd49a1118b914c1ef028b648e031b80e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: asn.cc,v 1.35 1998/05/09 16:49:00 wessels Exp $
+ * $Id: asn.cc,v 1.36 1998/05/11 18:44:32 rousskov Exp $
  *
  * DEBUG: section 53    AS Number handling
  * AUTHOR: Duane Wessels, Kostas Anagnostakis
@@ -185,8 +185,12 @@ asnCacheStart(int as)
     req = urlParse(METHOD_GET, asres);
     assert(NULL != req);
     asState->request = requestLink(req);
+#if OLD_CODE
     asState->request->headers = xstrdup("\r\n");
     asState->request->headers_sz = strlen(asState->request->headers);
+#else
+    httpRequestSetHeaders(asState->request, METHOD_GET, asres, "");
+#endif
     if ((e = storeGet(k)) == NULL) {
        e = storeCreateEntry(asres, asres, 0, METHOD_GET);
        storeClientListAdd(e, asState);
index ddbf07bcdf40ca501d1c4ec4d6883aad3d66a23b..5626a4d664da193d7fbde46e1e2465b5bcab2228 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: cache_manager.cc,v 1.11 1998/05/04 21:43:09 wessels Exp $
+ * $Id: cache_manager.cc,v 1.12 1998/05/11 18:44:32 rousskov Exp $
  *
  * DEBUG: section 16    Cache Manager Objects
  * AUTHOR: Duane Wessels
@@ -125,9 +125,10 @@ static void
 cachemgrParseHeaders(cachemgrStateData * mgr, const request_t * request)
 {
     const char *basic_cookie;  /* base 64 _decoded_ user:passwd pair */
-    const char *authField;
     const char *passwd_del;
     assert(mgr && request);
+#if OLD_CODE
+    const char *authField;
     /* this parsing will go away when hdrs are added to request_t @?@ */
     basic_cookie = mime_get_auth(request->headers, "Basic", &authField);
     debug(16, 9) ("cachemgrParseHeaders: got auth: '%s'\n", authField ? authField : "<none>");
@@ -137,8 +138,13 @@ cachemgrParseHeaders(cachemgrStateData * mgr, const request_t * request)
        debug(16, 1) ("cachemgrParseHeaders: unknown auth format in '%s'\n", authField);
        return;
     }
+#else
+    basic_cookie = httpHeaderGetAuth(&request->header, HDR_AUTHORIZATION, "Basic");
+    if (!basic_cookie)
+       return;
+#endif
     if (!(passwd_del = strchr(basic_cookie, ':'))) {
-       debug(16, 1) ("cachemgrParseHeaders: unknown basic_cookie '%s' format in '%s'\n", basic_cookie, authField);
+       debug(16, 1) ("cachemgrParseHeaders: unknown basic_cookie format '%s'\n", basic_cookie);
        return;
     }
     /* found user:password pair, reset old values */
index 6f22a25d5d5b73f515be181530c478911a5b4829..15bcc611e3d86e7cd3d93f8be77166aed54ce9fa 100644 (file)
@@ -1,7 +1,6 @@
 
-
 /*
- * $Id: client.cc,v 1.65 1998/04/24 07:09:29 wessels Exp $
+ * $Id: client.cc,v 1.66 1998/05/11 18:44:33 rousskov Exp $
  *
  * DEBUG: section 0     WWW Client
  * AUTHOR: Harvest Derived
@@ -141,7 +140,7 @@ usage(const char *progname)
        "    -t count     Trace count cache-hops\n"
        "    -g count     Ping mode, \"count\" iterations (0 to loop until interrupted).\n"
        "    -I interval  Ping interval in seconds (default 1 second).\n"
-       "    -H 'string'  Extra headers to send. Use quotes to protect new lines.\n",
+       "    -H 'string'  Extra headers to send. Use '\\n' for new lines.\n",
        progname, CACHE_HTTP_PORT);
     exit(1);
 }
@@ -288,9 +287,9 @@ main(int argc, char *argv[])
     }
     if (keep_alive) {
        if (port != 80)
-           snprintf(buf, BUFSIZ, "Proxy-Connection: Keep-Alive\r\n");
+           snprintf(buf, BUFSIZ, "Proxy-Connection: keep-alive\r\n");
        else
-           snprintf(buf, BUFSIZ, "Connection: Keep-Alive\r\n");
+           snprintf(buf, BUFSIZ, "Connection: keep-alive\r\n");
        strcat(msg, buf);
     }
     strcat(msg, extra_hdrs);
index b5aae24305f8bb9e5788880735bf43468a6b7bcf..2af0e2cfeacffa4e35596831931c8e642b7f31e0 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: client_side.cc,v 1.300 1998/05/09 04:49:09 wessels Exp $
+ * $Id: client_side.cc,v 1.301 1998/05/11 18:44:34 rousskov Exp $
  *
  * DEBUG: section 33    Client-side Routines
  * AUTHOR: Duane Wessels
@@ -54,6 +54,7 @@ static void checkFailureRatio(err_type, hier_code);
 static void clientProcessMiss(clientHttpRequest *);
 static void clientAppendReplyHeader(char *, const char *, size_t *, size_t);
 size_t clientBuildReplyHeader(clientHttpRequest *, char *, size_t, size_t *, char *, size_t);
+static clientHttpRequest *parseHttpRequestAbort(ConnStateData * conn, const char *uri);
 static clientHttpRequest *parseHttpRequest(ConnStateData *, method_t *, int *, char **, size_t *);
 static RH clientRedirectDone;
 static STCB clientHandleIMSReply;
@@ -62,7 +63,7 @@ static int checkAccelOnly(clientHttpRequest *);
 static int clientOnlyIfCached(clientHttpRequest * http);
 static STCB clientSendMoreData;
 static STCB clientCacheHit;
-static void clientParseRequestHeaders(clientHttpRequest *);
+static void clientInterpretRequestHeaders(clientHttpRequest *);
 static void clientProcessRequest(clientHttpRequest *);
 static void clientProcessExpired(void *data);
 static void clientProcessOnlyIfCachedMiss(clientHttpRequest * http);
@@ -92,7 +93,7 @@ clientAccessCheck(void *data)
 {
     clientHttpRequest *http = data;
     ConnStateData *conn = http->conn;
-    char *browser;
+    const char *browser;
     if (Config.onoff.ident_lookup && conn->ident.state == IDENT_NONE) {
        identStart(-1, conn, clientAccessCheck, http);
        return;
@@ -101,7 +102,11 @@ clientAccessCheck(void *data)
        clientAccessCheckDone(0, http);
        return;
     }
+#if OLD_CODE
     browser = mime_get_header(http->request->headers, "User-Agent");
+#else
+    browser = httpHeaderGetStr(&http->request->header, HDR_USER_AGENT);
+#endif
     http->acl_checklist = aclChecklistCreate(Config.accessList.http,
        http->request,
        conn->peer.sin_addr,
@@ -144,17 +149,12 @@ StoreEntry *
 clientCreateStoreEntry(clientHttpRequest * h, method_t m, int flags)
 {
     StoreEntry *e;
-    request_t *r;
     /*
      * For erroneous requests, we might not have a h->request,
      * so make a fake one.
      */
-    if (h->request == NULL) {
-       r = memAllocate(MEM_REQUEST_T);
-       r->method = m;
-       r->protocol = PROTO_NONE;
-       h->request = requestLink(r);
-    }
+    if (h->request == NULL)
+       h->request = requestLink(requestCreate(m, PROTO_NONE, NULL));
     e = storeCreateEntry(h->uri, h->log_uri, flags, m);
     storeClientListAdd(e, h);
     storeClientCopy(e, 0, 0, 4096, memAllocate(MEM_4K_BUF), clientSendMoreData, h);
@@ -225,8 +225,14 @@ clientRedirectDone(void *data, char *result)
        http->uri = xcalloc(l, 1);
        xstrncpy(http->uri, result, l);
        new_request->http_ver = old_request->http_ver;
+#if OLD_CODE
        new_request->headers = xstrdup(old_request->headers);
        new_request->headers_sz = old_request->headers_sz;
+#else
+       new_request->prefix = xstrdup(old_request->prefix);
+       new_request->prefix_sz = old_request->prefix_sz;
+       httpHeaderUpdate(&new_request->header, &old_request->header);
+#endif
        new_request->client_addr = old_request->client_addr;
        EBIT_SET(new_request->flags, REQ_REDIRECTED);
        if (old_request->body) {
@@ -238,7 +244,7 @@ clientRedirectDone(void *data, char *result)
        http->request = requestLink(new_request);
        urlCanonical(http->request, http->uri);
     }
-    clientParseRequestHeaders(http);
+    clientInterpretRequestHeaders(http);
     fd_note(http->conn->fd, http->uri);
     clientProcessRequest(http);
 }
@@ -450,6 +456,7 @@ modifiedSince(StoreEntry * entry, request_t * request)
     }
 }
 
+#if UNUSED_CODE
 char *
 clientConstructTraceEcho(clientHttpRequest * http)
 {
@@ -478,6 +485,7 @@ clientConstructTraceEcho(clientHttpRequest * http)
     http->http_code = HTTP_OK;
     return buf;
 }
+#endif /* UNUSED_CODE */
 
 void
 clientPurgeRequest(clientHttpRequest * http)
@@ -597,7 +605,8 @@ clientUpdateCounters(clientHttpRequest * http)
            inet_ntoa(http->request->client_addr), http->out.size);
     }
     /* @?@ split this ugly if-monster */
-    if (                       /* we used ICP or CD for peer selecton */
+    if (
+    /* we used ICP or CD for peer selecton */
        H->alg != PEER_SA_NONE &&
     /* a successful CD lookup was made */
        H->cd_lookup != LOOKUP_NONE &&
@@ -680,7 +689,7 @@ httpRequestFree(void *data)
        http->al.cache.ident = conn->ident.ident;
        if (request) {
            http->al.http.method = request->method;
-           http->al.headers.request = request->headers;
+           http->al.headers.request = request->prefix;
            http->al.hier = request->hier;
        }
        accessLogLog(&http->al);
@@ -745,61 +754,91 @@ connStateFree(int fd, void *data)
 }
 
 static void
-clientParseRequestHeaders(clientHttpRequest * http)
+clientInterpretRequestHeaders(clientHttpRequest * http)
 {
     request_t *request = http->request;
+#if OLD_CODE
     char *request_hdr = request->headers;
-    char *t = NULL;
+    const char *t = NULL;
+#else
+    const HttpHeader *req_hdr = &request->header;
+#if USE_USERAGENT_LOG
+    const char *str;
+#endif
+#endif
+#if OLD_CODE
     request->ims = -2;
     request->imslen = -1;
-    if ((t = mime_get_header(request_hdr, "If-Modified-Since"))) {
+    if ((t = httpHeaderGetStr(req_hdr, HDR_IF_MODIFIED_SINCE))) {
        EBIT_SET(request->flags, REQ_IMS);
        request->ims = parse_rfc1123(t);
+       /*
+        * "length=..." is not in the HTTP/1.1 specs. Any real proof that we
+        * should hornor it? Send complains to rousskov@nlanr.net
+        */
        while ((t = strchr(t, ';'))) {
            for (t++; isspace(*t); t++);
            if (strncasecmp(t, "length=", 7) == 0)
                request->imslen = atoi(t + 7);
        }
     }
-    if ((t = mime_get_header_field(request_hdr, "Pragma", "no-cache"))) {
-       EBIT_SET(request->flags, REQ_NOCACHE);
+#else
+    request->imslen = -1;
+    request->ims = httpHeaderGetTime(req_hdr, HDR_IF_MODIFIED_SINCE);
+    if (request->ims > 0)
+       EBIT_SET(request->flags, REQ_IMS);
+#endif
+    if (httpHeaderHas(req_hdr, HDR_PRAGMA)) {
+       String s = httpHeaderGetList(req_hdr, HDR_PRAGMA);
+       if (strListIsMember(&s, "no-cache", ','))
+           EBIT_SET(request->flags, REQ_NOCACHE);
+       stringClean(&s);
     }
-    if (mime_get_header(request_hdr, "Range")) {
-       EBIT_SET(request->flags, REQ_NOCACHE);
-       EBIT_SET(request->flags, REQ_RANGE);
-    } else if (mime_get_header(request_hdr, "Request-Range")) {
+    if (httpHeaderHas(req_hdr, HDR_RANGE)) {
        EBIT_SET(request->flags, REQ_NOCACHE);
        EBIT_SET(request->flags, REQ_RANGE);
+       /* Request-Range: deleted, not in the specs. Does it exist? */
     }
-    if (mime_get_header(request_hdr, "Authorization"))
+    if (httpHeaderHas(req_hdr, HDR_AUTHORIZATION))
        EBIT_SET(request->flags, REQ_AUTH);
     if (request->login[0] != '\0')
        EBIT_SET(request->flags, REQ_AUTH);
-    if ((t = mime_get_header(request_hdr, "Proxy-Connection"))) {
+#if OLD_CODE
+    if ((t =  httpHeaderGetStr(req_hdr, HDR_PROXY_CONNECTION))) {
        if (!strcasecmp(t, "Keep-Alive"))
            EBIT_SET(request->flags, REQ_PROXY_KEEPALIVE);
     }
-    if ((t = mime_get_header(request_hdr, "Via"))) {
-       if (strstr(t, ThisCache)) {
+#else
+    if (httpMsgIsPersistent(request->http_ver, req_hdr))
+       EBIT_SET(request->flags, REQ_PROXY_KEEPALIVE);
+#endif
+    if (httpHeaderHas(req_hdr, HDR_VIA)) {
+       String s = httpHeaderGetList(req_hdr, HDR_VIA);
+       if (strListIsMember(&s, ThisCache, ',')) {
            if (!http->flags.accel) {
                debug(33, 1) ("WARNING: Forwarding loop detected for '%s'\n",
                    http->uri);
-               debug(33, 1) ("--> %s\n", t);
+               debug(33, 1) ("--> %s\n", strBuf(s));
            }
            EBIT_SET(request->flags, REQ_LOOPDETECT);
        }
 #if FORW_VIA_DB
-       fvdbCountVia(t);
+       fvdbCountVia(strBuf(s));        
 #endif
+       stringClean(&s);
     }
 #if USE_USERAGENT_LOG
-    if ((t = mime_get_header(request_hdr, "User-Agent")))
-       logUserAgent(fqdnFromAddr(http->conn->peer.sin_addr), t);
+    if ((str = httpHeaderGetStr(req_hdr, HDR_USER_AGENT)))
+       logUserAgent(fqdnFromAddr(http->conn->peer.sin_addr), str);
 #endif
 #if FORW_VIA_DB
-    if ((t = mime_get_header(request_hdr, "X-Forwarded-For")))
-       fvdbCountForw(t);
+    if (httpHeaderHas(req_hdr, HDR_X_FORWARDED_FOR)) {
+       String s = httpHeaderGetList(req_hdr, HDR_X_FORWARDED_FOR);
+       fvdbCountForw(strBuf(s));
+       stringClean(&s);
+    }
 #endif
+#if OLD_CODE
     if ((t = mime_get_header_field(request_hdr, "Cache-control", "max-age="))) {
        request->max_age = atoi(t + 8);
     } else {
@@ -808,25 +847,33 @@ clientParseRequestHeaders(clientHttpRequest * http)
     if ((t = mime_get_header_field(request_hdr, "Cache-control", "only-if-cached"))) {
        EBIT_SET(request->flags, REQ_CC_ONLY_IF_CACHED);
     }
+#else
+    request->cache_control = httpHeaderGetCc(req_hdr);
+#endif
     if (request->method == METHOD_TRACE) {
+#if OLD_CODE
        if ((t = mime_get_header(request_hdr, "Max-Forwards")))
            request->max_forwards = atoi(t);
+#else
+       request->max_forwards = httpHeaderGetInt(req_hdr, HDR_MAX_FORWARDS);
+#endif
     }
     if (clientCachable(http))
        EBIT_SET(request->flags, REQ_CACHABLE);
     if (clientHierarchical(http))
        EBIT_SET(request->flags, REQ_HIERARCHICAL);
-    debug(33, 5) ("clientParseRequestHeaders: REQ_NOCACHE = %s\n",
+    debug(33, 5) ("clientInterpretRequestHeaders: REQ_NOCACHE = %s\n",
        EBIT_TEST(request->flags, REQ_NOCACHE) ? "SET" : "NOT SET");
-    debug(33, 5) ("clientParseRequestHeaders: REQ_CACHABLE = %s\n",
+    debug(33, 5) ("clientInterpretRequestHeaders: REQ_CACHABLE = %s\n",
        EBIT_TEST(request->flags, REQ_CACHABLE) ? "SET" : "NOT SET");
-    debug(33, 5) ("clientParseRequestHeaders: REQ_HIERARCHICAL = %s\n",
+    debug(33, 5) ("clientInterpretRequestHeaders: REQ_HIERARCHICAL = %s\n",
        EBIT_TEST(request->flags, REQ_HIERARCHICAL) ? "SET" : "NOT SET");
 }
 
 static int
 clientCheckContentLength(request_t * r)
 {
+#if OLD_CODE
     char *t;
     int len;
     /*
@@ -841,6 +888,11 @@ clientCheckContentLength(request_t * r)
     if (len < 0)
        return 0;
     return 1;
+#else
+    /* We only require a content-length for "upload" methods */
+    return !pumpMethod(r->method) || 
+       httpHeaderGetInt(&r->header, HDR_CONTENT_LENGTH) >= 0;
+#endif
 }
 
 static int
@@ -989,7 +1041,7 @@ clientBuildReplyHeader(clientHttpRequest * http,
            xmemmove(xbuf + 5, "1.0 ", 4);
 #if DONT_FILTER_THESE
        /*
-        * but you might want to if you run Squid as a HTTP accelerator
+        * but you might want to if you run Squid as an HTTP accelerator
         */
        if (strncasecmp(xbuf, "Accept-Ranges:", 14) == 0)
            continue;
@@ -1002,7 +1054,7 @@ clientBuildReplyHeader(clientHttpRequest * http,
            handleConnectionHeader(0, no_forward, &xbuf[11]);
            continue;
        }
-       if (strncasecmp(xbuf, "Keep-Alive:", 11) == 0)
+       if (strncasecmp(xbuf, "keep-alive:", 11) == 0)
            continue;
        if (strncasecmp(xbuf, "Set-Cookie:", 11) == 0)
            if (isTcpHit(http->log_type))
@@ -1024,7 +1076,7 @@ clientBuildReplyHeader(clientHttpRequest * http,
 #endif
     /* Append Proxy-Connection: */
     if (EBIT_TEST(http->request->flags, REQ_PROXY_KEEPALIVE)) {
-       snprintf(ybuf, 4096, "Proxy-Connection: Keep-Alive");
+       snprintf(ybuf, 4096, "Proxy-Connection: keep-alive");
        clientAppendReplyHeader(hdr_out, ybuf, &len, out_sz);
     }
     clientAppendReplyHeader(hdr_out, null_string, &len, out_sz);
@@ -1271,7 +1323,7 @@ clientWriteComplete(int fd, char *bufnotused, size_t size, int errflag, void *da
 
 /* called when clientGetHeadersFor*IMS completes */
 static void
-clientFinishIMS(clientHttpRequest * http)
+clientFinishIMS(clientHttpRequest *http)
 {
     StoreEntry *entry = http->entry;
     MemBuf mb;
@@ -1388,12 +1440,10 @@ clientGetHeadersForIMS(void *data, char *buf, ssize_t size)
 }
 
 /*
- * Client sent an IMS request for ENTRY_SPECIAL
- *   - fetch the headers
- *   - construct a 304 reply
- *   - if something goes wrong call clientCacheHit()
- *     to mimic our usual processing of special entries
- *   - note that clientGetHeadersForIMS frees "buf" earlier than we do
+ * client sent an IMS request for ENTRY_SPECIAL;
+ * mimic clientGetHeadersForIMS(), but call clientCacheHit()
+ *     if something goes wrong;
+ * note: clientGetHeadersForIMS frees "buf" earlier than we do
  */
 static void
 clientGetHeadersForSpecialIMS(void *data, char *buf, ssize_t size)
@@ -1434,9 +1484,9 @@ clientGetHeadersForSpecialIMS(void *data, char *buf, ssize_t size)
 }
 
 /*
- * client issued a request with an only-if-cached cache-control directive
+ * client issued a request with an only-if-cached cache-control directive;
  * we did not find a cached object that can be returned without
- *     contacting other servers
+ *     contacting other servers;
  * respond with a 504 (Gateway Timeout) as suggested in [RFC 2068]
  */
 static void
@@ -1447,7 +1497,6 @@ clientProcessOnlyIfCachedMiss(clientHttpRequest * http)
     ErrorState *err = NULL;
     debug(33, 4) ("clientProcessOnlyIfCachedMiss: '%s %s'\n",
        RequestMethodStr[r->method], url);
-    debug(33, 10) ("clientProcessMiss: request_hdr:\n%s\n", r->headers);
     http->al.http.code = HTTP_GATEWAY_TIMEOUT;
     err = errorCon(ERR_ONLY_IF_CACHED_MISS, HTTP_GATEWAY_TIMEOUT);
     err->request = requestLink(r);
@@ -1542,10 +1591,10 @@ clientProcessRequest(clientHttpRequest * http)
            storeBuffer(http->entry);
            rep = httpReplyCreate();
            httpReplySetHeaders(rep, 1.0, HTTP_OK, NULL, "text/plain",
-               r->headers_sz, 0, squid_curtime);
+               r->prefix_sz, 0, squid_curtime);
            httpReplySwapOut(rep, http->entry);
            httpReplyDestroy(rep);
-           storeAppend(http->entry, r->headers, r->headers_sz);
+           storeAppend(http->entry, r->prefix, r->prefix_sz);
            storeComplete(http->entry);
            return;
        }
@@ -1591,8 +1640,8 @@ clientProcessRequest(clientHttpRequest * http)
            http->out.offset,
            SM_PAGE_SIZE,
            memAllocate(MEM_4K_BUF),
-           (http->log_type == LOG_TCP_IMS_MISS) ?
-           clientGetHeadersForIMS : clientGetHeadersForSpecialIMS,
+           (http->log_type == LOG_TCP_IMS_MISS) ? 
+               clientGetHeadersForIMS : clientGetHeadersForSpecialIMS,
            http);
        break;
     case LOG_TCP_REFRESH_MISS:
@@ -1612,13 +1661,12 @@ clientProcessMiss(clientHttpRequest * http)
 {
     char *url = http->uri;
     request_t *r = http->request;
-    char *request_hdr = r->headers;
     aclCheck_t ch;
     int answer;
     ErrorState *err = NULL;
     debug(33, 4) ("clientProcessMiss: '%s %s'\n",
        RequestMethodStr[r->method], url);
-    debug(33, 10) ("clientProcessMiss: request_hdr:\n%s\n", request_hdr);
+    debug(33, 10) ("clientProcessMiss: prefix:\n%s\n", r->prefix);
     /*
      * We might have a left-over StoreEntry from a failed cache hit
      * or IMS request.
@@ -1630,9 +1678,6 @@ clientProcessMiss(clientHttpRequest * http)
        storeUnlockObject(http->entry);
        http->entry = NULL;
     }
-    /*
-     * Check if client tolerates misses
-     */
     if (clientOnlyIfCached(http)) {
        clientProcessOnlyIfCachedMiss(http);
        return;
@@ -1661,6 +1706,19 @@ clientProcessMiss(clientHttpRequest * http)
     protoDispatch(http->conn->fd, http->entry, r);
 }
 
+static clientHttpRequest *
+parseHttpRequestAbort(ConnStateData * conn, const char *uri)
+{
+    clientHttpRequest *http = xcalloc(1, sizeof(clientHttpRequest));
+    cbdataAdd(http, MEM_NONE);
+    http->conn = conn;
+    http->start = current_time;
+    http->req_sz = conn->in.offset;
+    http->uri = xstrdup(uri);
+    http->log_uri = xstrdup(uri);
+    return http;
+}
+
 /*
  *  parseHttpRequest()
  * 
@@ -1670,7 +1728,7 @@ clientProcessMiss(clientHttpRequest * http)
  */
 static clientHttpRequest *
 parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status,
-    char **headers_p, size_t * headers_sz_p)
+    char **prefix_p, size_t *req_line_sz_p)
 {
     char *inbuf = NULL;
     char *mstr = NULL;
@@ -1682,54 +1740,38 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status,
     char *end;
     int free_request = 0;
     size_t header_sz;          /* size of headers, not including first line */
-    size_t req_sz;             /* size of whole request */
+    size_t prefix_sz;          /* size of whole request (req-line + headers)*/
     size_t url_sz;
     method_t method;
     clientHttpRequest *http = NULL;
 
     /* Make sure a complete line has been received */
-    if (strchr(conn->in.buf, '\n') == NULL) {
+    if ((t = strchr(conn->in.buf, '\n')) == NULL) {
        debug(33, 5) ("Incomplete request line, waiting for more data\n");
        *status = 0;
        return NULL;
     }
+    *req_line_sz_p = t - conn->in.buf;
     /* Use xmalloc/xmemcpy instead of xstrdup because inbuf might
      * contain NULL bytes; especially for POST data  */
     inbuf = xmalloc(conn->in.offset + 1);
     xmemcpy(inbuf, conn->in.buf, conn->in.offset);
     *(inbuf + conn->in.offset) = '\0';
 
+    /* pre-set these values to make aborting simpler */
+    *prefix_p = inbuf;
+    *method_p = METHOD_NONE;
+    *status = -1;
+
     /* Look for request method */
     if ((mstr = strtok(inbuf, "\t ")) == NULL) {
        debug(33, 1) ("parseHttpRequest: Can't get request method\n");
-       http = xcalloc(1, sizeof(clientHttpRequest));
-       cbdataAdd(http, MEM_NONE);
-       http->conn = conn;
-       http->start = current_time;
-       http->req_sz = conn->in.offset;
-       http->uri = xstrdup("error:invalid-request-method");
-       http->log_uri = xstrdup("error:invalid-request-method");
-       *headers_sz_p = conn->in.offset;
-       *headers_p = inbuf;
-       *method_p = METHOD_NONE;
-       *status = -1;
-       return http;
+       return parseHttpRequestAbort(conn, "error:invalid-request-method");
     }
     method = urlParseMethod(mstr);
     if (method == METHOD_NONE) {
        debug(33, 1) ("parseHttpRequest: Unsupported method '%s'\n", mstr);
-       http = xcalloc(1, sizeof(clientHttpRequest));
-       cbdataAdd(http, MEM_NONE);
-       http->conn = conn;
-       http->start = current_time;
-       http->req_sz = conn->in.offset;
-       http->uri = xstrdup("error:unsupported-request-method");
-       http->log_uri = xstrdup("error:unsupported-request-method");
-       *headers_sz_p = conn->in.offset;
-       *headers_p = inbuf;
-       *method_p = METHOD_NONE;
-       *status = -1;
-       return http;
+       return parseHttpRequestAbort(conn, "error:unsupported-request-method");
     }
     debug(33, 5) ("parseHttpRequest: Method is '%s'\n", mstr);
     *method_p = method;
@@ -1737,17 +1779,7 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status,
     /* look for URL */
     if ((url = strtok(NULL, "\r\n\t ")) == NULL) {
        debug(33, 1) ("parseHttpRequest: Missing URL\n");
-       http = xcalloc(1, sizeof(clientHttpRequest));
-       cbdataAdd(http, MEM_NONE);
-       http->conn = conn;
-       http->start = current_time;
-       http->req_sz = conn->in.offset;
-       http->uri = xstrdup("error:missing-url");
-       http->log_uri = xstrdup("error:missing-url");
-       *headers_sz_p = conn->in.offset;
-       *headers_p = inbuf;
-       *status = -1;
-       return http;
+       return parseHttpRequestAbort(conn, "error:missing-url");
     }
     debug(33, 5) ("parseHttpRequest: Request is '%s'\n", url);
 
@@ -1758,20 +1790,11 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status,
 #if RELAXED_HTTP_PARSER
        http_ver = (float) 0.9; /* wild guess */
 #else
-       http = xcalloc(1, sizeof(clientHttpRequest));
-       cbdataAdd(http, MEM_NONE);
-       http->conn = conn;
-       http->start = current_time;
-       http->req_sz = conn->in.offset;
-       http->uri = xstrdup("error:missing-http-ident");
-       http->log_uri = xstrdup("error:missing-http-ident");
-       *headers_sz_p = conn->in.offset;
-       *headers_p = inbuf;
-       *status = -1;
-       return http;
+       return parseHttpRequestAbort(conn, "error:missing-http-ident");
 #endif
-    } else
+    } else {
        http_ver = (float) atof(token + 5);
+    }
 
     /* Check if headers are received */
     req_hdr = t;
@@ -1783,7 +1806,7 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status,
        return NULL;
     }
     /*
-     * Skip whitespace at the end of the frist line, up to the
+     * Skip whitespace at the end of the first line, up to the
      * first newline.
      */
     while (isspace(*req_hdr)) {
@@ -1795,9 +1818,19 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status,
     debug(33, 3) ("parseHttpRequest: req_hdr = {%s}\n", req_hdr);
     end = req_hdr + header_sz;
     debug(33, 3) ("parseHttpRequest: end = {%s}\n", end);
-    req_sz = end - inbuf;
-    debug(33, 3) ("parseHttpRequest: req_sz = %d\n", (int) req_sz);
-    assert(req_sz <= conn->in.offset);
+
+#if UNREACHABLE_CODE
+    if (end <= req_hdr) {
+       /* Invalid request */
+       debug(33, 3) ("parseHttpRequest: No request headers?\n");
+       return parseHttpRequestAbort(conn, "error:no-request-headers");
+    }
+#endif
+    prefix_sz = end - inbuf;
+    *req_line_sz_p = req_hdr - inbuf;
+    debug(33, 3) ("parseHttpRequest: prefix_sz = %d, req_line_sz = %d\n", 
+       (int) prefix_sz, (int) *req_line_sz_p);
+    assert(prefix_sz <= conn->in.offset);
 
     /* Ok, all headers are received */
     http = xcalloc(1, sizeof(clientHttpRequest));
@@ -1805,13 +1838,12 @@ parseHttpRequest(ConnStateData * conn, method_t * method_p, int *status,
     http->http_ver = http_ver;
     http->conn = conn;
     http->start = current_time;
-    http->req_sz = req_sz;
-    *headers_sz_p = header_sz;
-    *headers_p = xmalloc(header_sz + 1);
-    xmemcpy(*headers_p, req_hdr, header_sz);
-    *(*headers_p + header_sz) = '\0';
+    http->req_sz = prefix_sz;
+    *prefix_p = xmalloc(prefix_sz + 1);
+    xmemcpy(*prefix_p, conn->in.buf, prefix_sz);
+    *(*prefix_p + prefix_sz) = '\0';
 
-    debug(33, 5) ("parseHttpRequest: Request Header is\n%s\n", *headers_p);
+    debug(33, 5) ("parseHttpRequest: Request Header is\n%s\n", (*prefix_p)+*req_line_sz_p);
     /* Assign http->uri */
     if ((t = strchr(url, '\n')))       /* remove NL */
        *t = '\0';
@@ -1895,8 +1927,7 @@ clientReadRequest(int fd, void *data)
     method_t method;
     clientHttpRequest *http = NULL;
     clientHttpRequest **H = NULL;
-    char *headers;
-    size_t headers_sz;
+    char *prefix;
     ErrorState *err = NULL;
     fde *F = &fd_table[fd];
     int len = conn->in.size - conn->in.offset - 1;
@@ -1948,6 +1979,7 @@ clientReadRequest(int fd, void *data)
     conn->in.buf[conn->in.offset] = '\0';      /* Terminate the string */
     while (conn->in.offset > 0) {
        int nrequests;
+       int req_line_sz;
        /* Limit the number of concurrent requests to 2 */
        for (H = &conn->chr, nrequests = 0; *H; H = &(*H)->next, nrequests++);
        if (nrequests >= 2) {
@@ -1960,8 +1992,8 @@ clientReadRequest(int fd, void *data)
        http = parseHttpRequest(conn,
            &method,
            &parser_return_code,
-           &headers,
-           &headers_sz);
+           &prefix,
+           &req_line_sz);
        if (http) {
            assert(http->req_sz > 0);
            conn->in.offset -= http->req_sz;
@@ -1993,8 +2025,15 @@ clientReadRequest(int fd, void *data)
                http->al.http.code = err->http_status;
                http->entry = clientCreateStoreEntry(http, method, 0);
                errorAppendEntry(http->entry, err);
-               safe_free(headers);
+               safe_free(prefix);
                break;
+           } else {
+               /* compile headers */
+               /* we should skip request line! */
+               if (!httpRequestParseHeader(request, prefix+req_line_sz))
+                   debug(33, 1) ("Failed to parse request headers: %s\n%s\n",
+                       http->uri, prefix);
+               /* continue anyway? */
            }
            if (!http->flags.internal)
                if (internalCheck(strBuf(request->urlpath)))
@@ -2005,8 +2044,8 @@ clientReadRequest(int fd, void *data)
            http->log_uri = xstrdup(urlCanonicalClean(request));
            request->client_addr = conn->peer.sin_addr;
            request->http_ver = http->http_ver;
-           request->headers = headers;
-           request->headers_sz = headers_sz;
+           request->prefix = prefix;
+           request->prefix_sz = http->req_sz;
            if (!urlCheckRequest(request)) {
                err = errorCon(ERR_UNSUP_REQ, HTTP_NOT_IMPLEMENTED);
                err->src_addr = conn->peer.sin_addr;
index 7497d9c47ac65259fd4074ed8fe8f14bcf705709..1f968e032d3b3e196b95888000c27f088bb080dc 100644 (file)
 
 /* iteration for HttpHdrRange */
 #define HttpHdrRangeInitPos (-1)
+
+/* use this and only this to initialize HttpHeaderPos */
+#define HttpHeaderInitPos (-1)
+
+/* handy to determine the #elements in a static array */
+#define countof(arr) (sizeof(arr)/sizeof(*arr))
index 90e2b9c3dca8fa3936ccf70e5305c32414777679..a667cf867d922816327047e14405a1dc1c1eb2ef 100644 (file)
@@ -191,9 +191,12 @@ typedef enum {
     HDR_ACCEPT_LANGUAGE,
     HDR_ACCEPT_RANGES,
     HDR_AGE,
+    HDR_ALLOW,
+    HDR_AUTHORIZATION,
     HDR_CACHE_CONTROL,
     HDR_CONNECTION,
     HDR_CONTENT_ENCODING,
+    HDR_CONTENT_LANGUAGE,
     HDR_CONTENT_LENGTH,
     HDR_CONTENT_MD5,
     HDR_CONTENT_RANGE,
@@ -201,24 +204,33 @@ typedef enum {
     HDR_DATE,
     HDR_ETAG,
     HDR_EXPIRES,
+    HDR_FROM,
     HDR_HOST,
-    HDR_IMS,
+    HDR_IF_MODIFIED_SINCE,
     HDR_LAST_MODIFIED,
+    HDR_LINK,
     HDR_LOCATION,
     HDR_MAX_FORWARDS,
     HDR_MIME_VERSION,
+    HDR_PRAGMA,
     HDR_PROXY_AUTHENTICATE,
+    HDR_PROXY_AUTHORIZATION,
+    HDR_PROXY_CONNECTION,
     HDR_PUBLIC,
     HDR_RANGE,
+    HDR_REFERER,
     HDR_RETRY_AFTER,
     HDR_SERVER,
     HDR_SET_COOKIE,
+    HDR_TITLE,
     HDR_UPGRADE,
+    HDR_USER_AGENT,
+    HDR_VIA,
     HDR_WARNING,
     HDR_WWW_AUTHENTICATE,
     HDR_X_CACHE,
     HDR_X_CACHE_LOOKUP,                /* tmp hack, remove later */
-    HDR_PROXY_CONNECTION,
+    HDR_X_FORWARDED_FOR,
     HDR_OTHER,
     HDR_ENUM_END
 } http_hdr_type;
index c413b8c8fcae6a4009e39d63db05f9bbbddfdebb..1c808b3b1b50129aa3fb381bfb18ad8364ef9512 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: ftp.cc,v 1.223 1998/05/04 17:13:35 wessels Exp $
+ * $Id: ftp.cc,v 1.224 1998/05/11 18:44:37 rousskov Exp $
  *
  * DEBUG: section 9     File Transfer Protocol (FTP)
  * AUTHOR: Harvest Derived
@@ -854,7 +854,7 @@ ftpDataRead(int fd, void *data)
  * Return 0 if something is missing.
  */
 static int
-ftpCheckAuth(FtpStateData * ftpState, char *req_hdr)
+ftpCheckAuth(FtpStateData * ftpState, const HttpHeader *req_hdr)
 {
     char *orig_user;
     const char *auth;
@@ -866,7 +866,11 @@ ftpCheckAuth(FtpStateData * ftpState, char *req_hdr)
     if (ftpState->password[0])
        return 1;               /* passwd with no name? */
     /* URL has name, but no passwd */
+#if OLD_CODE
     if (!(auth = mime_get_auth(req_hdr, "Basic", NULL)))
+#else
+    if (!(auth = httpHeaderGetAuth(req_hdr, HDR_AUTHORIZATION, "Basic")))
+#endif
        return 0;               /* need auth header */
     orig_user = xstrdup(ftpState->user);
     ftpLoginParser(auth, ftpState);
@@ -955,7 +959,7 @@ ftpStart(request_t * request, StoreEntry * entry)
     EBIT_SET(ftpState->flags, FTP_REST_SUPPORTED);
     if (ftpState->request->method == METHOD_PUT)
        EBIT_SET(ftpState->flags, FTP_PUT);
-    if (!ftpCheckAuth(ftpState, request->headers)) {
+    if (!ftpCheckAuth(ftpState, &request->header)) {
        /* This request is not fully authenticated */
        if (request->port == 21) {
            snprintf(realm, 8192, "ftp %s", ftpState->user);
index 334c82a425a8b01c8e25c742971bbb1e0a62c6da..fd4dd0877f5d7fbe036a5f7677d78e156c722d64 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: http.cc,v 1.269 1998/05/09 04:49:10 wessels Exp $
+ * $Id: http.cc,v 1.270 1998/05/11 18:44:38 rousskov Exp $
  *
  * DEBUG: section 11    Hypertext Transfer Protocol (HTTP)
  * AUTHOR: Harvest Derived
@@ -131,7 +131,9 @@ static PF httpReadReply;
 static PF httpSendRequest;
 static PF httpStateFree;
 static PF httpTimeout;
+#if OLD_CODE
 static void httpAppendRequestHeader(char *hdr, const char *line, size_t * sz, size_t max, int);
+#endif
 static void httpCacheNegatively(StoreEntry *);
 static void httpMakePrivate(StoreEntry *);
 static void httpMakePublic(StoreEntry *);
@@ -381,7 +383,7 @@ httpPconnTransferDone(HttpStateData * httpState)
     HttpReply *reply = mem->reply;
     debug(11, 3) ("httpPconnTransferDone: FD %d\n", httpState->fd);
     /*
-     * If we didn't send a Keepalive request header, then this
+     * If we didn't send a keep-alive request header, then this
      * can not be a persistent connection.
      */
     if (!EBIT_TEST(httpState->flags, HTTP_KEEPALIVE))
@@ -569,6 +571,7 @@ httpSendComplete(int fd, char *bufnotused, size_t size, int errflag, void *data)
     }
 }
 
+#if OLD_CODE
 static void
 httpAppendRequestHeader(char *hdr, const char *line, size_t * sz, size_t max, int check)
 {
@@ -590,155 +593,164 @@ httpAppendRequestHeader(char *hdr, const char *line, size_t * sz, size_t max, in
     strcat(hdr + (*sz), crlf);
     *sz = n;
 }
+#endif
 
-#define YBUF_SZ (MAX_URL+32)
-size_t
+/*
+ * build request headers and append them to a given MemBuf 
+ * used by httpBuildRequestPrefix()
+ * note: calls httpHeaderInit(), the caller is responsible for Clean()-ing
+ */
+static void
 httpBuildRequestHeader(request_t * request,
     request_t * orig_request,
     StoreEntry * entry,
-    size_t * in_len,
-    char *hdr_out,
-    size_t out_sz,
+    HttpHeader *hdr_out,
     int cfd,
     int flags)
 {
-    LOCAL_ARRAY(char, ybuf, YBUF_SZ);
-    LOCAL_ARRAY(char, no_forward, 1024);
-    char *xbuf = memAllocate(MEM_4K_BUF);
-    char *viabuf = memAllocate(MEM_4K_BUF);
-    char *fwdbuf = memAllocate(MEM_4K_BUF);
-    char *t = NULL;
-    char *s = NULL;
-    char *end = NULL;
-    size_t len = 0;
-    size_t hdr_len = 0;
-    size_t l;
-    int hdr_flags = 0;
-    int cc_flags = 0;
-    int n;
-    const char *url = NULL;
-    char *hdr_in;
-
-    assert(orig_request->headers != NULL);
-    hdr_in = orig_request->headers;
-    debug(11, 3) ("httpBuildRequestHeader: INPUT:\n%s\n", hdr_in);
-    xstrncpy(fwdbuf, "X-Forwarded-For: ", 4096);
-    xstrncpy(viabuf, "Via: ", 4096);
-    snprintf(ybuf, YBUF_SZ, "%s %s HTTP/1.0",
-       RequestMethodStr[request->method],
-       strLen(request->urlpath) ? strBuf(request->urlpath) : "/");
-    httpAppendRequestHeader(hdr_out, ybuf, &len, out_sz, 1);
-    /* Add IMS header */
-    if (entry && entry->lastmod && request->method == METHOD_GET) {
-       snprintf(ybuf, YBUF_SZ, "If-Modified-Since: %s", mkrfc1123(entry->lastmod));
-       httpAppendRequestHeader(hdr_out, ybuf, &len, out_sz, 1);
-       EBIT_SET(hdr_flags, HDR_IMS);
-    }
-    assert(orig_request->headers_sz > 0);
-    end = orig_request->headers + orig_request->headers_sz;
-    for (t = hdr_in; t < end; t += strcspn(t, crlf), t += strspn(t, crlf)) {
-       hdr_len = t - hdr_in;
-       l = strcspn(t, crlf) + 1;
-       if (l > 4096)
-           l = 4096;
-       /* We might find a NULL before 'end' */
-       if (1 == l)
-           break;
-       xstrncpy(xbuf, t, l);
-       debug(11, 5) ("httpBuildRequestHeader: %s\n", xbuf);
-       if (strncasecmp(xbuf, "Proxy-Connection:", 17) == 0)
+    /* building buffer for complex strings */
+    #define BBUF_SZ (MAX_URL+32)
+    LOCAL_ARRAY(char, bbuf, BBUF_SZ);
+    String strConnection = StringNull;
+    const HttpHeader *hdr_in = &orig_request->header;
+    const HttpHeaderEntry *e;
+    HttpHeaderPos pos = HttpHeaderInitPos;
+
+    assert(orig_request->prefix != NULL);
+    debug(11, 3) ("httpBuildRequestHeader:\n%s", orig_request->prefix);
+    httpHeaderInit(hdr_out);
+    
+    /* append our IMS header */
+    if (entry && entry->lastmod && request->method == METHOD_GET)
+       httpHeaderPutTime(hdr_out, HDR_IF_MODIFIED_SINCE, entry->lastmod);
+
+    strConnection = httpHeaderGetList(hdr_in, HDR_CONNECTION);
+    while ((e = httpHeaderGetEntry(hdr_in, &pos))) {
+       debug(11, 5) ("httpBuildRequestHeader: %s: %s\n",
+           strBuf(e->name), strBuf(e->value));
+       if (!httpRequestHdrAllowed(e, &strConnection))
            continue;
-       if (strncasecmp(xbuf, "Proxy-authorization:", 20) == 0)
+       switch (e->id) {
+       case HDR_PROXY_AUTHORIZATION:
            /* If we're not going to do proxy auth, then it must be passed on */
-           if (EBIT_TEST(request->flags, REQ_USED_PROXY_AUTH))
-               continue;
-       if (strncasecmp(xbuf, "Connection:", 11) == 0) {
-           handleConnectionHeader(0, no_forward, &xbuf[11]);
-           continue;
-       }
-       if (strncasecmp(xbuf, "Host:", 5) == 0) {
+           if (!EBIT_TEST(request->flags, REQ_USED_PROXY_AUTH))
+               httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
+           break;
+       case HDR_HOST:
            /* Don't use client's Host: header for redirected requests */
-           if (EBIT_TEST(request->flags, REQ_REDIRECTED))
-               continue;
-           EBIT_SET(hdr_flags, HDR_HOST);
-       } else if (strncasecmp(xbuf, "Cache-Control:", 14) == 0) {
-           for (s = xbuf + 14; *s && isspace(*s); s++);
-           if (strncasecmp(s, "Max-age=", 8) == 0)
-               EBIT_SET(cc_flags, CCC_MAXAGE);
-       } else if (strncasecmp(xbuf, "Via:", 4) == 0) {
-           for (s = xbuf + 4; *s && isspace(*s); s++);
-           if ((int) strlen(viabuf) + (int) strlen(s) < 4000)
-               strcat(viabuf, s);
-           strcat(viabuf, ", ");
-           continue;
-       } else if (strncasecmp(xbuf, "X-Forwarded-For:", 16) == 0) {
-           for (s = xbuf + 16; *s && isspace(*s); s++);
-           if ((int) strlen(fwdbuf) + (int) strlen(s) < 4000)
-               strcat(fwdbuf, s);
-           strcat(fwdbuf, ", ");
-           continue;
-       } else if (strncasecmp(xbuf, "If-Modified-Since:", 18) == 0) {
-           if (EBIT_TEST(hdr_flags, HDR_IMS))
-               continue;
-       } else if (strncasecmp(xbuf, "Max-Forwards:", 13) == 0) {
+           if (!EBIT_TEST(request->flags, REQ_REDIRECTED))
+               httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
+           break;
+       case HDR_IF_MODIFIED_SINCE:
+           /* append unless we added our own;
+            * note: at most one client's ims header can pass through */
+           if (!httpHeaderHas(hdr_out, HDR_IF_MODIFIED_SINCE))
+               httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
+           break;
+       case HDR_MAX_FORWARDS:
            if (orig_request->method == METHOD_TRACE) {
-               for (s = xbuf + 13; *s && isspace(*s); s++);
-               n = atoi(s);
-               snprintf(xbuf, 4096, "Max-Forwards: %d", n - 1);
+               /* sacrificing efficiency over clarity, etc. */
+               const int hops = httpHeaderGetInt(hdr_in, HDR_MAX_FORWARDS);
+               if (hops > 0)
+                   httpHeaderPutInt(hdr_out, HDR_MAX_FORWARDS, hops-1);
            }
+           break;
+       case HDR_PROXY_CONNECTION:
+       case HDR_CONNECTION:
+       case HDR_VIA:
+       case HDR_X_FORWARDED_FOR:
+       case HDR_CACHE_CONTROL:
+           /* append these after the loop if needed */
+           break;
+       default:
+           /* pass on all other header fields */
+           httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
        }
-       if (!handleConnectionHeader(1, no_forward, xbuf))
-           httpAppendRequestHeader(hdr_out, xbuf, &len, out_sz - 512, 1);
     }
-    hdr_len = t - hdr_in;
-    if (Config.fake_ua && strstr(hdr_out, "User-Agent") == NULL) {
-       snprintf(ybuf, YBUF_SZ, "User-Agent: %s", Config.fake_ua);
-       httpAppendRequestHeader(hdr_out, ybuf, &len, out_sz, 0);
+
+    /* append fake user agent if configured and 
+     * the real one is not supplied by the client */
+    if (Config.fake_ua && !httpHeaderHas(hdr_out, HDR_USER_AGENT))
+       httpHeaderPutStr(hdr_out, HDR_USER_AGENT, Config.fake_ua);
+
+    /* append Via */
+    {
+       String strVia = httpHeaderGetList(hdr_in, HDR_VIA);
+       snprintf(bbuf, BBUF_SZ, "%3.1f %s", orig_request->http_ver, ThisCache);
+       strListAdd(&strVia, bbuf, ',');
+       httpHeaderPutStr(hdr_out, HDR_VIA, strBuf(strVia));
+       stringClean(&strVia);
     }
-    /* Append Via: */
-    /* snprintf would fail here too */
-    snprintf(ybuf, YBUF_SZ, "%3.1f %s", orig_request->http_ver, ThisCache);
-    strcat(viabuf, ybuf);
-    httpAppendRequestHeader(hdr_out, viabuf, &len, out_sz, 1);
-    /* Append to X-Forwarded-For: */
-    strcat(fwdbuf, cfd < 0 ? "unknown" : fd_table[cfd].ipaddr);
-    httpAppendRequestHeader(hdr_out, fwdbuf, &len, out_sz, 1);
-    if (!EBIT_TEST(hdr_flags, HDR_HOST)) {
-       if (orig_request->port == urlDefaultPort(orig_request->protocol))
-           snprintf(ybuf, YBUF_SZ, "Host: %s", orig_request->host);
-       else
-           snprintf(ybuf, YBUF_SZ, "Host: %s:%d", orig_request->host,
-               orig_request->port);
-       httpAppendRequestHeader(hdr_out, ybuf, &len, out_sz, 1);
+    /* append X-Forwarded-For */
+    {
+       String strFwd = httpHeaderGetList(hdr_in, HDR_X_FORWARDED_FOR);
+       strListAdd(&strFwd, (cfd < 0 ? "unknown" : fd_table[cfd].ipaddr), ',');
+       httpHeaderPutStr(hdr_out, HDR_X_FORWARDED_FOR, strBuf(strFwd));
+       stringClean(&strFwd);
     }
-    if (!EBIT_TEST(cc_flags, CCC_MAXAGE)) {
-       url = entry ? storeUrl(entry) : urlCanonical(orig_request, NULL);
-       snprintf(ybuf, YBUF_SZ, "Cache-control: Max-age=%d", (int) getMaxAge(url));
-       httpAppendRequestHeader(hdr_out, ybuf, &len, out_sz, 1);
-       if (strLen(request->urlpath))
-           assert(strstr(url, strBuf(request->urlpath)));
+    /* append Host if not there already */
+    if (!httpHeaderHas(hdr_out, HDR_HOST)) {
+       /* use port# only if not default */
+       if (orig_request->port == urlDefaultPort(orig_request->protocol)) {
+           httpHeaderPutStr(hdr_out, HDR_HOST, orig_request->host);
+       } else {
+           snprintf(bbuf, BBUF_SZ, "%s:%d",
+               orig_request->host, (int) orig_request->port);
+           httpHeaderPutStr(hdr_out, HDR_HOST, bbuf);
+       }
     }
-    /* maybe append Connection: Keep-Alive */
+    /* append Cache-Control, add max-age if not there already */
+    {
+       HttpHdrCc *cc = httpHeaderGetCc(hdr_in);
+       if (!cc)
+           cc = httpHdrCcCreate();
+       if (!EBIT_TEST(cc->mask, CC_MAX_AGE)) {
+           const char *url = entry ? storeUrl(entry) : urlCanonical(orig_request, NULL);
+           httpHdrCcSetMaxAge(cc, getMaxAge(url));
+           if (strLen(request->urlpath))
+               assert(strstr(url, strBuf(request->urlpath)));
+       }
+       httpHeaderPutCc(hdr_out, cc);
+       httpHdrCcDestroy(cc);
+    }
+    /* maybe append Connection: keep-alive */
     if (EBIT_TEST(flags, HTTP_KEEPALIVE)) {
        if (EBIT_TEST(flags, HTTP_PROXYING)) {
-           snprintf(ybuf, YBUF_SZ, "Proxy-Connection: Keep-Alive");
+           httpHeaderPutStr(hdr_out, HDR_PROXY_CONNECTION, "keep-alive");
        } else {
-           snprintf(ybuf, YBUF_SZ, "Connection: Keep-Alive");
+           httpHeaderPutStr(hdr_out, HDR_CONNECTION, "keep-alive");
        }
-       httpAppendRequestHeader(hdr_out, ybuf, &len, out_sz, 1);
     }
-    httpAppendRequestHeader(hdr_out, null_string, &len, out_sz, 1);
-    memFree(MEM_4K_BUF, xbuf);
-    memFree(MEM_4K_BUF, viabuf);
-    memFree(MEM_4K_BUF, fwdbuf);
-    if (in_len)
-       *in_len = hdr_len;
-    if ((l = strlen(hdr_out)) != len) {
-       debug_trap("httpBuildRequestHeader: size mismatch");
-       len = l;
+    stringClean(&strConnection);
+}
+
+/* build request prefix and append it to a given MemBuf; 
+ * return the length of the prefix */
+size_t
+httpBuildRequestPrefix(request_t * request,
+    request_t * orig_request,
+    StoreEntry * entry,
+    MemBuf *mb,
+    int cfd,
+    int flags)
+{
+    const int offset = mb->size;
+    memBufPrintf(mb, "%s %s HTTP/1.0\r\n",
+       RequestMethodStr[request->method],
+       strLen(request->urlpath) ? strBuf(request->urlpath) : "/");
+    /* build and pack headers */
+    {
+       HttpHeader hdr;
+       Packer p;
+       httpBuildRequestHeader(request, orig_request, entry, &hdr, cfd, flags);
+       packerToMemInit(&p, mb);
+       httpHeaderPackInto(&hdr, &p);
+       httpHeaderClean(&hdr);
+       packerClean(&p);
     }
-    debug(11, 3) ("httpBuildRequestHeader: OUTPUT:\n%s\n", hdr_out);
-    return len;
+    /* append header terminator */
+    memBufAppend(mb, "\r\n", 2);
+    return mb->size - offset;
 }
 
 /* This will be called when connect completes. Write request. */
@@ -746,35 +758,20 @@ static void
 httpSendRequest(int fd, void *data)
 {
     HttpStateData *httpState = data;
-    char *buf = NULL;
-    int len = 0;
-    int buflen;
+    MemBuf mb;
     request_t *req = httpState->request;
-    int buftype = 0;
     StoreEntry *entry = httpState->entry;
     int cfd;
     peer *p = httpState->peer;
     CWCB *sendHeaderDone;
 
     debug(11, 5) ("httpSendRequest: FD %d: httpState %p.\n", fd, httpState);
-    buflen = strLen(req->urlpath);
-    if (req->headers)
-       buflen += req->headers_sz + 1;
-    buflen += 512;             /* lots of extra */
 
     if (pumpMethod(req->method))
        sendHeaderDone = httpSendRequestEntry;
     else
        sendHeaderDone = httpSendComplete;
 
-    if (buflen < DISK_PAGE_SIZE) {
-       buf = memAllocate(MEM_8K_BUF);
-       buftype = BUF_TYPE_8K;
-       buflen = DISK_PAGE_SIZE;
-    } else {
-       buf = xcalloc(buflen, 1);
-       buftype = BUF_TYPE_MALLOC;
-    }
     if (!opt_forwarded_for)
        cfd = -1;
     else if (entry->mem_obj == NULL)
@@ -785,7 +782,7 @@ httpSendRequest(int fd, void *data)
     if (p != NULL)
        EBIT_SET(httpState->flags, HTTP_PROXYING);
     /*
-     * Is Keepalive okay for all request methods?
+     * Is keep-alive okay for all request methods?
      */
     if (p == NULL)
        EBIT_SET(httpState->flags, HTTP_KEEPALIVE);
@@ -793,21 +790,15 @@ httpSendRequest(int fd, void *data)
        EBIT_SET(httpState->flags, HTTP_KEEPALIVE);
     else if ((double) p->stats.n_keepalives_recv / (double) p->stats.n_keepalives_sent > 0.50)
        EBIT_SET(httpState->flags, HTTP_KEEPALIVE);
-    len = httpBuildRequestHeader(req,
+    memBufDefInit(&mb);
+    httpBuildRequestPrefix(req,
        httpState->orig_request,
        entry,
-       NULL,
-       buf,
-       buflen,
+       &mb,
        cfd,
        httpState->flags);
-    debug(11, 6) ("httpSendRequest: FD %d:\n%s\n", fd, buf);
-    comm_write(fd,
-       buf,
-       len,
-       sendHeaderDone,
-       httpState,
-       buftype == BUF_TYPE_8K ? memFree8K : xfree);
+    debug(11, 6) ("httpSendRequest: FD %d:\n%s\n", fd, mb.buf);
+    comm_write_mbuf(fd, mb, sendHeaderDone, httpState);
 }
 
 static int
@@ -841,11 +832,10 @@ httpBuildState(int fd, StoreEntry * entry, request_t * orig_request, peer * e)
     httpState->entry = entry;
     httpState->fd = fd;
     if (e) {
-       request = memAllocate(MEM_REQUEST_T);
-       request->method = orig_request->method;
+       request = requestCreate(
+           orig_request->method, PROTO_NONE, storeUrl(entry));
        xstrncpy(request->host, e->host, SQUIDHOSTNAMELEN);
        request->port = e->http_port;
-       stringReset(&request->urlpath, storeUrl(entry));
        httpState->request = requestLink(request);
        httpState->peer = e;
        httpState->orig_request = requestLink(orig_request);
index 06cac899197bdd6d266d6c1c885fa4ca22ca84c1..d85e5f38322278663f8b144812c79b2d248b7cb1 100644 (file)
@@ -269,8 +269,12 @@ icpHandleIcpV2(int fd, struct sockaddr_in from, char *buf, int len)
        break;
     }
     if (icp_request) {
+#if OLD_CODE
        stringClean(&icp_request->urlpath);
        memFree(MEM_REQUEST_T, icp_request);
+#else
+       requestDestroy(icp_request);
+#endif
     }
 }
 
index 7c3b4ab2a3c6ba74c84db1531ac52cb963734078..3ee5eaf35ce9f49b2d2b3ac1a216d31373a44494 100644 (file)
@@ -111,7 +111,11 @@ icpHandleIcpV3(int fd, struct sockaddr_in from, char *buf, int len)
        break;
     }
     if (icp_request) {
+#if OLD_CODE
        stringClean(&icp_request->urlpath);
        memFree(MEM_REQUEST_T, icp_request);
+#else
+       requestDestroy(icp_request);
+#endif
     }
 }
index 79f823e271420d9e788e4346ad5c48ed6e8784aa..c813a051d4782e3fab1b8692a8021dd53bec93fd 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: main.cc,v 1.248 1998/04/25 07:07:40 wessels Exp $
+ * $Id: main.cc,v 1.249 1998/05/11 18:44:41 rousskov Exp $
  *
  * DEBUG: section 1     Startup and Main Loop
  * AUTHOR: Harvest Derived
@@ -465,6 +465,7 @@ mainInitialize(void)
     redirectOpenServers();
     useragentOpenLog();
     httpHeaderInitModule();    /* must go before any header processing (e.g. the one in errorInitialize) */
+    httpAnonInitModule();       /* must go before accepting requests */
     errorInitialize();
     accessLogInit();
 #ifdef SQUID_SNMP
index 260403d06159190ed55c7eab0c9f3b4875c66758..5876b4b2de91f34db9834bc19c045a0be4dc261a 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: neighbors.cc,v 1.205 1998/05/06 21:09:51 wessels Exp $
+ * $Id: neighbors.cc,v 1.206 1998/05/11 18:44:42 rousskov Exp $
  *
  * DEBUG: section 15    Neighbor Routines
  * AUTHOR: Harvest Derived
@@ -1190,7 +1190,7 @@ dump_peers(StoreEntry * sentry, peer * peers)
                storeAppendPrintf(sentry, "!%s ", d->domain);
        }
        storeAppendPrintf(sentry, "\n");
-       storeAppendPrintf(sentry, "Keep-Alive Ratio: %d%%\n",
+       storeAppendPrintf(sentry, "keep-alive ratio: %d%%\n",
            percent(e->stats.n_keepalives_recv, e->stats.n_keepalives_sent));
     }
 }
index 3040e882e6bec5eea9075378c2844cb297b07546..5bae8183f897374ee9db9b4cba22793d740965bc 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: net_db.cc,v 1.97 1998/05/10 03:03:12 wessels Exp $
+ * $Id: net_db.cc,v 1.98 1998/05/11 18:44:43 rousskov Exp $
  *
  * DEBUG: section 37    Network Measurement Database
  * AUTHOR: Duane Wessels
@@ -1050,8 +1050,12 @@ netdbExchangeStart(void *data)
     }
     requestLink(ex->r);
     assert(NULL != ex->r);
+#if OLD_CODE
     ex->r->headers = xstrdup("\r\n");
     ex->r->headers_sz = strlen(ex->r->headers);
+#else
+    httpRequestSetHeaders(ex->r, METHOD_GET, uri, "");
+#endif
     ex->e = storeCreateEntry(uri, uri, 0, METHOD_GET);
     ex->buf_sz = 4096;;
     ex->buf = memAllocate(MEM_4K_BUF);
index 7c61d8cbf3e34f0260de8763c4c23d2a18621d1e..5aacce30520167213362416e5cc0e35a35c369ba 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: peer_digest.cc,v 1.24 1998/05/09 04:49:11 wessels Exp $
+ * $Id: peer_digest.cc,v 1.25 1998/05/11 18:44:44 rousskov Exp $
  *
  * DEBUG: section 72    Peer Digest Routines
  * AUTHOR: Alex Rousskov
@@ -247,18 +247,15 @@ peerDigestRequest(peer * p)
     requestLink(req);
     assert(req);
     /* add custom headers */
-    /* rewrite this when requests get new header interface */
-    assert(!req->headers);
+    /* rewrite this when requests get rid of "prefix" */
+    assert(!req->prefix);
     {
        MemBuf mb;
        memBufDefInit(&mb);
        memBufPrintf(&mb, "Accept: %s,text/html\r\n", StoreDigestMimeStr);
        memBufPrintf(&mb, "Cache-control: only-if-cached\r\n");
-       memBufAppend(&mb, "\r\n", 2);
-       /* kludge! */
-       assert(memBufFreeFunc(&mb) == &xfree);
-       req->headers = mb.buf;
-       req->headers_sz = mb.size;
+       httpRequestSetHeaders(req, METHOD_GET, url, mb.buf);
+       memBufClean(&mb);
     }
     /* create fetch state structure */
     fetch = memAllocate(MEM_DIGEST_FETCH_STATE);
@@ -555,12 +552,12 @@ peerDigestFetchFinish(DigestFetchState * fetch, char *buf, const char *err_msg)
     }
     /* update global stats */
     /* note: outgoing numbers are not precise! @?@ */
-    kb_incr(&Counter.cd.kbytes_sent, req->headers_sz);
+    kb_incr(&Counter.cd.kbytes_sent, req->prefix_sz);
     kb_incr(&Counter.cd.kbytes_recv, (size_t) b_read);
     Counter.cd.msgs_sent++;
     Counter.cd.msgs_recv++;
     /* update peer stats */
-    kb_incr(&peer->digest.stats.kbytes_sent, req->headers_sz);
+    kb_incr(&peer->digest.stats.kbytes_sent, req->prefix_sz);
     kb_incr(&peer->digest.stats.kbytes_recv, (size_t) b_read);
     peer->digest.stats.msgs_sent++;
     peer->digest.stats.msgs_recv++;
index 0cfbce65b209b4f093db0b963419e838cdaf113a..2e661f298aefebfa032646a3f38bbdd819e2c28b 100644 (file)
@@ -14,8 +14,8 @@ extern void fvdbCountForw(const char *key);
 extern aclCheck_t *aclChecklistCreate(const struct _acl_access *,
     request_t *,
     struct in_addr src,
-    char *ua,
-    char *id);
+    const char *user_agent,
+    const char *ident);
 extern void aclNBCheck(aclCheck_t *, PF *, void *);
 extern int aclCheckFast(const struct _acl_access *A, aclCheck_t *);
 extern void aclChecklistFree(aclCheck_t *);
@@ -226,17 +226,15 @@ extern int httpCachable(method_t);
 extern void httpStart(request_t *, StoreEntry *, peer *);
 extern void httpParseReplyHeaders(const char *, http_reply *);
 extern void httpProcessReplyHeader(HttpStateData *, const char *, int);
-extern size_t httpBuildRequestHeader(request_t * request,
+extern size_t httpBuildRequestPrefix(request_t * request,
     request_t * orig_request,
     StoreEntry * entry,
-    size_t * in_len,
-    char *hdr_out,
-    size_t out_sz,
+    MemBuf *mb,
     int cfd,
     int flags);
-extern int httpAnonAllowed(const char *line);
-extern int httpAnonDenied(const char *line);
-extern void httpInit(void);
+extern void httpAnonInitModule();
+extern int httpAnonHdrAllowed(http_hdr_type hdr_id);
+extern int httpAnonHdrDenied(http_hdr_type hdr_id);
 
 /* Http Status Line */
 /* init/clean */
@@ -270,18 +268,19 @@ extern void httpBodyPackInto(const HttpBody * body, Packer * p);
 extern void httpHdrCcInitModule();
 extern void httpHdrCcCleanModule();
 extern HttpHdrCc *httpHdrCcCreate();
-extern HttpHdrCc *httpHdrCcParseCreate(const char *str);
+extern HttpHdrCc *httpHdrCcParseCreate(const String *str);
 extern void httpHdrCcDestroy(HttpHdrCc * cc);
 extern HttpHdrCc *httpHdrCcDup(const HttpHdrCc * cc);
 extern void httpHdrCcPackInto(const HttpHdrCc * cc, Packer * p);
 extern void httpHdrCcJoinWith(HttpHdrCc * cc, const HttpHdrCc * new_cc);
+extern void httpHdrCcSetMaxAge(HttpHdrCc * cc, int max_age);
 extern void httpHdrCcUpdateStats(const HttpHdrCc * cc, StatHist * hist);
 extern void httpHdrCcStatDumper(StoreEntry * sentry, int idx, double val, double size, int count);
 
 /* Http Range Header Field */
-extern HttpHdrRange *httpHdrRangeParseCreate(const char *range_spec);
+extern HttpHdrRange *httpHdrRangeParseCreate(const String *range_spec);
 /* returns true if ranges are valid; inits HttpHdrRange */
-extern int httpHdrRangeParseInit(HttpHdrRange * range, const char *range_spec);
+extern int httpHdrRangeParseInit(HttpHdrRange * range, const String *range_spec);
 extern void httpHdrRangeDestroy(HttpHdrRange * range);
 extern HttpHdrRange *httpHdrRangeDup(const HttpHdrRange * range);
 extern void httpHdrRangePackInto(const HttpHdrRange * range, Packer * p);
@@ -302,7 +301,10 @@ extern void httpHeaderDestroyFieldsInfo(HttpHeaderFieldInfo * info, int count);
 extern int httpHeaderIdByName(const char *name, int name_len, const HttpHeaderFieldInfo * attrs, int end);
 extern void httpHeaderMaskInit(HttpHeaderMask * mask);
 extern void httpHeaderCalcMask(HttpHeaderMask * mask, const int *enums, int count);
-extern int strListGetItem(const char *str, char del, const char **item, int *ilen, const char **pos);
+extern int httpHeaderHasConnDir(const HttpHeader *hdr, const char *directive);
+extern void strListAdd(String *str, const char *item, char del);
+extern int strListIsMember(const String *str, const char *item, char del);
+extern int strListGetItem(const String *str, char del, const char **item, int *ilen, const char **pos);
 extern const char *getStringPrefix(const char *str, const char *end);
 extern int httpHeaderParseInt(const char *start, int *val);
 extern int httpHeaderParseSize(const char *start, size_t * sz);
@@ -313,7 +315,7 @@ extern void httpHeaderCleanModule();
 /* init/clean */
 extern void httpHeaderInit(HttpHeader * hdr);
 extern void httpHeaderClean(HttpHeader * hdr);
-/* clone */
+/* update */
 extern void httpHeaderUpdate(HttpHeader * old, const HttpHeader * fresh);
 /* parse/pack */
 extern int httpHeaderParse(HttpHeader * hdr, const char *header_start, const char *header_end);
@@ -324,7 +326,8 @@ extern void httpHeaderPutInt(HttpHeader * hdr, http_hdr_type type, int number);
 extern void httpHeaderPutTime(HttpHeader * hdr, http_hdr_type type, time_t time);
 extern void httpHeaderPutStr(HttpHeader * hdr, http_hdr_type type, const char *str);
 extern void httpHeaderPutAuth(HttpHeader * hdr, const char *authScheme, const char *realm);
-extern void httpHeaderAddExt(HttpHeader * hdr, const char *name, const char *value);
+extern void httpHeaderPutCc(HttpHeader * hdr, const HttpHdrCc *cc);
+extern void httpHeaderPutExt(HttpHeader * hdr, const char *name, const char *value);
 extern int httpHeaderGetInt(const HttpHeader * hdr, http_hdr_type id);
 extern time_t httpHeaderGetTime(const HttpHeader * hdr, http_hdr_type id);
 extern HttpHdrCc *httpHeaderGetCc(const HttpHeader * hdr);
@@ -332,12 +335,22 @@ extern HttpHdrRange *httpHeaderGetRange(const HttpHeader * hdr);
 extern HttpHdrContRange *httpHeaderGetContRange(const HttpHeader * hdr);
 extern const char *httpHeaderGetStr(const HttpHeader * hdr, http_hdr_type id);
 extern const char *httpHeaderGetLastStr(const HttpHeader * hdr, http_hdr_type id);
+extern const char *httpHeaderGetAuth(const HttpHeader * hdr, http_hdr_type id, const char *authScheme);
+extern String httpHeaderGetList(const HttpHeader * hdr, http_hdr_type id);
 extern int httpHeaderDelByName(HttpHeader * hdr, const char *name);
+/* avoid using these low level routines */
+extern HttpHeaderEntry *httpHeaderGetEntry(const HttpHeader * hdr, HttpHeaderPos * pos);
 extern HttpHeaderEntry *httpHeaderFindEntry(const HttpHeader * hdr, http_hdr_type id);
+extern void httpHeaderAddEntry(HttpHeader * hdr, HttpHeaderEntry * e);
+extern HttpHeaderEntry *httpHeaderEntryClone(const HttpHeaderEntry * e);
 extern void httpHeaderEntryPackInto(const HttpHeaderEntry * e, Packer * p);
 /* store report about current header usage and other stats */
 extern void httpHeaderStoreReport(StoreEntry * e);
 
+/* Http Msg (currently in HttpReply.c @?@ ) */
+extern int httpMsgIsPersistent(float http_ver, const HttpHeader *hdr);
+extern int httpMsgIsolateHeaders(const char **parse_start, const char **blk_start, const char **blk_end);
+
 /* Http Reply */
 extern HttpReply *httpReplyCreate();
 extern void httpReplyInit(HttpReply * rep);
@@ -365,12 +378,20 @@ extern MemBuf httpPackedReply(double ver, http_status status, const char *ctype,
 extern MemBuf httpPacked304Reply(const HttpReply * rep);
 /* update when 304 reply is received for a cached object */
 extern void httpReplyUpdateOnNotModified(HttpReply * rep, HttpReply * freshRep);
-/* header manipulation, see HttpReply.c for caveats */
+/* header manipulation */
 extern int httpReplyContentLen(const HttpReply * rep);
 extern const char *httpReplyContentType(const HttpReply * rep);
 extern time_t httpReplyExpires(const HttpReply * rep);
 extern int httpReplyHasCc(const HttpReply * rep, http_hdr_cc_type type);
 
+/* Http Request */
+extern request_t *requestCreate(method_t, protocol_t, const char *urlpath);
+extern void requestDestroy(request_t *);
+extern request_t *requestLink(request_t *);
+extern void requestUnlink(request_t *);
+extern int httpRequestParseHeader(request_t *req, const char *parse_start);
+extern void httpRequestSetHeaders(request_t *, method_t, const char *uri, const char *header_str);
+extern int httpRequestHdrAllowed(const HttpHeaderEntry *e, String *strConnection);
 
 extern void icmpOpen(void);
 extern void icmpClose(void);
@@ -571,6 +592,7 @@ extern void statHistLogInit(StatHist * H, int capacity, double min, double max);
 extern void statHistEnumInit(StatHist * H, int last_enum);
 extern void statHistIntDumper(StoreEntry * sentry, int idx, double val, double size, int count);
 
+
 /* MemMeter */
 extern void memMeterSyncHWater(MemMeter * m);
 #define memMeterCheckHWater(m) { if ((m).hwater_level < (m).level) memMeterSyncHWater(&(m)); }
@@ -841,8 +863,8 @@ extern method_t urlParseMethod(const char *);
 extern void urlInitialize(void);
 extern request_t *urlParse(method_t, char *);
 extern char *urlCanonical(const request_t *, char *);
-extern request_t *requestLink(request_t *);
-extern void requestUnlink(request_t *);
+extern char *urlRInternal(const char *host, u_short port, const char *dir, const char *name);
+extern char *urlInternal(const char *dir, const char *name);
 extern int matchDomainName(const char *d, const char *h);
 extern int urlCheckRequest(const request_t *);
 extern int urlDefaultPort(protocol_t p);
@@ -893,6 +915,7 @@ void htcpSocketClose(void);
 #define strCmp(s,str)     strcmp(strBuf(s), (str))
 #define strNCmp(s,str,n)     strncmp(strBuf(s), (str), (n))
 #define strCaseCmp(s,str) strcasecmp(strBuf(s), (str))
+#define strNCaseCmp(s,str,n) strncasecmp(strBuf(s), (str), (n))
 #define strSet(s,ptr,ch) (s).buf[ptr-(s).buf] = (ch)
 #define strCut(s,pos) (s).buf[pos] = '\0'
 /* #define strCat(s,str)  stringAppend(&(s), (str), strlen(str)+1) */
index 0265a3bb1f54ecc3234ffe414d6afd4e4723ca1b..b58a008d0d7eb52003de60eb1f99ed91af96543f 100644 (file)
@@ -465,7 +465,7 @@ struct _hash_table {
 /* http status line */
 struct _HttpStatusLine {
     /* public, read only */
-    double version;
+    float version;
     const char *reason;                /* points to a _constant_ string (default or supplied), never free()d */
     http_status status;
 };
@@ -1095,8 +1095,20 @@ struct _request_t {
     int imslen;
     int max_forwards;
     struct in_addr client_addr;
+#if OLD_CODE
     char *headers;
     size_t headers_sz;
+#else
+#if TEST_STAGE_CODE
+    const char *prefix;
+    const size_t prefix_sz;
+    const HttpHeader header;
+#else
+    char *prefix;
+    size_t prefix_sz;
+    HttpHeader header;
+#endif
+#endif
     char *body;
     size_t body_sz;
     HierarchyLogEntry hier;
index b6b1ac6b524097d9b7802be33d01da479af87ce7..f5408fa5ce6f209cd4382a4ef346ea03181e7b2d 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: url.cc,v 1.91 1998/05/08 23:29:31 wessels Exp $
+ * $Id: url.cc,v 1.92 1998/05/11 18:44:47 rousskov Exp $
  *
  * DEBUG: section 23    URL Parsing
  * AUTHOR: Duane Wessels
@@ -271,30 +271,18 @@ urlParse(method_t method, char *url)
        return NULL;
     }
 #endif
-    request = memAllocate(MEM_REQUEST_T);
-    request->method = method;
-    request->protocol = protocol;
+    request = requestCreate(method, protocol, urlpath);
     xstrncpy(request->host, host, SQUIDHOSTNAMELEN);
     xstrncpy(request->login, login, MAX_LOGIN_SZ);
     request->port = (u_short) port;
-    stringReset(&request->urlpath, urlpath);
-    request->max_age = -1;
-    request->max_forwards = -1;
     return request;
 }
 
 static request_t *
 urnParse(method_t method, char *urn)
 {
-    request_t *request = NULL;
     debug(50, 5) ("urnParse: %s\n", urn);
-    request = memAllocate(MEM_REQUEST_T);
-    request->method = method;
-    request->protocol = PROTO_URN;
-    stringReset(&request->urlpath, urn + 4);
-    request->max_age = -1;
-    request->max_forwards = -1;
-    return request;
+    return requestCreate(method, PROTO_URN, urn + 4);
 }
 
 char *
@@ -365,6 +353,7 @@ urlCanonicalClean(const request_t * request)
     return buf;
 }
 
+#if OLD_CODE /* moved to HttpRequest.c */
 request_t *
 requestLink(request_t * request)
 {
@@ -380,11 +369,17 @@ requestUnlink(request_t * request)
     request->link_count--;
     if (request->link_count)
        return;
+#if OLD_CODE
     safe_free(request->headers);
+#else
+    httpHeaderClean(&request->header);
+    safe_free(request->prefix);
+#endif
     safe_free(request->body);
     stringClean(&request->urlpath);
     memFree(MEM_REQUEST_T, request);
 }
+#endif
 
 int
 matchDomainName(const char *domain, const char *host)
@@ -407,12 +402,14 @@ int
 urlCheckRequest(const request_t * r)
 {
     int rc = 0;
+    /* protocol "independent" methods */
     if (r->method == METHOD_CONNECT)
        return 1;
     if (r->method == METHOD_TRACE)
        return 1;
     if (r->method == METHOD_PURGE)
        return 1;
+    /* does method match the protocol? */
     switch (r->protocol) {
     case PROTO_URN:
     case PROTO_HTTP:
index 709ef3609de2030a505374ca3e18fcf4491be75e..64763ada872b57e18dca7f804a35a02c7949082c 100644 (file)
@@ -1,7 +1,7 @@
 
 /*
  *
- * $Id: urn.cc,v 1.32 1998/05/09 04:49:12 wessels Exp $
+ * $Id: urn.cc,v 1.33 1998/05/11 18:44:48 rousskov Exp $
  *
  * DEBUG: section 52    URN Parsing
  * AUTHOR: Kostas Anagnostakis
@@ -134,8 +134,12 @@ urnStart(request_t * r, StoreEntry * e)
        errorAppendEntry(e, err);
        return;
     }
+#if OLD_CODE
     urlres_r->headers = xstrdup("Accept: text/plain\r\n\r\n");
     urlres_r->headers_sz = strlen(urlres_r->headers);
+#else
+    httpRequestSetHeaders(urlres_r, METHOD_GET, urlres, "Accept: text/plain\r\n");
+#endif
     if ((urlres_e = storeGet(k)) == NULL) {
        urlres_e = storeCreateEntry(urlres, urlres, 0, METHOD_GET);
        storeClientListAdd(urlres_e, urnState);
index 8839e502e9eec0bc5f4633f3f8692894cfa64884..4d7cb3cf02ba3bb8c791064b914e30e158838717 100644 (file)
@@ -1,6 +1,6 @@
 
 /*
- * $Id: wais.cc,v 1.106 1998/03/31 05:37:55 wessels Exp $
+ * $Id: wais.cc,v 1.107 1998/05/11 18:44:48 rousskov Exp $
  *
  * DEBUG: section 24    WAIS Relay
  * AUTHOR: Harvest Derived
@@ -322,7 +322,7 @@ waisStart(request_t * request, StoreEntry * entry)
     waisState->method = method;
     waisState->relayhost = Config.Wais.relayHost;
     waisState->relayport = Config.Wais.relayPort;
-    waisState->request_hdr = request->headers;
+    waisState->request_hdr = request->prefix;
     waisState->fd = fd;
     waisState->entry = entry;
     xstrncpy(waisState->request, url, MAX_URL);