⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 httpheader.c

📁 -
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * $Id: HttpHeader.c,v 1.61.2.1 1999/02/12 19:38:18 wessels Exp $ * * DEBUG: section 55    HTTP Header * AUTHOR: Alex Rousskov * * 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.  Squid is Copyrighted (C) 1998 by *  Duane Wessels and the University of California San Diego.  Please *  see the COPYRIGHT file for full details.  Squid incorporates *  software developed and/or copyrighted by other sources.  Please see *  the CREDITS file for full details. * *  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., 59 Temple Place, Suite 330, Boston, MA 02111, USA. * */#include "squid.h"/* * On naming conventions: *  * HTTP/1.1 defines message-header as  *  * message-header = field-name ":" [ field-value ] CRLF * field-name     = token * field-value    = *( field-content | LWS ) *  * HTTP/1.1 does not give a name name a group of all message-headers in a message. * Squid 1.1 seems to refer to that group _plus_ start-line as "headers". *  * HttpHeader is an object that represents all message-headers in a message. * HttpHeader does not manage start-line. *  * HttpHeader is implemented as a collection of header "entries". * An entry is a (field_id, field_name, field_value) triplet. *//* * local constants and vars *//* * A table with major attributes for every known field.  * We calculate name lengths and reorganize this array on start up.  * After reorganization, field id can be used as an index to the table. */static const HttpHeaderFieldAttrs HeadersAttrs[] ={    {"Accept", HDR_ACCEPT, ftStr},    {"Accept-Charset", HDR_ACCEPT_CHARSET, ftStr},    {"Accept-Encoding", HDR_ACCEPT_ENCODING, ftStr},    {"Accept-Language", HDR_ACCEPT_LANGUAGE, ftStr},    {"Accept-Ranges", HDR_ACCEPT_RANGES, ftStr},    {"Age", HDR_AGE, ftInt},    {"Allow", HDR_ALLOW, ftStr},    {"Authorization", HDR_AUTHORIZATION, ftStr},	/* for now */    {"Cache-Control", HDR_CACHE_CONTROL, ftPCc},    {"Connection", HDR_CONNECTION, ftStr},    {"Content-Base", HDR_CONTENT_BASE, ftStr},    {"Content-Encoding", HDR_CONTENT_ENCODING, ftStr},    {"Content-Language", HDR_CONTENT_LANGUAGE, ftStr},    {"Content-Length", HDR_CONTENT_LENGTH, ftInt},    {"Content-Location", HDR_CONTENT_LOCATION, ftStr},    {"Content-MD5", HDR_CONTENT_MD5, ftStr},	/* for now */    {"Content-Range", HDR_CONTENT_RANGE, ftPContRange},    {"Content-Type", HDR_CONTENT_TYPE, ftStr},    {"Date", HDR_DATE, ftDate_1123},    {"ETag", HDR_ETAG, ftETag},    {"Expires", HDR_EXPIRES, ftDate_1123},    {"From", HDR_FROM, ftStr},    {"Host", HDR_HOST, ftStr},    {"If-Match", HDR_IF_MATCH, ftStr},	/* for now */    {"If-Modified-Since", HDR_IF_MODIFIED_SINCE, ftDate_1123},    {"If-None-Match", HDR_IF_NONE_MATCH, ftStr},	/* for now */    {"If-Range", HDR_IF_RANGE, ftDate_1123_or_ETag},    {"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},    {"Referer", HDR_REFERER, ftStr},    {"Request-Range", HDR_REQUEST_RANGE, ftPRange},	/* usually matches HDR_RANGE */    {"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},    {"Vary", HDR_VARY, ftStr},	/* for now */    {"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},    {"X-Request-URI", HDR_X_REQUEST_URI, ftStr},    {"X-Squid-Error", HDR_X_SQUID_ERROR, ftStr},    {"Other:", HDR_OTHER, ftStr}	/* ':' will not allow matches */};static HttpHeaderFieldInfo *Headers = NULL;/* * headers with field values defined as #(values) in HTTP/1.1 * Headers that are currently not recognized, are commented out. */static HttpHeaderMask ListHeadersMask;	/* set run-time using  ListHeadersArr */static http_hdr_type ListHeadersArr[] ={    HDR_ACCEPT,    HDR_ACCEPT_CHARSET, HDR_ACCEPT_ENCODING, HDR_ACCEPT_LANGUAGE,    HDR_ACCEPT_RANGES, HDR_ALLOW,    HDR_CACHE_CONTROL,    HDR_CONTENT_ENCODING,    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_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_BASE, HDR_CONTENT_ENCODING, HDR_CONTENT_LANGUAGE,    HDR_CONTENT_LENGTH, HDR_CONTENT_LOCATION, HDR_CONTENT_MD5,    HDR_CONTENT_RANGE, HDR_CONTENT_TYPE, 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_LOCATION, HDR_MAX_FORWARDS,    HDR_MIME_VERSION, HDR_PUBLIC, HDR_RETRY_AFTER, HDR_SERVER, HDR_SET_COOKIE,    HDR_VARY,    HDR_WARNING, HDR_PROXY_CONNECTION, HDR_X_CACHE,    HDR_X_CACHE_LOOKUP,    HDR_X_REQUEST_URI,    HDR_X_SQUID_ERROR};static HttpHeaderMask RequestHeadersMask;	/* set run-time using RequestHeaders */static http_hdr_type RequestHeadersArr[] ={    HDR_AUTHORIZATION, HDR_FROM, HDR_HOST,    HDR_IF_MATCH, HDR_IF_MODIFIED_SINCE, HDR_IF_NONE_MATCH,    HDR_IF_RANGE, HDR_MAX_FORWARDS, HDR_PROXY_CONNECTION,    HDR_PROXY_AUTHORIZATION, HDR_RANGE, HDR_REFERER, HDR_REQUEST_RANGE,    HDR_USER_AGENT, HDR_X_FORWARDED_FOR};/* header accounting */static HttpHeaderStat HttpHeaderStats[] ={    {"all"},#if USE_HTCP    {"HTCP reply"},#endif    {"request"},    {"reply"}};static int HttpHeaderStatCount = countof(HttpHeaderStats);static int HeaderEntryParsedCount = 0;/* * local routines */#define assert_eid(id) assert((id) >= 0 && (id) < HDR_ENUM_END)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 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);/* * Module initialization routines */voidhttpHeaderInitModule(){    int i;    /* check that we have enough space for masks */    assert(8 * sizeof(HttpHeaderMask) >= HDR_ENUM_END);    /* all headers must be described */    assert(countof(HeadersAttrs) == HDR_ENUM_END);    if (!Headers)	Headers = httpHeaderBuildFieldsInfo(HeadersAttrs, HDR_ENUM_END);    /* create masks */    httpHeaderMaskInit(&ListHeadersMask, 0);    httpHeaderCalcMask(&ListHeadersMask, (const int *) ListHeadersArr, countof(ListHeadersArr));    httpHeaderMaskInit(&ReplyHeadersMask, 0);    httpHeaderCalcMask(&ReplyHeadersMask, (const int *) ReplyHeadersArr, countof(ReplyHeadersArr));    httpHeaderCalcMask(&ReplyHeadersMask, (const int *) GeneralHeadersArr, countof(GeneralHeadersArr));    httpHeaderCalcMask(&ReplyHeadersMask, (const int *) EntityHeadersArr, countof(EntityHeadersArr));    httpHeaderMaskInit(&RequestHeadersMask, 0);    httpHeaderCalcMask(&RequestHeadersMask, (const int *) RequestHeadersArr, countof(RequestHeadersArr));    httpHeaderCalcMask(&RequestHeadersMask, (const int *) GeneralHeadersArr, countof(GeneralHeadersArr));    httpHeaderCalcMask(&RequestHeadersMask, (const int *) EntityHeadersArr, countof(EntityHeadersArr));    /* init header stats */    assert(HttpHeaderStatCount == hoReply + 1);    for (i = 0; i < HttpHeaderStatCount; i++)	httpHeaderStatInit(HttpHeaderStats + i, HttpHeaderStats[i].label);    HttpHeaderStats[hoRequest].owner_mask = &RequestHeadersMask;    HttpHeaderStats[hoReply].owner_mask = &ReplyHeadersMask;#if USE_HTCP    HttpHeaderStats[hoHtcpReply].owner_mask = &ReplyHeadersMask;#endif    /* init dependent modules */    httpHdrCcInitModule();    /* register with cache manager */    cachemgrRegister("http_headers",	"HTTP Header Statistics", httpHeaderStoreReport, 0, 1);}voidhttpHeaderCleanModule(){    httpHeaderDestroyFieldsInfo(Headers, HDR_ENUM_END);    Headers = NULL;    httpHdrCcCleanModule();}static voidhttpHeaderStatInit(HttpHeaderStat * hs, const char *label){    assert(hs);    assert(label);    memset(hs, 0, sizeof(HttpHeaderStat));    hs->label = label;    statHistEnumInit(&hs->hdrUCountDistr, 32);	/* not a real enum */    statHistEnumInit(&hs->fieldTypeDistr, HDR_ENUM_END);    statHistEnumInit(&hs->ccTypeDistr, CC_ENUM_END);}/* * HttpHeader Implementation */voidhttpHeaderInit(HttpHeader * hdr, http_hdr_owner_type owner){    assert(hdr);    assert(owner > hoNone && owner <= hoReply);    debug(55, 7) ("init-ing hdr: %p owner: %d\n", hdr, owner);    memset(hdr, 0, sizeof(*hdr));    hdr->owner = owner;    arrayInit(&hdr->entries);}voidhttpHeaderClean(HttpHeader * hdr){    HttpHeaderPos pos = HttpHeaderInitPos;    HttpHeaderEntry *e;    assert(hdr);    assert(hdr->owner > hoNone && hdr->owner <= hoReply);    debug(55, 7) ("cleaning hdr: %p owner: %d\n", hdr, hdr->owner);    statHistCount(&HttpHeaderStats[hdr->owner].hdrUCountDistr, hdr->entries.count);    HttpHeaderStats[hdr->owner].destroyedCount++;    HttpHeaderStats[hdr->owner].busyDestroyedCount += hdr->entries.count > 0;    while ((e = httpHeaderGetEntry(hdr, &pos))) {	/* tmp hack to try to avoid coredumps */	if (e->id < 0 || e->id >= HDR_ENUM_END) {	    debug(55, 0) ("httpHeaderClean BUG: entry[%d] is invalid (%d). Ignored.\n",		pos, e->id);	} else {	    statHistCount(&HttpHeaderStats[hdr->owner].fieldTypeDistr, e->id);	    /* yes, this destroy() leaves us in an incosistent state */	    httpHeaderEntryDestroy(e);	}    }    arrayClean(&hdr->entries);}/* append entries (also see httpHeaderUpdate) */voidhttpHeaderAppend(HttpHeader * dest, const HttpHeader * src){    const HttpHeaderEntry *e;    HttpHeaderPos pos = HttpHeaderInitPos;    assert(src && dest);    assert(src != dest);    debug(55, 7) ("appending hdr: %p += %p\n", dest, src);    while ((e = httpHeaderGetEntry(src, &pos))) {	httpHeaderAddEntry(dest, httpHeaderEntryClone(e));    }}/* use fresh entries to replace old ones */voidhttpHeaderUpdate(HttpHeader * old, const HttpHeader * fresh, const HttpHeaderMask * denied_mask){    const HttpHeaderEntry *e;    HttpHeaderPos pos = HttpHeaderInitPos;    assert(old && fresh);    assert(old != fresh);    debug(55, 7) ("updating hdr: %p <- %p\n", old, fresh);    while ((e = httpHeaderGetEntry(fresh, &pos))) {	/* deny bad guys (ok to check for HDR_OTHER) here */	if (denied_mask && CBIT_TEST(*denied_mask, e->id))	    continue;	httpHeaderDelByName(old, strBuf(e->name));	httpHeaderAddEntry(old, httpHeaderEntryClone(e));    }}/* just handy in parsing: resets and returns false */int

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -