http.c
上传用户:liugui
上传日期:2007-01-04
资源大小:822k
文件大小:31k
源码类别:

代理服务器

开发平台:

Unix_Linux

  1. /*
  2.  * $Id: http.c,v 1.346.2.1 1999/02/12 19:38:29 wessels Exp $
  3.  *
  4.  * DEBUG: section 11    Hypertext Transfer Protocol (HTTP)
  5.  * AUTHOR: Harvest Derived
  6.  *
  7.  * SQUID Internet Object Cache  http://squid.nlanr.net/Squid/
  8.  * ----------------------------------------------------------
  9.  *
  10.  *  Squid is the result of efforts by numerous individuals from the
  11.  *  Internet community.  Development is led by Duane Wessels of the
  12.  *  National Laboratory for Applied Network Research and funded by the
  13.  *  National Science Foundation.  Squid is Copyrighted (C) 1998 by
  14.  *  Duane Wessels and the University of California San Diego.  Please
  15.  *  see the COPYRIGHT file for full details.  Squid incorporates
  16.  *  software developed and/or copyrighted by other sources.  Please see
  17.  *  the CREDITS file for full details.
  18.  *
  19.  *  This program is free software; you can redistribute it and/or modify
  20.  *  it under the terms of the GNU General Public License as published by
  21.  *  the Free Software Foundation; either version 2 of the License, or
  22.  *  (at your option) any later version.
  23.  *  
  24.  *  This program is distributed in the hope that it will be useful,
  25.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  26.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  27.  *  GNU General Public License for more details.
  28.  *  
  29.  *  You should have received a copy of the GNU General Public License
  30.  *  along with this program; if not, write to the Free Software
  31.  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
  32.  *
  33.  */
  34. /*
  35.  * Anonymizing patch by lutz@as-node.jena.thur.de
  36.  * have a look into http-anon.c to get more informations.
  37.  */
  38. #include "squid.h"
  39. static const char *const crlf = "rn";
  40. static CNCB httpConnectDone;
  41. static CWCB httpSendComplete;
  42. static CWCB httpSendRequestEntry;
  43. static CWCB httpSendRequestEntryDone;
  44. static PF httpReadReply;
  45. static PF httpSendRequest;
  46. static PF httpStateFree;
  47. static PF httpTimeout;
  48. static void httpCacheNegatively(StoreEntry *);
  49. static void httpMakePrivate(StoreEntry *);
  50. static void httpMakePublic(StoreEntry *);
  51. static int httpCachableReply(HttpStateData *);
  52. static void httpMaybeRemovePublic(StoreEntry *, http_status);
  53. static void
  54. httpStateFree(int fd, void *data)
  55. {
  56.     HttpStateData *httpState = data;
  57. #if DELAY_POOLS
  58.     delayClearNoDelay(fd);
  59. #endif
  60.     if (httpState == NULL)
  61. return;
  62.     storeUnlockObject(httpState->entry);
  63.     if (httpState->reply_hdr) {
  64. memFree(httpState->reply_hdr, MEM_8K_BUF);
  65. httpState->reply_hdr = NULL;
  66.     }
  67.     requestUnlink(httpState->request);
  68.     requestUnlink(httpState->orig_request);
  69.     httpState->request = NULL;
  70.     httpState->orig_request = NULL;
  71.     cbdataFree(httpState);
  72. }
  73. int
  74. httpCachable(method_t method)
  75. {
  76.     /* GET and HEAD are cachable. Others are not. */
  77.     if (method != METHOD_GET && method != METHOD_HEAD)
  78. return 0;
  79.     /* else cachable */
  80.     return 1;
  81. }
  82. static void
  83. httpTimeout(int fd, void *data)
  84. {
  85.     HttpStateData *httpState = data;
  86.     StoreEntry *entry = httpState->entry;
  87.     debug(11, 4) ("httpTimeout: FD %d: '%s'n", fd, storeUrl(entry));
  88.     if (entry->store_status == STORE_PENDING) {
  89. if (entry->mem_obj->inmem_hi == 0) {
  90.     fwdFail(httpState->fwd,
  91. errorCon(ERR_READ_TIMEOUT, HTTP_GATEWAY_TIMEOUT));
  92. }
  93.     }
  94.     comm_close(fd);
  95. }
  96. /* This object can be cached for a long time */
  97. static void
  98. httpMakePublic(StoreEntry * entry)
  99. {
  100.     if (EBIT_TEST(entry->flags, ENTRY_CACHABLE))
  101. storeSetPublicKey(entry);
  102. }
  103. /* This object should never be cached at all */
  104. static void
  105. httpMakePrivate(StoreEntry * entry)
  106. {
  107.     storeExpireNow(entry);
  108.     storeReleaseRequest(entry); /* delete object when not used */
  109.     /* storeReleaseRequest clears ENTRY_CACHABLE flag */
  110. }
  111. /* This object may be negatively cached */
  112. static void
  113. httpCacheNegatively(StoreEntry * entry)
  114. {
  115.     storeNegativeCache(entry);
  116.     if (EBIT_TEST(entry->flags, ENTRY_CACHABLE))
  117. storeSetPublicKey(entry);
  118. }
  119. static void
  120. httpMaybeRemovePublic(StoreEntry * e, http_status status)
  121. {
  122.     int remove = 0;
  123.     StoreEntry *pe;
  124.     if (!EBIT_TEST(e->flags, KEY_PRIVATE))
  125. return;
  126.     switch (status) {
  127.     case HTTP_OK:
  128.     case HTTP_NON_AUTHORITATIVE_INFORMATION:
  129.     case HTTP_MULTIPLE_CHOICES:
  130.     case HTTP_MOVED_PERMANENTLY:
  131.     case HTTP_MOVED_TEMPORARILY:
  132.     case HTTP_FORBIDDEN:
  133.     case HTTP_NOT_FOUND:
  134.     case HTTP_METHOD_NOT_ALLOWED:
  135.     case HTTP_GONE:
  136. remove = 1;
  137. break;
  138. #if WORK_IN_PROGRESS
  139.     case HTTP_UNAUTHORIZED:
  140. remove = 1;
  141. break;
  142. #endif
  143.     default:
  144. remove = 0;
  145. break;
  146.     }
  147.     if (!remove)
  148. return;
  149.     assert(e->mem_obj);
  150.     if ((pe = storeGetPublic(e->mem_obj->url, e->mem_obj->method)) != NULL) {
  151. assert(e != pe);
  152. storeRelease(pe);
  153.     }
  154.     if (e->mem_obj->method == METHOD_GET) {
  155. /* A fresh GET should eject old HEAD objects */
  156. if ((pe = storeGetPublic(e->mem_obj->url, METHOD_HEAD)) != NULL) {
  157.     assert(e != pe);
  158.     storeRelease(pe);
  159. }
  160.     }
  161. }
  162. static int
  163. httpCachableReply(HttpStateData * httpState)
  164. {
  165.     HttpReply *rep = httpState->entry->mem_obj->reply;
  166.     HttpHeader *hdr = &rep->header;
  167.     const int cc_mask = (rep->cache_control) ? rep->cache_control->mask : 0;
  168.     const char *v;
  169.     if (EBIT_TEST(cc_mask, CC_PRIVATE))
  170. return 0;
  171.     if (EBIT_TEST(cc_mask, CC_NO_CACHE))
  172. return 0;
  173.     if (EBIT_TEST(cc_mask, CC_NO_STORE))
  174. return 0;
  175.     if (httpState->request->flags.auth) {
  176. /*
  177.  * Responses to requests with authorization may be cached
  178.  * only if a Cache-Control: public reply header is present.
  179.  * RFC 2068, sec 14.9.4
  180.  */
  181. if (!EBIT_TEST(cc_mask, CC_PUBLIC))
  182.     return 0;
  183.     }
  184.     /*
  185.      * We don't properly deal with Vary features yet, so we can't
  186.      * cache these
  187.      */
  188.     if (httpHeaderHas(hdr, HDR_VARY))
  189. return 0;
  190.     /* Pragma: no-cache in _replies_ is not documented in HTTP,
  191.      * but servers like "Active Imaging Webcast/2.0" sure do use it */
  192.     if (httpHeaderHas(hdr, HDR_PRAGMA)) {
  193. String s = httpHeaderGetList(hdr, HDR_PRAGMA);
  194. const int no_cache = strListIsMember(&s, "no-cache", ',');
  195. stringClean(&s);
  196. if (no_cache)
  197.     return 0;
  198.     }
  199.     /*
  200.      * The "multipart/x-mixed-replace" content type is used for
  201.      * continuous push replies.  These are generally dynamic and
  202.      * probably should not be cachable
  203.      */
  204.     if ((v = httpHeaderGetStr(hdr, HDR_CONTENT_TYPE)))
  205. if (!strncasecmp(v, "multipart/x-mixed-replace", 25))
  206.     return 0;
  207.     switch (httpState->entry->mem_obj->reply->sline.status) {
  208. /* Responses that are cacheable */
  209.     case HTTP_OK:
  210.     case HTTP_NON_AUTHORITATIVE_INFORMATION:
  211.     case HTTP_MULTIPLE_CHOICES:
  212.     case HTTP_MOVED_PERMANENTLY:
  213.     case HTTP_GONE:
  214. /*
  215.  * Don't cache objects that need to be refreshed on next request,
  216.  * unless we know how to refresh it.
  217.  */
  218. if (!refreshIsCachable(httpState->entry))
  219.     return 0;
  220. /* don't cache objects from peers w/o LMT, Date, or Expires */
  221. /* check that is it enough to check headers @?@ */
  222. if (rep->date > -1)
  223.     return 1;
  224. else if (rep->last_modified > -1)
  225.     return 1;
  226. else if (!httpState->peer)
  227.     return 1;
  228. /* @?@ (here and 302): invalid expires header compiles to squid_curtime */
  229. else if (rep->expires > -1)
  230.     return 1;
  231. else
  232.     return 0;
  233. /* NOTREACHED */
  234. break;
  235. /* Responses that only are cacheable if the server says so */
  236.     case HTTP_MOVED_TEMPORARILY:
  237. if (rep->expires > -1)
  238.     return 1;
  239. else
  240.     return 0;
  241. /* NOTREACHED */
  242. break;
  243. /* Errors can be negatively cached */
  244.     case HTTP_NO_CONTENT:
  245.     case HTTP_USE_PROXY:
  246.     case HTTP_BAD_REQUEST:
  247.     case HTTP_FORBIDDEN:
  248.     case HTTP_NOT_FOUND:
  249.     case HTTP_METHOD_NOT_ALLOWED:
  250.     case HTTP_REQUEST_URI_TOO_LARGE:
  251.     case HTTP_INTERNAL_SERVER_ERROR:
  252.     case HTTP_NOT_IMPLEMENTED:
  253.     case HTTP_BAD_GATEWAY:
  254.     case HTTP_SERVICE_UNAVAILABLE:
  255.     case HTTP_GATEWAY_TIMEOUT:
  256. return -1;
  257. /* NOTREACHED */
  258. break;
  259. /* Some responses can never be cached */
  260.     case HTTP_PARTIAL_CONTENT: /* Not yet supported */
  261.     case HTTP_SEE_OTHER:
  262.     case HTTP_NOT_MODIFIED:
  263.     case HTTP_UNAUTHORIZED:
  264.     case HTTP_PROXY_AUTHENTICATION_REQUIRED:
  265.     case HTTP_INVALID_HEADER: /* Squid header parsing error */
  266.     default: /* Unknown status code */
  267. return 0;
  268. /* NOTREACHED */
  269. break;
  270.     }
  271.     /* NOTREACHED */
  272. }
  273. /* rewrite this later using new interfaces @?@ */
  274. void
  275. httpProcessReplyHeader(HttpStateData * httpState, const char *buf, int size)
  276. {
  277.     char *t = NULL;
  278.     StoreEntry *entry = httpState->entry;
  279.     int room;
  280.     int hdr_len;
  281.     HttpReply *reply = entry->mem_obj->reply;
  282.     debug(11, 3) ("httpProcessReplyHeader: key '%s'n",
  283. storeKeyText(entry->key));
  284.     if (httpState->reply_hdr == NULL)
  285. httpState->reply_hdr = memAllocate(MEM_8K_BUF);
  286.     if (httpState->reply_hdr_state == 0) {
  287. hdr_len = strlen(httpState->reply_hdr);
  288. room = 8191 - hdr_len;
  289. strncat(httpState->reply_hdr, buf, room < size ? room : size);
  290. hdr_len += room < size ? room : size;
  291. if (hdr_len > 4 && strncmp(httpState->reply_hdr, "HTTP/", 5)) {
  292.     debug(11, 3) ("httpProcessReplyHeader: Non-HTTP-compliant header: '%s'n", httpState->reply_hdr);
  293.     httpState->reply_hdr_state += 2;
  294.     reply->sline.status = HTTP_INVALID_HEADER;
  295.     return;
  296. }
  297. t = httpState->reply_hdr + hdr_len;
  298. /* headers can be incomplete only if object still arriving */
  299. if (!httpState->eof) {
  300.     size_t k = headersEnd(httpState->reply_hdr, 8192);
  301.     if (0 == k)
  302. return; /* headers not complete */
  303.     t = httpState->reply_hdr + k;
  304. }
  305. *t = '';
  306. httpState->reply_hdr_state++;
  307.     }
  308.     if (httpState->reply_hdr_state == 1) {
  309. const Ctx ctx = ctx_enter(entry->mem_obj->url);
  310. httpState->reply_hdr_state++;
  311. debug(11, 9) ("GOT HTTP REPLY HDR:n---------n%sn----------n",
  312.     httpState->reply_hdr);
  313. /* Parse headers into reply structure */
  314. /* what happens if we fail to parse here? */
  315. httpReplyParse(reply, httpState->reply_hdr); /* httpState->eof); */
  316. storeTimestampsSet(entry);
  317. /* Check if object is cacheable or not based on reply code */
  318. debug(11, 3) ("httpProcessReplyHeader: HTTP CODE: %dn", reply->sline.status);
  319. if (neighbors_do_private_keys)
  320.     httpMaybeRemovePublic(entry, reply->sline.status);
  321. switch (httpCachableReply(httpState)) {
  322. case 1:
  323.     httpMakePublic(entry);
  324.     break;
  325. case 0:
  326.     httpMakePrivate(entry);
  327.     break;
  328. case -1:
  329.     httpCacheNegatively(entry);
  330.     break;
  331. default:
  332.     assert(0);
  333.     break;
  334. }
  335. if (reply->cache_control) {
  336.     if (EBIT_TEST(reply->cache_control->mask, CC_PROXY_REVALIDATE))
  337. EBIT_SET(entry->flags, ENTRY_REVALIDATE);
  338.     else if (EBIT_TEST(reply->cache_control->mask, CC_MUST_REVALIDATE))
  339. EBIT_SET(entry->flags, ENTRY_REVALIDATE);
  340. }
  341. if (httpState->flags.keepalive)
  342.     if (httpState->peer)
  343. httpState->peer->stats.n_keepalives_sent++;
  344. if (reply->keep_alive)
  345.     if (httpState->peer)
  346. httpState->peer->stats.n_keepalives_recv++;
  347. ctx_exit(ctx);
  348. if (reply->date > -1 && !httpState->peer) {
  349.     int skew = abs(reply->date - squid_curtime);
  350.     if (skew > 86400)
  351. debug(11, 3) ("%s's clock is skewed by %d seconds!n",
  352.     httpState->request->host, skew);
  353. }
  354.     }
  355. }
  356. static int
  357. httpPconnTransferDone(HttpStateData * httpState)
  358. {
  359.     /* return 1 if we got the last of the data on a persistent connection */
  360.     MemObject *mem = httpState->entry->mem_obj;
  361.     HttpReply *reply = mem->reply;
  362.     debug(11, 3) ("httpPconnTransferDone: FD %dn", httpState->fd);
  363.     /*
  364.      * If we didn't send a keep-alive request header, then this
  365.      * can not be a persistent connection.
  366.      */
  367.     if (!httpState->flags.keepalive)
  368. return 0;
  369.     /*
  370.      * What does the reply have to say about keep-alive?
  371.      */
  372.     if (!reply->keep_alive)
  373. return 0;
  374.     debug(11, 5) ("httpPconnTransferDone: content_length=%dn",
  375. reply->content_length);
  376.     /*
  377.      * Deal with gross HTTP stuff
  378.      *    - If we haven't seen the end of the reply headers, we can't
  379.      *      be persistent.
  380.      *    - For HEAD requests we're done.
  381.      *    - For "200 OK" check the content-length in the next block.
  382.      *    - For "204 No Content" (even with content-length) we're done.
  383.      *    - For "304 Not Modified" (even with content-length) we're done.
  384.      *    - 1XX replies never have a body; we're done.
  385.      *    - For all other replies, check content length in next block.
  386.      */
  387.     if (httpState->reply_hdr_state < 2)
  388. return 0;
  389.     else if (httpState->request->method == METHOD_HEAD)
  390. return 1;
  391.     else if (reply->sline.status == HTTP_OK)
  392. (void) 0; /* common case, continue */
  393.     else if (reply->sline.status == HTTP_NO_CONTENT)
  394. return 1;
  395.     else if (reply->sline.status == HTTP_NOT_MODIFIED)
  396. return 1;
  397.     else if (reply->sline.status < HTTP_OK)
  398. return 1;
  399.     /*
  400.      * If there is no content-length, then we can't be
  401.      * persistent.  If there is a content length, then we must
  402.      * wait until we've seen the end of the body.
  403.      */
  404.     if (reply->content_length < 0)
  405. return 0;
  406.     else if (mem->inmem_hi < reply->content_length + reply->hdr_sz)
  407. return 0;
  408.     else
  409. return 1;
  410. }
  411. /* This will be called when data is ready to be read from fd.  Read until
  412.  * error or connection closed. */
  413. /* XXX this function is too long! */
  414. static void
  415. httpReadReply(int fd, void *data)
  416. {
  417.     HttpStateData *httpState = data;
  418.     LOCAL_ARRAY(char, buf, SQUID_TCP_SO_RCVBUF);
  419.     StoreEntry *entry = httpState->entry;
  420.     const request_t *request = httpState->request;
  421.     int len;
  422.     int bin;
  423.     int clen;
  424.     size_t read_sz;
  425. #if DELAY_POOLS
  426.     delay_id delay_id;
  427.     /* special "if" only for http (for nodelay proxy conns) */
  428.     if (delayIsNoDelay(fd))
  429. delay_id = 0;
  430.     else
  431. delay_id = delayMostBytesAllowed(entry->mem_obj);
  432. #endif
  433.     if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
  434. comm_close(fd);
  435. return;
  436.     }
  437.     /* check if we want to defer reading */
  438.     errno = 0;
  439.     read_sz = SQUID_TCP_SO_RCVBUF;
  440. #if DELAY_POOLS
  441.     read_sz = delayBytesWanted(delay_id, 1, read_sz);
  442. #endif
  443.     Counter.syscalls.sock.reads++;
  444.     len = read(fd, buf, read_sz);
  445.     debug(11, 5) ("httpReadReply: FD %d: len %d.n", fd, len);
  446.     if (len > 0) {
  447. fd_bytes(fd, len, FD_READ);
  448. #if DELAY_POOLS
  449. delayBytesIn(delay_id, len);
  450. #endif
  451. kb_incr(&Counter.server.all.kbytes_in, len);
  452. kb_incr(&Counter.server.http.kbytes_in, len);
  453. commSetTimeout(fd, Config.Timeout.read, NULL, NULL);
  454. IOStats.Http.reads++;
  455. for (clen = len - 1, bin = 0; clen; bin++)
  456.     clen >>= 1;
  457. IOStats.Http.read_hist[bin]++;
  458.     }
  459.     if (!httpState->reply_hdr && len > 0) {
  460. /* Skip whitespace */
  461. while (len > 0 && xisspace(*buf))
  462.     xmemmove(buf, buf + 1, len--);
  463. if (len == 0) {
  464.     /* Continue to read... */
  465.     commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);
  466.     return;
  467. }
  468.     }
  469.     if (len < 0) {
  470. debug(50, 2) ("httpReadReply: FD %d: read failure: %s.n",
  471.     fd, xstrerror());
  472. if (ignoreErrno(errno)) {
  473.     commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);
  474. } else if (entry->mem_obj->inmem_hi == 0) {
  475.     ErrorState *err;
  476.     err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR);
  477.     err->xerrno = errno;
  478.     fwdFail(httpState->fwd, err);
  479.     comm_close(fd);
  480. } else {
  481.     comm_close(fd);
  482. }
  483.     } else if (len == 0 && entry->mem_obj->inmem_hi == 0) {
  484. ErrorState *err;
  485. err = errorCon(ERR_ZERO_SIZE_OBJECT, HTTP_SERVICE_UNAVAILABLE);
  486. err->xerrno = errno;
  487. fwdFail(httpState->fwd, err);
  488. httpState->eof = 1;
  489. comm_close(fd);
  490.     } else if (len == 0) {
  491. /* Connection closed; retrieval done. */
  492. httpState->eof = 1;
  493. if (httpState->reply_hdr_state < 2)
  494.     /*
  495.      * Yes Henrik, there is a point to doing this.  When we
  496.      * called httpProcessReplyHeader() before, we didn't find
  497.      * the end of headers, but now we are definately at EOF, so
  498.      * we want to process the reply headers.
  499.      */
  500.     httpProcessReplyHeader(httpState, buf, len);
  501. fwdComplete(httpState->fwd);
  502. comm_close(fd);
  503.     } else {
  504. if (httpState->reply_hdr_state < 2) {
  505.     httpProcessReplyHeader(httpState, buf, len);
  506.     if (httpState->reply_hdr_state == 2) {
  507. http_status s = entry->mem_obj->reply->sline.status;
  508. /* If its "successful" reply, allow the client
  509.  * to get it
  510.  */
  511. if (s >= 200 && s < 300)
  512.     EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
  513.     }
  514. }
  515. storeAppend(entry, buf, len);
  516. if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) {
  517.     /*
  518.      * the above storeAppend() call could ABORT this entry,
  519.      * in that case, the server FD should already be closed.
  520.      * there's nothing for us to do.
  521.      */
  522.     (void) 0;
  523. } else if (httpPconnTransferDone(httpState)) {
  524.     /* yes we have to clear all these! */
  525.     commSetDefer(fd, NULL, NULL);
  526.     commSetTimeout(fd, -1, NULL, NULL);
  527.     commSetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
  528.     comm_remove_close_handler(fd, httpStateFree, httpState);
  529.     fwdUnregister(fd, httpState->fwd);
  530.     pconnPush(fd, request->host, request->port);
  531.     fwdComplete(httpState->fwd);
  532.     httpState->fd = -1;
  533.     httpStateFree(fd, httpState);
  534. } else {
  535.     /* Wait for EOF condition */
  536.     commSetSelect(fd, COMM_SELECT_READ, httpReadReply, httpState, 0);
  537. }
  538.     }
  539. }
  540. /* This will be called when request write is complete. Schedule read of
  541.  * reply. */
  542. static void
  543. httpSendComplete(int fd, char *bufnotused, size_t size, int errflag, void *data)
  544. {
  545.     HttpStateData *httpState = data;
  546.     StoreEntry *entry = httpState->entry;
  547.     ErrorState *err;
  548.     debug(11, 5) ("httpSendComplete: FD %d: size %d: errflag %d.n",
  549. fd, size, errflag);
  550.     if (size > 0) {
  551. fd_bytes(fd, size, FD_WRITE);
  552. kb_incr(&Counter.server.all.kbytes_out, size);
  553. kb_incr(&Counter.server.http.kbytes_out, size);
  554.     }
  555.     if (errflag == COMM_ERR_CLOSING)
  556. return;
  557.     if (errflag) {
  558. err = errorCon(ERR_WRITE_ERROR, HTTP_INTERNAL_SERVER_ERROR);
  559. err->xerrno = errno;
  560. err->request = requestLink(httpState->orig_request);
  561. errorAppendEntry(entry, err);
  562. comm_close(fd);
  563. return;
  564.     } else {
  565. /* Schedule read reply. */
  566. commSetSelect(fd,
  567.     COMM_SELECT_READ,
  568.     httpReadReply,
  569.     httpState, 0);
  570. commSetDefer(fd, fwdCheckDeferRead, entry);
  571.     }
  572. }
  573. /*
  574.  * build request headers and append them to a given MemBuf 
  575.  * used by httpBuildRequestPrefix()
  576.  * note: calls httpHeaderInit(), the caller is responsible for Clean()-ing
  577.  */
  578. void
  579. httpBuildRequestHeader(request_t * request,
  580.     request_t * orig_request,
  581.     StoreEntry * entry,
  582.     HttpHeader * hdr_out,
  583.     int cfd,
  584.     http_state_flags flags)
  585. {
  586.     /* building buffer for complex strings */
  587. #define BBUF_SZ (MAX_URL+32)
  588.     LOCAL_ARRAY(char, bbuf, BBUF_SZ);
  589.     String strConnection = StringNull;
  590.     const HttpHeader *hdr_in = &orig_request->header;
  591.     int we_do_ranges;
  592.     const HttpHeaderEntry *e;
  593.     HttpHeaderPos pos = HttpHeaderInitPos;
  594.     httpHeaderInit(hdr_out, hoRequest);
  595.     /* append our IMS header */
  596.     if (entry && entry->lastmod > -1 && request->method == METHOD_GET)
  597. httpHeaderPutTime(hdr_out, HDR_IF_MODIFIED_SINCE, entry->lastmod);
  598.     /* decide if we want to do Ranges ourselves 
  599.      * (and fetch the whole object now)
  600.      * We want to handle Ranges ourselves iff
  601.      *    - we can actually parse client Range specs
  602.      *    - the specs are expected to be simple enough (e.g. no out-of-order ranges)
  603.      *    - reply will be cachable
  604.      * (If the reply will be uncachable we have to throw it away after 
  605.      *  serving this request, so it is better to forward ranges to 
  606.      *  the server and fetch only the requested content) 
  607.      */
  608.     we_do_ranges =
  609. orig_request->range && orig_request->flags.cachable && !httpHdrRangeWillBeComplex(orig_request->range) && (Config.rangeOffsetLimit == -1 || httpHdrRangeFirstOffset(orig_request->range) <= Config.rangeOffsetLimit);
  610.     debug(11, 8) ("httpBuildRequestHeader: range specs: %p, cachable: %d; we_do_ranges: %dn",
  611. orig_request->range, orig_request->flags.cachable, we_do_ranges);
  612.     strConnection = httpHeaderGetList(hdr_in, HDR_CONNECTION);
  613.     while ((e = httpHeaderGetEntry(hdr_in, &pos))) {
  614. debug(11, 5) ("httpBuildRequestHeader: %s: %sn",
  615.     strBuf(e->name), strBuf(e->value));
  616. if (!httpRequestHdrAllowed(e, &strConnection))
  617.     continue;
  618. switch (e->id) {
  619. case HDR_PROXY_AUTHORIZATION:
  620.     /* If we're not doing proxy auth, then it must be passed on */
  621.     if (!request->flags.used_proxy_auth)
  622. httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
  623.     break;
  624. case HDR_AUTHORIZATION:
  625.     /* If we're not doing www auth, then it must be passed on */
  626.     if (!request->flags.accelerated || !request->flags.used_proxy_auth)
  627. httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
  628.     else
  629. request->flags.auth = 0; /* We have used the authentication */
  630.     break;
  631. case HDR_HOST:
  632.     /* Don't use client's Host: header for redirected requests */
  633.     if (!request->flags.redirected || !Config.onoff.redir_rewrites_host)
  634. httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
  635.     break;
  636. case HDR_IF_MODIFIED_SINCE:
  637.     /* append unless we added our own;
  638.      * note: at most one client's ims header can pass through */
  639.     if (!httpHeaderHas(hdr_out, HDR_IF_MODIFIED_SINCE))
  640. httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
  641.     break;
  642. case HDR_MAX_FORWARDS:
  643.     if (orig_request->method == METHOD_TRACE) {
  644. /* sacrificing efficiency over clarity, etc. */
  645. const int hops = httpHeaderGetInt(hdr_in, HDR_MAX_FORWARDS);
  646. if (hops > 0)
  647.     httpHeaderPutInt(hdr_out, HDR_MAX_FORWARDS, hops - 1);
  648.     }
  649.     break;
  650. case HDR_RANGE:
  651. case HDR_IF_RANGE:
  652. case HDR_REQUEST_RANGE:
  653.     if (!we_do_ranges)
  654. httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
  655.     break;
  656. case HDR_PROXY_CONNECTION:
  657. case HDR_CONNECTION:
  658. case HDR_VIA:
  659. case HDR_X_FORWARDED_FOR:
  660. case HDR_CACHE_CONTROL:
  661.     /* append these after the loop if needed */
  662.     break;
  663. default:
  664.     /* pass on all other header fields */
  665.     httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e));
  666. }
  667.     }
  668.     /* append fake user agent if configured and 
  669.      * the real one is not supplied by the client */
  670.     if (Config.fake_ua && !httpHeaderHas(hdr_out, HDR_USER_AGENT))
  671. httpHeaderPutStr(hdr_out, HDR_USER_AGENT, Config.fake_ua);
  672.     /* append Via */
  673.     {
  674. String strVia = httpHeaderGetList(hdr_in, HDR_VIA);
  675. snprintf(bbuf, BBUF_SZ, "%3.1f %s", orig_request->http_ver, ThisCache);
  676. strListAdd(&strVia, bbuf, ',');
  677. httpHeaderPutStr(hdr_out, HDR_VIA, strBuf(strVia));
  678. stringClean(&strVia);
  679.     }
  680.     /* append X-Forwarded-For */
  681.     {
  682. String strFwd = httpHeaderGetList(hdr_in, HDR_X_FORWARDED_FOR);
  683. strListAdd(&strFwd, (cfd < 0 ? "unknown" : fd_table[cfd].ipaddr), ',');
  684. httpHeaderPutStr(hdr_out, HDR_X_FORWARDED_FOR, strBuf(strFwd));
  685. stringClean(&strFwd);
  686.     }
  687.     /* append Host if not there already */
  688.     if (!httpHeaderHas(hdr_out, HDR_HOST)) {
  689. /* use port# only if not default */
  690. if (orig_request->port == urlDefaultPort(orig_request->protocol)) {
  691.     httpHeaderPutStr(hdr_out, HDR_HOST, orig_request->host);
  692. } else {
  693.     httpHeaderPutStrf(hdr_out, HDR_HOST, "%s:%d",
  694. orig_request->host, (int) orig_request->port);
  695. }
  696.     }
  697.     /* append Authorization if known in URL, not in header and going direct */
  698.     if (!httpHeaderHas(hdr_out, HDR_AUTHORIZATION)) {
  699. if (!request->flags.proxying && *request->login) {
  700.     httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s",
  701. base64_encode(request->login));
  702. }
  703.     }
  704.     /* append Proxy-Authorization if configured for peer, and proxying */
  705.     if (!httpHeaderHas(hdr_out, HDR_PROXY_AUTHORIZATION)) {
  706. if (request->flags.proxying && request->peer_login) {
  707.     httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s",
  708. base64_encode(request->peer_login));
  709. }
  710.     }
  711.     /* append Cache-Control, add max-age if not there already */
  712.     {
  713. HttpHdrCc *cc = httpHeaderGetCc(hdr_in);
  714. if (!cc)
  715.     cc = httpHdrCcCreate();
  716. if (!EBIT_TEST(cc->mask, CC_MAX_AGE)) {
  717.     const char *url = entry ? storeUrl(entry) : urlCanonical(orig_request);
  718.     httpHdrCcSetMaxAge(cc, getMaxAge(url));
  719.     if (strLen(request->urlpath))
  720. assert(strstr(url, strBuf(request->urlpath)));
  721. }
  722. if (flags.only_if_cached)
  723.     EBIT_SET(cc->mask, CC_ONLY_IF_CACHED);
  724. httpHeaderPutCc(hdr_out, cc);
  725. httpHdrCcDestroy(cc);
  726.     }
  727.     /* maybe append Connection: keep-alive */
  728.     if (flags.keepalive) {
  729. if (flags.proxying) {
  730.     httpHeaderPutStr(hdr_out, HDR_PROXY_CONNECTION, "keep-alive");
  731. } else {
  732.     httpHeaderPutStr(hdr_out, HDR_CONNECTION, "keep-alive");
  733. }
  734.     }
  735.     stringClean(&strConnection);
  736. }
  737. /* build request prefix and append it to a given MemBuf; 
  738.  * return the length of the prefix */
  739. size_t
  740. httpBuildRequestPrefix(request_t * request,
  741.     request_t * orig_request,
  742.     StoreEntry * entry,
  743.     MemBuf * mb,
  744.     int cfd,
  745.     http_state_flags flags)
  746. {
  747.     const int offset = mb->size;
  748.     memBufPrintf(mb, "%s %s HTTP/1.0rn",
  749. RequestMethodStr[request->method],
  750. strLen(request->urlpath) ? strBuf(request->urlpath) : "/");
  751.     /* build and pack headers */
  752.     {
  753. HttpHeader hdr;
  754. Packer p;
  755. httpBuildRequestHeader(request, orig_request, entry, &hdr, cfd, flags);
  756. packerToMemInit(&p, mb);
  757. httpHeaderPackInto(&hdr, &p);
  758. httpHeaderClean(&hdr);
  759. packerClean(&p);
  760.     }
  761.     /* append header terminator */
  762.     memBufAppend(mb, crlf, 2);
  763.     return mb->size - offset;
  764. }
  765. /* This will be called when connect completes. Write request. */
  766. static void
  767. httpSendRequest(int fd, void *data)
  768. {
  769.     HttpStateData *httpState = data;
  770.     MemBuf mb;
  771.     request_t *req = httpState->request;
  772.     StoreEntry *entry = httpState->entry;
  773.     int cfd;
  774.     peer *p = httpState->peer;
  775.     CWCB *sendHeaderDone;
  776.     debug(11, 5) ("httpSendRequest: FD %d: httpState %p.n", fd, httpState);
  777.     if (pumpMethod(req->method))
  778. sendHeaderDone = httpSendRequestEntry;
  779.     else
  780. sendHeaderDone = httpSendComplete;
  781.     if (!opt_forwarded_for)
  782. cfd = -1;
  783.     else if (entry->mem_obj == NULL)
  784. cfd = -1;
  785.     else
  786. cfd = entry->mem_obj->fd;
  787.     assert(-1 == cfd || FD_SOCKET == fd_table[cfd].type);
  788.     if (p != NULL)
  789. httpState->flags.proxying = 1;
  790.     /*
  791.      * Is keep-alive okay for all request methods?
  792.      */
  793.     if (p == NULL)
  794. httpState->flags.keepalive = 1;
  795.     else if (p->stats.n_keepalives_sent < 10)
  796. httpState->flags.keepalive = 1;
  797.     else if ((double) p->stats.n_keepalives_recv / (double) p->stats.n_keepalives_sent > 0.50)
  798. httpState->flags.keepalive = 1;
  799.     if (httpState->peer)
  800. if (neighborType(httpState->peer, httpState->request) == PEER_SIBLING)
  801.     httpState->flags.only_if_cached = 1;
  802.     memBufDefInit(&mb);
  803.     httpBuildRequestPrefix(req,
  804. httpState->orig_request,
  805. entry,
  806. &mb,
  807. cfd,
  808. httpState->flags);
  809.     debug(11, 6) ("httpSendRequest: FD %d:n%sn", fd, mb.buf);
  810.     comm_write_mbuf(fd, mb, sendHeaderDone, httpState);
  811. }
  812. void
  813. httpStart(FwdState * fwd)
  814. {
  815.     int fd = fwd->server_fd;
  816.     HttpStateData *httpState = memAllocate(MEM_HTTP_STATE_DATA);
  817.     request_t *proxy_req;
  818.     request_t *orig_req = fwd->request;
  819.     debug(11, 3) ("httpStart: "%s %s"n",
  820. RequestMethodStr[orig_req->method],
  821. storeUrl(fwd->entry));
  822.     cbdataAdd(httpState, memFree, MEM_HTTP_STATE_DATA);
  823.     storeLockObject(fwd->entry);
  824.     httpState->fwd = fwd;
  825.     httpState->entry = fwd->entry;
  826.     httpState->fd = fd;
  827.     if (fwd->servers)
  828. httpState->peer = fwd->servers->peer; /* might be NULL */
  829.     if (httpState->peer) {
  830. proxy_req = requestCreate(orig_req->method,
  831.     PROTO_NONE, storeUrl(httpState->entry));
  832. xstrncpy(proxy_req->host, httpState->peer->host, SQUIDHOSTNAMELEN);
  833. proxy_req->port = httpState->peer->http_port;
  834. proxy_req->flags = orig_req->flags;
  835. proxy_req->peer_login = httpState->peer->login;
  836. httpState->request = requestLink(proxy_req);
  837. httpState->orig_request = requestLink(orig_req);
  838. proxy_req->flags.proxying = 1;
  839. /*
  840.  * This NEIGHBOR_PROXY_ONLY check probably shouldn't be here.
  841.  * We might end up getting the object from somewhere else if,
  842.  * for example, the request to this neighbor fails.
  843.  */
  844. if (httpState->peer->options.proxy_only)
  845.     storeReleaseRequest(httpState->entry);
  846. #if DELAY_POOLS
  847. assert(delayIsNoDelay(fd) == 0);
  848. if (httpState->peer->options.no_delay)
  849.     delaySetNoDelay(fd);
  850. #endif
  851.     } else {
  852. httpState->request = requestLink(orig_req);
  853. httpState->orig_request = requestLink(orig_req);
  854.     }
  855.     /*
  856.      * register the handler to free HTTP state data when the FD closes
  857.      */
  858.     comm_add_close_handler(fd, httpStateFree, httpState);
  859.     Counter.server.all.requests++;
  860.     Counter.server.http.requests++;
  861.     httpConnectDone(fd, COMM_OK, httpState);
  862. }
  863. static void
  864. httpConnectDone(int fd, int status, void *data)
  865. {
  866.     HttpStateData *httpState = data;
  867.     request_t *request = httpState->request;
  868.     StoreEntry *entry = httpState->entry;
  869.     ErrorState *err;
  870.     if (status == COMM_ERR_DNS) {
  871. debug(11, 4) ("httpConnectDone: Unknown host: %sn", request->host);
  872. err = errorCon(ERR_DNS_FAIL, HTTP_SERVICE_UNAVAILABLE);
  873. err->dnsserver_msg = xstrdup(dns_error_message);
  874. err->request = requestLink(httpState->orig_request);
  875. errorAppendEntry(entry, err);
  876. comm_close(fd);
  877.     } else if (status != COMM_OK) {
  878. err = errorCon(ERR_CONNECT_FAIL, HTTP_SERVICE_UNAVAILABLE);
  879. err->xerrno = errno;
  880. err->host = xstrdup(request->host);
  881. err->port = request->port;
  882. err->request = requestLink(httpState->orig_request);
  883. errorAppendEntry(entry, err);
  884. if (httpState->peer)
  885.     peerCheckConnectStart(httpState->peer);
  886. comm_close(fd);
  887.     } else {
  888. commSetSelect(fd, COMM_SELECT_WRITE, httpSendRequest, httpState, 0);
  889. commSetTimeout(fd, Config.Timeout.read, httpTimeout, httpState);
  890.     }
  891. }
  892. static void
  893. httpSendRequestEntry(int fd, char *bufnotused, size_t size, int errflag, void *data)
  894. {
  895.     HttpStateData *httpState = data;
  896.     StoreEntry *entry = httpState->entry;
  897.     ErrorState *err;
  898.     debug(11, 5) ("httpSendRequestEntry: FD %d: size %d: errflag %d.n",
  899. fd, size, errflag);
  900.     if (size > 0) {
  901. fd_bytes(fd, size, FD_WRITE);
  902. kb_incr(&Counter.server.all.kbytes_out, size);
  903. kb_incr(&Counter.server.http.kbytes_out, size);
  904.     }
  905.     if (errflag == COMM_ERR_CLOSING)
  906. return;
  907.     if (errflag) {
  908. err = errorCon(ERR_WRITE_ERROR, HTTP_INTERNAL_SERVER_ERROR);
  909. err->xerrno = errno;
  910. err->request = requestLink(httpState->orig_request);
  911. errorAppendEntry(entry, err);
  912. comm_close(fd);
  913. return;
  914.     }
  915.     pumpStart(fd, httpState->fwd, httpSendRequestEntryDone, httpState);
  916. }
  917. static void
  918. httpSendRequestEntryDone(int fd, char *bufnotused, size_t size, int errflag, void *data)
  919. {
  920.     HttpStateData *httpState = data;
  921.     StoreEntry *entry = httpState->entry;
  922.     ErrorState *err;
  923.     aclCheck_t ch;
  924.     debug(11, 5) ("httpSendRequestEntryDone: FD %d: size %d: errflag %d.n",
  925. fd, size, errflag);
  926.     if (size > 0) {
  927. fd_bytes(fd, size, FD_WRITE);
  928. kb_incr(&Counter.server.all.kbytes_out, size);
  929. kb_incr(&Counter.server.http.kbytes_out, size);
  930.     }
  931.     if (errflag == COMM_ERR_CLOSING)
  932. return;
  933.     if (errflag) {
  934. err = errorCon(ERR_WRITE_ERROR, HTTP_INTERNAL_SERVER_ERROR);
  935. err->xerrno = errno;
  936. err->request = requestLink(httpState->orig_request);
  937. errorAppendEntry(entry, err);
  938. comm_close(fd);
  939. return;
  940.     }
  941.     memset(&ch, '', sizeof(ch));
  942.     ch.request = httpState->request;
  943.     if (!Config.accessList.brokenPosts) {
  944. debug(11, 5) ("httpSendRequestEntryDone: No brokenPosts listn");
  945. httpSendComplete(fd, NULL, 0, 0, data);
  946.     } else if (!aclCheckFast(Config.accessList.brokenPosts, &ch)) {
  947. debug(11, 5) ("httpSendRequestEntryDone: didn't match brokenPostsn");
  948. httpSendComplete(fd, NULL, 0, 0, data);
  949.     } else {
  950. debug(11, 2) ("httpSendRequestEntryDone: matched brokenPostsn");
  951. comm_write(fd, "rn", 2, httpSendComplete, data, NULL);
  952.     }
  953. }