- 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):
/*
- * $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
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);
}
/*
- * $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
static int CcParsedCount = 0;
/* local prototypes */
-static int httpHdrCcParseInit(HttpHdrCc * cc, const char *str);
+static int httpHdrCcParseInit(HttpHdrCc * cc, const String *str);
/* module initialization */
/* 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)) {
/* 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 */
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;
}
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++;
}
}
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)
{
/*
- * $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
}
HttpHdrRange *
-httpHdrRangeParseCreate(const char *str)
+httpHdrRangeParseCreate(const String *str)
{
HttpHdrRange *r = httpHdrRangeCreate();
if (!httpHdrRangeParseInit(r, 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);
*/
if (spec)
stackPush(&range->specs, spec);
+ count++;
}
debug(68, 8) ("parsed range range count: %d\n", range->specs.count);
return range->specs.count;
/*
- * $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
} HttpHeaderStat;
-/* use this and only this to initialize HttpHeaderPos */
-#define HttpHeaderInitPos (-1)
-
-
/*
* local constants and vars
*/
{"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},
{"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;
{
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 */
#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
*/
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);
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)
{
}
/* returns next valid entry */
-static HttpHeaderEntry *
+HttpHeaderEntry *
httpHeaderGetEntry(const HttpHeader * hdr, HttpHeaderPos * pos)
{
assert(hdr && pos);
return count;
}
-#if FUTURE_CODE
static int
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
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);
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;
}
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)
return value;
}
-/* sync httpHeaderGetLastStr */
+/* sync with httpHeaderGetLastStr */
const char *
httpHeaderGetStr(const HttpHeader * hdr, http_hdr_type id)
{
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);
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;
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
return e;
}
-static HttpHeaderEntry *
+HttpHeaderEntry *
httpHeaderEntryClone(const HttpHeaderEntry * e)
{
return httpHeaderEntryCreate(e->id, strBuf(e->name), strBuf(e->value));
/*
- * $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
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 */
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'
* 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);
else
(*pos)++;
} else {
- *pos = str;
+ *pos = strBuf(*str);
+ if (!*pos)
+ return 0;
}
/* skip leading ws (ltrim) */
/*
- * $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
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 *
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)
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);
return 1;
}
-
/* handy: resets and returns -1 */
static int
httpReplyParseError(HttpReply * rep)
}
/* 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");
*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;
}
--- /dev/null
+
+/*
+ * $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;
+}
+
#
# 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:
#
HttpHeaderTools.o \
HttpBody.o \
HttpReply.o \
+ HttpRequest.o \
icmp.o \
icp_v2.o \
icp_v3.o \
/*
- * $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
*/
/*
- * To-Do: uses memory pools for .buf recycling @?@
+ * To-Do: uses memory pools for .buf recycling @?@ @?@
*/
/*
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 */
/*
- * $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
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;
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;
/*
- * $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
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)
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));;
/*
- * $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
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);
/*
- * $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
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>");
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 */
-
/*
- * $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
" -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);
}
}
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);
/*
- * $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
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;
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);
{
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;
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,
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);
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) {
http->request = requestLink(new_request);
urlCanonical(http->request, http->uri);
}
- clientParseRequestHeaders(http);
+ clientInterpretRequestHeaders(http);
fd_note(http->conn->fd, http->uri);
clientProcessRequest(http);
}
}
}
+#if UNUSED_CODE
char *
clientConstructTraceEcho(clientHttpRequest * http)
{
http->http_code = HTTP_OK;
return buf;
}
+#endif /* UNUSED_CODE */
void
clientPurgeRequest(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 &&
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);
}
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 {
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;
/*
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
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;
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))
#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);
/* called when clientGetHeadersFor*IMS completes */
static void
-clientFinishIMS(clientHttpRequest * http)
+clientFinishIMS(clientHttpRequest *http)
{
StoreEntry *entry = http->entry;
MemBuf mb;
}
/*
- * 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)
}
/*
- * 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
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);
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;
}
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:
{
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.
storeUnlockObject(http->entry);
http->entry = NULL;
}
- /*
- * Check if client tolerates misses
- */
if (clientOnlyIfCached(http)) {
clientProcessOnlyIfCachedMiss(http);
return;
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()
*
*/
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;
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;
/* 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);
#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;
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)) {
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));
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';
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;
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) {
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;
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)))
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;
/* 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))
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,
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;
/*
- * $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
* 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;
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);
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);
/*
- * $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
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 *);
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))
}
}
+#if OLD_CODE
static void
httpAppendRequestHeader(char *hdr, const char *line, size_t * sz, size_t max, int check)
{
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. */
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)
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);
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
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);
break;
}
if (icp_request) {
+#if OLD_CODE
stringClean(&icp_request->urlpath);
memFree(MEM_REQUEST_T, icp_request);
+#else
+ requestDestroy(icp_request);
+#endif
}
}
break;
}
if (icp_request) {
+#if OLD_CODE
stringClean(&icp_request->urlpath);
memFree(MEM_REQUEST_T, icp_request);
+#else
+ requestDestroy(icp_request);
+#endif
}
}
/*
- * $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
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
/*
- * $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
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));
}
}
/*
- * $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
}
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);
/*
- * $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
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);
}
/* 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++;
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 *);
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 */
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);
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);
/* 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);
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);
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);
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);
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)); }
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);
#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) */
/* 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;
};
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;
/*
- * $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
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 *
return buf;
}
+#if OLD_CODE /* moved to HttpRequest.c */
request_t *
requestLink(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)
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:
/*
*
- * $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
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);
/*
- * $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
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);