#include "MemBuf.h"
#include "MemObject.h"
#include "protos.h"
+#include "rfc1738.h"
#include "SquidTime.h"
#include "Store.h"
#include "TextException.h"
return 0;
default: /* Unknown status code */
- debugs (11, 0, HERE << "HttpStateData::cacheableReply: unexpected http status code " << rep->sline.status);
+ debugs (11, DBG_IMPORTANT, "WARNING: Unexpected http status code " << rep->sline.status);
return 0;
HttpReply *newrep = new HttpReply;
const bool parsed = newrep->parse(readBuf, eof, &error);
- if (!parsed && readBuf->contentSize() > 5 && strncmp(readBuf->content(), "HTTP/", 5) != 0) {
+ if (!parsed && readBuf->contentSize() > 5 && strncmp(readBuf->content(), "HTTP/", 5) != 0 && strncmp(readBuf->content(), "ICY", 3) != 0) {
MemBuf *mb;
HttpReply *tmprep = new HttpReply;
- tmprep->sline.version = HttpVersion(1, 0);
- tmprep->sline.status = HTTP_OK;
- tmprep->header.putTime(HDR_DATE, squid_curtime);
+ tmprep->setHeaders(HTTP_OK, "Gatewaying", NULL, -1, -1, -1);
tmprep->header.putExt("X-Transformed-From", "HTTP/0.9");
mb = tmprep->pack();
newrep->parse(mb, eof, &error);
if (!parsed && error > 0) { // unrecoverable parsing error
debugs(11, 3, "processReplyHeader: Non-HTTP-compliant header: '" << readBuf->content() << "'");
flags.headers_parsed = 1;
- newrep->sline.version = HttpVersion(1, 0);
+ newrep->sline.version = HttpVersion(1,0);
newrep->sline.status = error;
HttpReply *vrep = setVirginReply(newrep);
entry->replaceHttpReply(vrep);
}
flags.chunked = 0;
- if (newrep->header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ',')) {
+ if (newrep->sline.protocol == PROTO_HTTP && newrep->header.hasListMember(HDR_TRANSFER_ENCODING, "chunked", ',')) {
flags.chunked = 1;
httpChunkDecoder = new ChunkedCodingParser;
}
if (!vary) {
entry->makePrivate();
+ if (!fwd->reforwardableStatus(rep->sline.status))
+ EBIT_CLR(entry->flags, ENTRY_FWD_HDR_WAIT);
goto no_cache;
-
}
entry->mem_obj->vary_headers = xstrdup(vary);
const http_status s = vrep->sline.status;
const HttpVersion &v = vrep->sline.version;
if (s == HTTP_INVALID_HEADER && v != HttpVersion(0,9)) {
+ debugs(11, DBG_IMPORTANT, "WARNING: HTTP: Invalid Response: Bad header encountered from " << entry->url() << " AKA " << orig_request->GetHost() << orig_request->urlpath.termedBuf() );
error = ERR_INVALID_RESP;
} else if (s == HTTP_HEADER_TOO_LARGE) {
fwd->dontRetry(true);
}
} else {
// parsed headers but got no reply
+ debugs(11, DBG_IMPORTANT, "WARNING: HTTP: Invalid Response: No reply at all for " << entry->url() << " AKA " << orig_request->GetHost() << orig_request->urlpath.termedBuf() );
error = ERR_INVALID_RESP;
}
} else {
assert(eof);
- error = readBuf->hasContent() ?
- ERR_INVALID_RESP : ERR_ZERO_SIZE_OBJECT;
+ if (readBuf->hasContent()) {
+ error = ERR_INVALID_RESP;
+ debugs(11, DBG_IMPORTANT, "WARNING: HTTP: Invalid Response: Headers did not parse at all for " << entry->url() << " AKA " << orig_request->GetHost() << orig_request->urlpath.termedBuf() );
+ } else {
+ error = ERR_ZERO_SIZE_OBJECT;
+ debugs(11, DBG_IMPORTANT, "WARNING: HTTP: Invalid Response: No object data received for " << entry->url() << " AKA " << orig_request->GetHost() << orig_request->urlpath.termedBuf() );
+ }
}
assert(error != ERR_NONE);
{
const char *data = NULL;
int len;
- bool status = false;
+ bool wasThereAnException = false;
assert(flags.chunked);
assert(httpChunkDecoder);
SQUID_ENTER_THROWING_CODE();
MemBuf decodedData;
decodedData.init();
- const bool done = httpChunkDecoder->parse(readBuf,&decodedData);
+ const bool doneParsing = httpChunkDecoder->parse(readBuf,&decodedData);
len = decodedData.contentSize();
data=decodedData.content();
addVirginReplyBody(data, len);
- if (done) {
+ if (doneParsing) {
lastChunk = 1;
flags.do_next_read = 0;
}
- SQUID_EXIT_THROWING_CODE(status);
- return status;
+ SQUID_EXIT_THROWING_CODE(wasThereAnException);
+ return wasThereAnException;
}
/**
void
HttpStateData::maybeReadVirginBody()
{
- int read_sz = replyBodySpace(readBuf->spaceSize());
+ // we may need to grow the buffer if headers do not fit
+ const int minRead = flags.headers_parsed ? 0 :1024;
+ const int read_size = replyBodySpace(*readBuf, minRead);
debugs(11,9, HERE << (flags.do_next_read ? "may" : "wont") <<
- " read up to " << read_sz << " bytes from FD " << fd);
+ " read up to " << read_size << " bytes from FD " << fd);
/*
* why <2? Because delayAwareRead() won't actually read if
* handler until we get a notification from someone that
* its okay to read again.
*/
- if (read_sz < 2) {
- if (flags.headers_parsed)
- return;
- else
- read_sz = 1024;
- }
+ if (read_size < 2)
+ return;
if (flags.do_next_read) {
flags.do_next_read = 0;
typedef CommCbMemFunT<HttpStateData, CommIoCbParams> Dialer;
- entry->delayAwareRead(fd, readBuf->space(read_sz), read_sz,
+ entry->delayAwareRead(fd, readBuf->space(read_size), read_size,
asyncCall(11, 5, "HttpStateData::readReply",
Dialer(this, &HttpStateData::readReply)));
}
/* Nothing to do unless we are forwarding to a peer */
if (!request->flags.proxying)
- return;
+ return;
/* Needs to be explicitly enabled */
if (!orig_request->peer_login)
- return;
+ return;
/* Maybe already dealt with? */
if (hdr_out->has(header))
- return;
+ return;
/* Nothing to do here for PASSTHRU */
if (strcmp(orig_request->peer_login, "PASSTHRU") == 0)
- return;
+ return;
/* PROXYPASS is a special case, single-signon to servers with the proxy password (basic only) */
if (flags.originpeer && strcmp(orig_request->peer_login, "PROXYPASS") == 0 && hdr_in->has(HDR_PROXY_AUTHORIZATION)) {
- const char *auth = hdr_in->getStr(HDR_PROXY_AUTHORIZATION);
+ const char *auth = hdr_in->getStr(HDR_PROXY_AUTHORIZATION);
- if (auth && strncasecmp(auth, "basic ", 6) == 0) {
- hdr_out->putStr(header, auth);
- return;
- }
+ if (auth && strncasecmp(auth, "basic ", 6) == 0) {
+ hdr_out->putStr(header, auth);
+ return;
+ }
}
/* Special mode to pass the username to the upstream cache */
if (*orig_request->peer_login == '*') {
- char loginbuf[256];
- const char *username = "-";
+ char loginbuf[256];
+ const char *username = "-";
- if (orig_request->extacl_user.size())
- username = orig_request->extacl_user.termedBuf();
- else if (orig_request->auth_user_request)
- username = orig_request->auth_user_request->username();
+ if (orig_request->extacl_user.size())
+ username = orig_request->extacl_user.termedBuf();
+ else if (orig_request->auth_user_request)
+ username = orig_request->auth_user_request->username();
- snprintf(loginbuf, sizeof(loginbuf), "%s%s", username, orig_request->peer_login + 1);
+ snprintf(loginbuf, sizeof(loginbuf), "%s%s", username, orig_request->peer_login + 1);
- httpHeaderPutStrf(hdr_out, header, "Basic %s",
- base64_encode(loginbuf));
- return;
+ httpHeaderPutStrf(hdr_out, header, "Basic %s",
+ base64_encode(loginbuf));
+ return;
}
/* external_acl provided credentials */
if (orig_request->extacl_user.size() && orig_request->extacl_passwd.size() &&
- (strcmp(orig_request->peer_login, "PASS") == 0 ||
- strcmp(orig_request->peer_login, "PROXYPASS") == 0)) {
- char loginbuf[256];
- snprintf(loginbuf, sizeof(loginbuf), SQUIDSTRINGPH ":" SQUIDSTRINGPH,
- SQUIDSTRINGPRINT(orig_request->extacl_user),
- SQUIDSTRINGPRINT(orig_request->extacl_passwd));
- httpHeaderPutStrf(hdr_out, header, "Basic %s",
- base64_encode(loginbuf));
- return;
+ (strcmp(orig_request->peer_login, "PASS") == 0 ||
+ strcmp(orig_request->peer_login, "PROXYPASS") == 0)) {
+ char loginbuf[256];
+ snprintf(loginbuf, sizeof(loginbuf), SQUIDSTRINGPH ":" SQUIDSTRINGPH,
+ SQUIDSTRINGPRINT(orig_request->extacl_user),
+ SQUIDSTRINGPRINT(orig_request->extacl_passwd));
+ httpHeaderPutStrf(hdr_out, header, "Basic %s",
+ base64_encode(loginbuf));
+ return;
}
/* Kerberos login to peer */
#endif /* HAVE_KRB5 && HAVE_GSSAPI */
httpHeaderPutStrf(hdr_out, header, "Basic %s",
- base64_encode(orig_request->peer_login));
+ base64_encode(orig_request->peer_login));
return;
}
}
#if USE_SQUID_ESI
- {
+ if (orig_request->flags.accelerated) {
/* Append Surrogate-Capabilities */
String strSurrogate (hdr_in->getList(HDR_SURROGATE_CAPABILITY));
snprintf(bbuf, BBUF_SZ, "%s=\"Surrogate/1.0 ESI/1.0\"",
* authentication forwarding is explicitly enabled
*/
if (!flags.originpeer && flags.proxying && orig_request->peer_login &&
- (strcmp(orig_request->peer_login, "PASS") == 0 ||
- strcmp(orig_request->peer_login, "PROXYPASS") == 0 ||
- strcmp(orig_request->peer_login, "PASSTHRU") == 0)) {
+ (strcmp(orig_request->peer_login, "PASS") == 0 ||
+ strcmp(orig_request->peer_login, "PROXYPASS") == 0 ||
+ strcmp(orig_request->peer_login, "PASSTHRU") == 0)) {
hdr_out->addEntry(e->clone());
}
break;
/* build request prefix and append it to a given MemBuf;
* return the length of the prefix */
mb_size_t
-HttpStateData::buildRequestPrefix(HttpRequest * request,
- HttpRequest * orig_request,
- StoreEntry * entry,
+HttpStateData::buildRequestPrefix(HttpRequest * aRequest,
+ HttpRequest * original_request,
+ StoreEntry * sentry,
MemBuf * mb,
- http_state_flags flags)
+ http_state_flags stateFlags)
{
const int offset = mb->size;
- HttpVersion httpver(1, 0);
+ HttpVersion httpver(1,0);
mb->Printf("%s %s HTTP/%d.%d\r\n",
- RequestMethodStr(request->method),
- request->urlpath.size() ? request->urlpath.termedBuf() : "/",
+ RequestMethodStr(aRequest->method),
+ aRequest->urlpath.size() ? aRequest->urlpath.termedBuf() : "/",
httpver.major,httpver.minor);
/* build and pack headers */
{
HttpHeader hdr(hoRequest);
Packer p;
- httpBuildRequestHeader(request, orig_request, entry, &hdr, flags);
+ httpBuildRequestHeader(aRequest, original_request, sentry, &hdr, stateFlags);
- if (request->flags.pinned && request->flags.connection_auth)
- request->flags.auth_sent = 1;
+ if (aRequest->flags.pinned && aRequest->flags.connection_auth)
+ aRequest->flags.auth_sent = 1;
else if (hdr.has(HDR_AUTHORIZATION))
- request->flags.auth_sent = 1;
+ aRequest->flags.auth_sent = 1;
packerToMemInit(&p, mb);
hdr.packInto(&p);