@@ -1992,6 +1992,8 @@ class CWSCAsyncFor : implements IWSCAsyncFor, public CInterface, public CAsyncFo
19921992 void createHttpRequest (StringBuffer &request, const Url &url, const IProperties * traceHeaders)
19931993 {
19941994 // Create the HTTP POST request
1995+ // NOTE: if using an http proxy and method is not https then path should be prepended with url host:port
1996+ // but this would break regression tests that use esp as a proxy
19951997 if (master->wscType == STsoap)
19961998 request.clear ().append (" POST " ).append (url.path ).append (" HTTP/1.1\r\n " );
19971999 else
@@ -2517,6 +2519,10 @@ class CWSCAsyncFor : implements IWSCAsyncFor, public CInterface, public CAsyncFo
25172519 checkTimeLimitExceeded (&remainingMS);
25182520 Url &connUrl = master->proxyUrlArray .empty () ? url : master->proxyUrlArray .item (0 );
25192521
2522+ bool useProxy = false ;
2523+ if (!master->proxyUrlArray .empty ())
2524+ useProxy = true ;
2525+
25202526 CCycleTimer dnsTimer;
25212527
25222528 // TODO: for DNS, do we use timeoutMS or remainingMS or remainingMS / maxRetries+1 or ?
@@ -2554,7 +2560,54 @@ class CWSCAsyncFor : implements IWSCAsyncFor, public CInterface, public CAsyncFo
25542560 if (proto == PersistentProtocol::ProtoTLS)
25552561 {
25562562#ifdef _USE_OPENSSL
2557- Owned<ISecureSocket> ssock = master->createSecureSocket (socket.getClear (), connUrl.host );
2563+ if (useProxy && strieq (connUrl.method .str (), " http" ))
2564+ {
2565+ StringBuffer urlHost;
2566+ if (streq (url.host .str (), " ." ))
2567+ urlHost.append (GetCachedHostName ());
2568+ else
2569+ urlHost.append (url.host .str ());
2570+ StringBuffer proxyText;
2571+ proxyText.appendf (" CONNECT %s:%d HTTP/1.1\r\n " , urlHost.str (), url.port );
2572+ proxyText.append (" Proxy-Connection: Keep-Alive\r\n\r\n " );
2573+ socket->write (proxyText.str (),proxyText.length ());
2574+
2575+ checkTimeLimitExceeded (&remainingMS);
2576+ unsigned proxyTimeout = MIN (remainingMS, master->timeoutMS );
2577+ char proxyResponse[MAX_HTTP_HEADERSIZE + 1 ];
2578+ unsigned proxyRemaining = proxyTimeout;
2579+ CTimeMon tm (proxyTimeout);
2580+ unsigned totalRead = 0 ;
2581+ unsigned bytesRead = 0 ;
2582+ bool sockClosed = false ;
2583+ while (!sockClosed && !tm.timedout (&proxyRemaining))
2584+ {
2585+ unsigned maxPoss = MAX_HTTP_HEADERSIZE - totalRead;
2586+ sockClosed = readtmsAllowClose (socket, &proxyResponse[totalRead], 1 , maxPoss, bytesRead, proxyRemaining);
2587+ totalRead += bytesRead;
2588+ proxyResponse[totalRead] = 0 ;
2589+
2590+ if (strstr (proxyResponse, " \r\n\r\n " ))
2591+ break ;
2592+ if (totalRead >= MAX_HTTP_HEADERSIZE)
2593+ break ;
2594+ }
2595+
2596+ if (tm.timedout (&proxyRemaining))
2597+ throw makeStringException (-1 , " Timed out waiting for proxy response" );
2598+
2599+ bool proxyTunnelOK = false ;
2600+ const char *okResp = strstr (proxyResponse, " HTTP/" );
2601+ if (okResp)
2602+ {
2603+ if (strstr (okResp, " 200 " ))
2604+ proxyTunnelOK = true ;
2605+ }
2606+ if (!proxyTunnelOK)
2607+ throw makeStringException (-1 , " Invalid response from proxy" );
2608+ }
2609+
2610+ Owned<ISecureSocket> ssock = master->createSecureSocket (socket.getClear (), url.host );
25582611 if (ssock)
25592612 {
25602613 checkTimeLimitExceeded (&remainingMS);
0 commit comments