/*
- * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
+ * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
*
* Squid software is distributed under GPLv2+ license and includes
* contributions from numerous individuals and organizations.
{
assert(request);
return request->cache_control &&
- request->cache_control->onlyIfCached();
+ request->cache_control->hasOnlyIfCached();
}
/**
int
clientBeginRequest(const HttpRequestMethod& method, char const *url, CSCB * streamcallback,
CSD * streamdetach, ClientStreamData streamdata, HttpHeader const *header,
- char *tailbuf, size_t taillen)
+ char *tailbuf, size_t taillen, const MasterXaction::Pointer &mx)
{
size_t url_sz;
ClientHttpRequest *http = new ClientHttpRequest(NULL);
http->uri = (char *)xcalloc(url_sz, 1);
strcpy(http->uri, url);
- if ((request = HttpRequest::CreateFromUrl(http->uri, method)) == NULL) {
+ if ((request = HttpRequest::FromUrl(http->uri, mx, method)) == NULL) {
debugs(85, 5, "Invalid URL: " << http->uri);
return -1;
}
*/
request->flags.accelerated = http->flags.accel;
- request->flags.internalClient = true;
-
/* this is an internally created
* request, not subject to acceleration
* target overrides */
ClientRequestContext::clientRedirectStart()
{
debugs(33, 5, HERE << "'" << http->uri << "'");
- (void)SyncNotes(*http->al, *http->request);
+ http->al->syncNotes(http->request);
if (Config.accessList.redirector) {
acl_checklist = clientAclChecklistCreate(Config.accessList.redirector, http);
acl_checklist->nonBlockingCheck(clientRedirectAccessCheckDone, this);
// Put helper response Notes into the transaction state record (ALE) eventually
// do it early to ensure that no matter what the outcome the notes are present.
- if (http->al != NULL)
- (void)SyncNotes(*http->al, *old_request);
+ if (http->al)
+ http->al->syncNotes(old_request);
UpdateRequestNotes(http->getConn(), *old_request, reply.notes);
// XXX: validate the URL properly *without* generating a whole new request object right here.
// XXX: the clone() should be done only AFTER we know the new URL is valid.
HttpRequest *new_request = old_request->clone();
- if (urlParse(old_request->method, const_cast<char*>(urlNote), new_request)) {
+ if (urlParse(old_request->method, const_cast<char*>(urlNote), *new_request)) {
debugs(61, 2, "URL-rewriter diverts URL from " << old_request->effectiveRequestUri() << " to " << new_request->effectiveRequestUri());
// update the new request to flag the re-writing was done on it
// Put helper response Notes into the transaction state record (ALE) eventually
// do it early to ensure that no matter what the outcome the notes are present.
- if (http->al != NULL)
- (void)SyncNotes(*http->al, *old_request);
+ if (http->al)
+ http->al->syncNotes(old_request);
UpdateRequestNotes(http->getConn(), *old_request, reply.notes);
ClientRequestContext::checkNoCacheDone(const allow_t &answer)
{
acl_checklist = NULL;
- http->request->flags.cachable = (answer == ACCESS_ALLOWED);
+ if (answer == ACCESS_DENIED) {
+ http->request->flags.noCache = true; // dont read reply from cache
+ http->request->flags.cachable = false; // dont store reply into cache
+ }
http->doCallouts();
}
return false;
}
- // If SSL connection tunneling or bumping decision has been made, obey it.
const Ssl::BumpMode bumpMode = http->getConn()->sslBumpMode;
+ if (http->request->flags.forceTunnel) {
+ debugs(85, 5, "not needed; already decided to tunnel " << http->getConn());
+ if (bumpMode != Ssl::bumpEnd)
+ http->al->ssl.bumpMode = bumpMode; // inherited from bumped connection
+ return false;
+ }
+
+ // If SSL connection tunneling or bumping decision has been made, obey it.
if (bumpMode != Ssl::bumpEnd) {
debugs(85, 5, HERE << "SslBump already decided (" << bumpMode <<
"), " << "ignoring ssl_bump for " << http->getConn());
- if (!http->getConn()->serverBump())
+
+ // We need the following "if" for transparently bumped TLS connection,
+ // because in this case we are running ssl_bump access list before
+ // the doCallouts runs. It can be removed after the bug #4340 fixed.
+ // We do not want to proceed to bumping steps:
+ // - if the TLS connection with the client is already established
+ // because we are accepting normal HTTP requests on TLS port,
+ // or because of the client-first bumping mode
+ // - When the bumping is already started
+ if (!http->getConn()->switchedToHttps() &&
+ !http->getConn()->serverBump())
http->sslBumpNeed(bumpMode); // for processRequest() to bump if needed and not already bumped
http->al->ssl.bumpMode = bumpMode; // inherited from bumped connection
return false;
return false;
}
+ if (error) {
+ debugs(85, 5, "SslBump applies. Force bump action on error " << errorTypeName(error->type));
+ http->sslBumpNeed(Ssl::bumpBump);
+ http->al->ssl.bumpMode = Ssl::bumpBump;
+ return false;
+ }
+
debugs(85, 5, HERE << "SslBump possible, checking ACL");
ACLFilledChecklist *aclChecklist = clientAclChecklistCreate(Config.accessList.ssl_bump, http);
return;
const Ssl::BumpMode bumpMode = answer == ACCESS_ALLOWED ?
- static_cast<Ssl::BumpMode>(answer.kind) : Ssl::bumpNone;
+ static_cast<Ssl::BumpMode>(answer.kind) : Ssl::bumpSplice;
http->sslBumpNeed(bumpMode); // for processRequest() to bump if needed
http->al->ssl.bumpMode = bumpMode; // for logging
+ if (bumpMode == Ssl::bumpTerminate) {
+ const Comm::ConnectionPointer clientConn = http->getConn() ? http->getConn()->clientConnection : nullptr;
+ if (Comm::IsConnOpen(clientConn)) {
+ debugs(85, 3, "closing after Ssl::bumpTerminate ");
+ clientConn->close();
+ }
+ return;
+ }
+
http->doCallouts();
}
#endif
{
debugs(85, 4, request->method << ' ' << uri);
- if (request->method == Http::METHOD_CONNECT && !redirect.status) {
+ const bool untouchedConnect = request->method == Http::METHOD_CONNECT && !redirect.status;
+
#if USE_OPENSSL
- if (sslBumpNeeded()) {
- sslBumpStart();
- return;
- }
+ if (untouchedConnect && sslBumpNeeded()) {
+ assert(!request->flags.forceTunnel);
+ sslBumpStart();
+ return;
+ }
#endif
+
+ if (untouchedConnect || request->flags.forceTunnel) {
getConn()->stopReading(); // tunnels read for themselves
tunnelStart(this);
return;
{
assert(calloutContext);
+ auto &ale = calloutContext->http->al;
/*Save the original request for logging purposes*/
- if (!calloutContext->http->al->request) {
- calloutContext->http->al->request = request;
- HTTPMSGLOCK(calloutContext->http->al->request);
+ if (!ale->request) {
+ ale->request = request;
+ HTTPMSGLOCK(ale->request);
- NotePairs ¬es = SyncNotes(*calloutContext->http->al, *calloutContext->http->request);
// Make the previously set client connection ID available as annotation.
if (ConnStateData *csd = calloutContext->http->getConn()) {
- if (!csd->connectionTag().isEmpty())
- notes.add("clt_conn_tag", SBuf(csd->connectionTag()).c_str());
+ if (!csd->notes()->empty())
+ calloutContext->http->request->notes()->appendNewOnly(csd->notes().getRaw());
}
+ ale->syncNotes(calloutContext->http->request);
}
if (!calloutContext->error) {
}
#if USE_OPENSSL
- // We need to check for SslBump even if the calloutContext->error is set
- // because bumping may require delaying the error until after CONNECT.
+ // Even with calloutContext->error, we call sslBumpAccessCheck() to decide
+ // whether SslBump applies to this transaction. If it applies, we will
+ // attempt to bump the client to serve the error.
if (!calloutContext->sslBumpCheckDone) {
calloutContext->sslBumpCheckDone = true;
if (calloutContext->sslBumpAccessCheck())
if (calloutContext->error) {
// XXX: prformance regression. c_str() reallocates
- SBuf storeUri(request->storeId());
- StoreEntry *e = storeCreateEntry(storeUri.c_str(), storeUri.c_str(), request->flags, request->method);
+ SBuf storeUriBuf(request->storeId());
+ const char *storeUri = storeUriBuf.c_str();
+ StoreEntry *e = storeCreateEntry(storeUri, storeUri, request->flags, request->method);
#if USE_OPENSSL
if (sslBumpNeeded()) {
// We have to serve an error, so bump the client first.
sslBumpNeed(Ssl::bumpClientFirst);
// set final error but delay sending until we bump
- Ssl::ServerBump *srvBump = new Ssl::ServerBump(request, e);
+ Ssl::ServerBump *srvBump = new Ssl::ServerBump(request, e, Ssl::bumpClientFirst);
errorAppendEntry(e, calloutContext->error);
calloutContext->error = NULL;
getConn()->setServerBump(srvBump);
#endif
}
-#if !_USE_INLINE_
-#include "client_side_request.cci"
-#endif
-
#if USE_ADAPTATION
/// Initiate an asynchronous adaptation transaction which will call us back.
void
switch (answer.kind) {
case Adaptation::Answer::akForward:
- handleAdaptedHeader(const_cast<HttpMsg*>(answer.message.getRaw()));
+ handleAdaptedHeader(const_cast<Http::Message*>(answer.message.getRaw()));
break;
case Adaptation::Answer::akBlock:
}
void
-ClientHttpRequest::handleAdaptedHeader(HttpMsg *msg)
+ClientHttpRequest::handleAdaptedHeader(Http::Message *msg)
{
assert(msg);
doCallouts();
}
+void
+ClientHttpRequest::callException(const std::exception &ex)
+{
+ if (const auto clientConn = getConn() ? getConn()->clientConnection : nullptr) {
+ if (Comm::IsConnOpen(clientConn)) {
+ debugs(85, 3, "closing after exception: " << ex.what());
+ clientConn->close(); // initiate orderly top-to-bottom cleanup
+ return;
+ }
+ }
+ debugs(85, DBG_IMPORTANT, "ClientHttpRequest exception without connection. Ignoring " << ex.what());
+ // XXX: Normally, we mustStop() but we cannot do that here because it is
+ // likely to leave Http::Stream and ConnStateData with a dangling http
+ // pointer. See r13480 or XXX in Http::Stream class description.
+}
#endif
// XXX: modify and use with ClientRequestContext::clientAccessCheckDone too.