📄 http.c
字号:
continue; switch (e->id) { case HDR_PROXY_AUTHORIZATION: /* If we're not doing proxy auth, then it must be passed on */ if (!request->flags.used_proxy_auth) httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e)); break; case HDR_AUTHORIZATION: /* If we're not doing www auth, then it must be passed on */ if (!request->flags.accelerated || !request->flags.used_proxy_auth) httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e)); else request->flags.auth = 0; /* We have used the authentication */ break; case HDR_HOST: /* Don't use client's Host: header for redirected requests */ if (!request->flags.redirected || !Config.onoff.redir_rewrites_host) 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) { /* 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_RANGE: case HDR_IF_RANGE: case HDR_REQUEST_RANGE: if (!we_do_ranges) httpHeaderAddEntry(hdr_out, httpHeaderEntryClone(e)); 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)); } } /* 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 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); } /* 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 { httpHeaderPutStrf(hdr_out, HDR_HOST, "%s:%d", orig_request->host, (int) orig_request->port); } } /* append Authorization if known in URL, not in header and going direct */ if (!httpHeaderHas(hdr_out, HDR_AUTHORIZATION)) { if (!request->flags.proxying && *request->login) { httpHeaderPutStrf(hdr_out, HDR_AUTHORIZATION, "Basic %s", base64_encode(request->login)); } } /* append Proxy-Authorization if configured for peer, and proxying */ if (!httpHeaderHas(hdr_out, HDR_PROXY_AUTHORIZATION)) { if (request->flags.proxying && request->peer_login) { httpHeaderPutStrf(hdr_out, HDR_PROXY_AUTHORIZATION, "Basic %s", base64_encode(request->peer_login)); } } /* 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); httpHdrCcSetMaxAge(cc, getMaxAge(url)); if (strLen(request->urlpath)) assert(strstr(url, strBuf(request->urlpath))); } if (flags.only_if_cached) EBIT_SET(cc->mask, CC_ONLY_IF_CACHED); httpHeaderPutCc(hdr_out, cc); httpHdrCcDestroy(cc); } /* maybe append Connection: keep-alive */ if (flags.keepalive) { if (flags.proxying) { httpHeaderPutStr(hdr_out, HDR_PROXY_CONNECTION, "keep-alive"); } else { httpHeaderPutStr(hdr_out, HDR_CONNECTION, "keep-alive"); } } stringClean(&strConnection);}/* build request prefix and append it to a given MemBuf; * return the length of the prefix */size_thttpBuildRequestPrefix(request_t * request, request_t * orig_request, StoreEntry * entry, MemBuf * mb, int cfd, http_state_flags 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); } /* append header terminator */ memBufAppend(mb, crlf, 2); return mb->size - offset;}/* This will be called when connect completes. Write request. */static voidhttpSendRequest(HttpStateData * httpState){ MemBuf mb; request_t *req = httpState->request; StoreEntry *entry = httpState->entry; int cfd; peer *p = httpState->peer; CWCB *sendHeaderDone; debug(11, 5) ("httpSendRequest: FD %d: httpState %p.\n", httpState->fd, httpState); if (pumpMethod(req->method)) sendHeaderDone = httpSendRequestEntry; else sendHeaderDone = httpSendComplete; if (!opt_forwarded_for) cfd = -1; else if (entry->mem_obj == NULL) cfd = -1; else cfd = entry->mem_obj->fd; assert(-1 == cfd || FD_SOCKET == fd_table[cfd].type); if (p != NULL) httpState->flags.proxying = 1; /* * Is keep-alive okay for all request methods? */ if (p == NULL) httpState->flags.keepalive = 1; else if (p->stats.n_keepalives_sent < 10) httpState->flags.keepalive = 1; else if ((double) p->stats.n_keepalives_recv / (double) p->stats.n_keepalives_sent > 0.50) httpState->flags.keepalive = 1; if (httpState->peer) if (neighborType(httpState->peer, httpState->request) == PEER_SIBLING) httpState->flags.only_if_cached = 1; memBufDefInit(&mb); httpBuildRequestPrefix(req, httpState->orig_request, entry, &mb, cfd, httpState->flags); debug(11, 6) ("httpSendRequest: FD %d:\n%s\n", httpState->fd, mb.buf); comm_write_mbuf(httpState->fd, mb, sendHeaderDone, httpState);}voidhttpStart(FwdState * fwd){ int fd = fwd->server_fd; HttpStateData *httpState = memAllocate(MEM_HTTP_STATE_DATA); request_t *proxy_req; request_t *orig_req = fwd->request; debug(11, 3) ("httpStart: \"%s %s\"\n", RequestMethodStr[orig_req->method], storeUrl(fwd->entry)); cbdataAdd(httpState, memFree, MEM_HTTP_STATE_DATA); storeLockObject(fwd->entry); httpState->fwd = fwd; httpState->entry = fwd->entry; httpState->fd = fd; if (fwd->servers) httpState->peer = fwd->servers->peer; /* might be NULL */ if (httpState->peer) { proxy_req = requestCreate(orig_req->method, PROTO_NONE, storeUrl(httpState->entry)); xstrncpy(proxy_req->host, httpState->peer->host, SQUIDHOSTNAMELEN); proxy_req->port = httpState->peer->http_port; proxy_req->flags = orig_req->flags; proxy_req->peer_login = httpState->peer->login; httpState->request = requestLink(proxy_req); httpState->orig_request = requestLink(orig_req); proxy_req->flags.proxying = 1; /* * This NEIGHBOR_PROXY_ONLY check probably shouldn't be here. * We might end up getting the object from somewhere else if, * for example, the request to this neighbor fails. */ if (httpState->peer->options.proxy_only) storeReleaseRequest(httpState->entry);#if DELAY_POOLS assert(delayIsNoDelay(fd) == 0); if (httpState->peer->options.no_delay) delaySetNoDelay(fd);#endif } else { httpState->request = requestLink(orig_req); httpState->orig_request = requestLink(orig_req); } /* * register the handler to free HTTP state data when the FD closes */ comm_add_close_handler(fd, httpStateFree, httpState); Counter.server.all.requests++; Counter.server.http.requests++; httpSendRequest(httpState); /* * We used to set the read timeout here, but not any more. * Now its set in httpSendComplete() after the full request, * including request body, has been written to the server. */}static voidhttpSendRequestEntry(int fd, char *bufnotused, size_t size, int errflag, void *data){ HttpStateData *httpState = data; StoreEntry *entry = httpState->entry; ErrorState *err; debug(11, 5) ("httpSendRequestEntry: FD %d: size %d: errflag %d.\n", fd, size, errflag); if (size > 0) { fd_bytes(fd, size, FD_WRITE); kb_incr(&Counter.server.all.kbytes_out, size); kb_incr(&Counter.server.http.kbytes_out, size); } if (errflag == COMM_ERR_CLOSING) return; if (errflag) { err = errorCon(ERR_WRITE_ERROR, HTTP_INTERNAL_SERVER_ERROR); err->xerrno = errno; err->request = requestLink(httpState->orig_request); errorAppendEntry(entry, err); comm_close(fd); return; } if (EBIT_TEST(entry->flags, ENTRY_ABORTED)) { comm_close(fd); return; } pumpStart(fd, httpState->fwd, httpSendRequestEntryDone, httpState);}static voidhttpSendRequestEntryDone(int fd, char *bufnotused, size_t size, int errflag, void *data){ HttpStateData *httpState = data; StoreEntry *entry = httpState->entry; ErrorState *err; aclCheck_t ch; debug(11, 5) ("httpSendRequestEntryDone: FD %d: size %d: errflag %d.\n", fd, size, errflag); if (size > 0) { fd_bytes(fd, size, FD_WRITE); kb_incr(&Counter.server.all.kbytes_out, size); kb_incr(&Counter.server.http.kbytes_out, size); } if (errflag == COMM_ERR_CLOSING) return; if (errflag) { err = errorCon(ERR_WRITE_ERROR, HTTP_INTERNAL_SERVER_ERROR); err->xerrno = errno; err->request = requestLink(httpState->orig_request); errorAppendEntry(entry, err); comm_close(fd); return; } memset(&ch, '\0', sizeof(ch)); ch.request = httpState->request; if (!Config.accessList.brokenPosts) { debug(11, 5) ("httpSendRequestEntryDone: No brokenPosts list\n"); httpSendComplete(fd, NULL, 0, 0, data); } else if (!aclCheckFast(Config.accessList.brokenPosts, &ch)) { debug(11, 5) ("httpSendRequestEntryDone: didn't match brokenPosts\n"); httpSendComplete(fd, NULL, 0, 0, data); } else { debug(11, 2) ("httpSendRequestEntryDone: matched brokenPosts\n"); comm_write(fd, "\r\n", 2, httpSendComplete, data, NULL); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -