Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

claudsonm's avatar

Http Client with proxy working only on first request

  1. Make a get request to some URL using the \Illuminate\Support\Facades\Http with a proxy setup;
  2. The request goes through the proxy and hits the destination server. I can see the IP received belongs to the proxy and not to my machine. (Everything working fine so far);
  3. Make that same request again;
  4. The IP received by the destination server belongs to my machine. The proxy is not working anymore.

See the tinker output:

my-aws-docker-user@fb14363368ff:/var/www/html$ php artisan tinker
Psy Shell v0.10.4 (PHP 7.4.10 — cli) by Justin Hileman

>>> $credentials = "http://54.234.XXX.XX:808";
=> "http://54.234.XXX.XX:808"

>>> \Illuminate\Support\Facades\Http::withOptions(['proxy' => $credentials, 'debug' => true])->get('https://api.ipify.org/')->body();

* Expire in 0 ms for 6 (transfer 0x560ff2ad7d30)
* Expire in 150000 ms for 2 (transfer 0x560ff2ad7d30)
*   Trying 54.234.XXX.XX...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x560ff2ad7d30)
* Connected to 54.234.XX.XX (54.234.XXX.XX) port 808 (#0)
* allocate connect buffer!
* Establish HTTP proxy tunnel to api.ipify.org:443
> CONNECT api.ipify.org:443 HTTP/1.1
Host: api.ipify.org:443
Proxy-Connection: Keep-Alive

< HTTP/1.1 200 Connection established
< Proxy-agent: CCProxy
<
* Proxy replied 200 to CONNECT request
* CONNECT phase completed!
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* CONNECT phase completed!
* CONNECT phase completed!
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: OU=Domain Control Validated; OU=PositiveSSL Wildcard; CN=*.ipify.org
*  start date: Jan 24 00:00:00 2018 GMT
*  expire date: Jan 23 23:59:59 2021 GMT
*  subjectAltName: host "api.ipify.org" matched cert's "*.ipify.org"
*  issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Domain Validation Secure Server CA
*  SSL certificate verify ok.
> GET / HTTP/1.1
Host: api.ipify.org
User-Agent: GuzzleHttp/6.5.5 curl/7.64.0 PHP/7.4.10

< HTTP/1.1 200 OK
< Server: Cowboy
< Connection: keep-alive
< Content-Type: text/plain
< Vary: Origin
< Date: Tue, 29 Sep 2020 20:10:22 GMT
< Content-Length: 13
< Via: 1.1 vegur
<
* Connection #0 to host 54.234.XXX.XX left intact

=> "54.234.XXX.XX" // This is my proxy IP

The first request works good. Now performing the same one in the same tinker session (arrow up + enter):

>>> \Illuminate\Support\Facades\Http::withOptions(['proxy' => $credentials, 'debug' => true])->get('https://api.ipify.org/')->body();

* Expire in 0 ms for 6 (transfer 0x560ff2addc90)
* Expire in 150000 ms for 2 (transfer 0x560ff2addc90)
* Expire in 1 ms for 1 (transfer 0x560ff2addc90)
* Expire in 0 ms for 1 (transfer 0x560ff2addc90)
* Expire in 1 ms for 1 (transfer 0x560ff2addc90)
* Expire in 0 ms for 1 (transfer 0x560ff2addc90)
* Expire in 0 ms for 1 (transfer 0x560ff2addc90)
* Expire in 2 ms for 1 (transfer 0x560ff2addc90)
* Expire in 0 ms for 1 (transfer 0x560ff2addc90)
* Expire in 0 ms for 1 (transfer 0x560ff2addc90)
* Expire in 2 ms for 1 (transfer 0x560ff2addc90)
* Expire in 0 ms for 1 (transfer 0x560ff2addc90)
* Expire in 0 ms for 1 (transfer 0x560ff2addc90)
* Expire in 2 ms for 1 (transfer 0x560ff2addc90)
* Expire in 0 ms for 1 (transfer 0x560ff2addc90)
* Expire in 0 ms for 1 (transfer 0x560ff2addc90)
* Expire in 2 ms for 1 (transfer 0x560ff2addc90)
* Expire in 0 ms for 1 (transfer 0x560ff2addc90)
* Expire in 0 ms for 1 (transfer 0x560ff2addc90)
* Expire in 2 ms for 1 (transfer 0x560ff2addc90)
* Expire in 0 ms for 1 (transfer 0x560ff2addc90)
* Expire in 0 ms for 1 (transfer 0x560ff2addc90)
* Expire in 2 ms for 1 (transfer 0x560ff2addc90)
* Expire in 1 ms for 1 (transfer 0x560ff2addc90)
* Expire in 1 ms for 1 (transfer 0x560ff2addc90)
* Expire in 2 ms for 1 (transfer 0x560ff2addc90)
* Expire in 1 ms for 1 (transfer 0x560ff2addc90)
* Expire in 1 ms for 1 (transfer 0x560ff2addc90)
* Expire in 4 ms for 1 (transfer 0x560ff2addc90)
* Expire in 2 ms for 1 (transfer 0x560ff2addc90)
* Expire in 2 ms for 1 (transfer 0x560ff2addc90)
* Expire in 4 ms for 1 (transfer 0x560ff2addc90)
* Expire in 2 ms for 1 (transfer 0x560ff2addc90)
* Expire in 2 ms for 1 (transfer 0x560ff2addc90)
* Expire in 4 ms for 1 (transfer 0x560ff2addc90)
* Expire in 3 ms for 1 (transfer 0x560ff2addc90)
* Expire in 3 ms for 1 (transfer 0x560ff2addc90)
* Expire in 4 ms for 1 (transfer 0x560ff2addc90)
* Expire in 3 ms for 1 (transfer 0x560ff2addc90)
* Expire in 3 ms for 1 (transfer 0x560ff2addc90)
* Expire in 4 ms for 1 (transfer 0x560ff2addc90)
* Expire in 4 ms for 1 (transfer 0x560ff2addc90)
* Expire in 4 ms for 1 (transfer 0x560ff2addc90)
* Expire in 4 ms for 1 (transfer 0x560ff2addc90)
* Expire in 5 ms for 1 (transfer 0x560ff2addc90)
* Expire in 5 ms for 1 (transfer 0x560ff2addc90)
* Expire in 4 ms for 1 (transfer 0x560ff2addc90)
* Expire in 6 ms for 1 (transfer 0x560ff2addc90)
* Expire in 6 ms for 1 (transfer 0x560ff2addc90)
* Expire in 8 ms for 1 (transfer 0x560ff2addc90)
* Expire in 7 ms for 1 (transfer 0x560ff2addc90)
* Expire in 7 ms for 1 (transfer 0x560ff2addc90)
* Expire in 8 ms for 1 (transfer 0x560ff2addc90)
* Expire in 8 ms for 1 (transfer 0x560ff2addc90)
* Expire in 8 ms for 1 (transfer 0x560ff2addc90)
* Expire in 16 ms for 1 (transfer 0x560ff2addc90)
* Expire in 10 ms for 1 (transfer 0x560ff2addc90)
* Expire in 10 ms for 1 (transfer 0x560ff2addc90)
* Expire in 16 ms for 1 (transfer 0x560ff2addc90)
* Expire in 11 ms for 1 (transfer 0x560ff2addc90)
* Expire in 11 ms for 1 (transfer 0x560ff2addc90)
* Expire in 16 ms for 1 (transfer 0x560ff2addc90)
* Expire in 14 ms for 1 (transfer 0x560ff2addc90)
* Expire in 14 ms for 1 (transfer 0x560ff2addc90)
* Expire in 15 ms for 1 (transfer 0x560ff2addc90)
*   Trying 23.21.203.47...
* TCP_NODELAY set
* Expire in 74977 ms for 3 (transfer 0x560ff2addc90)
* Expire in 200 ms for 4 (transfer 0x560ff2addc90)
* Connected to api.ipify.org (23.21.203.47) port 443 (#0)
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: OU=Domain Control Validated; OU=PositiveSSL Wildcard; CN=*.ipify.org
*  start date: Jan 24 00:00:00 2018 GMT
*  expire date: Jan 23 23:59:59 2021 GMT
*  subjectAltName: host "api.ipify.org" matched cert's "*.ipify.org"
*  issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Domain Validation Secure Server CA
*  SSL certificate verify ok.
> GET / HTTP/1.1
Host: api.ipify.org
User-Agent: GuzzleHttp/6.5.5 curl/7.64.0 PHP/7.4.10

< HTTP/1.1 200 OK
< Server: Cowboy
< Connection: keep-alive
< Content-Type: text/plain
< Vary: Origin
< Date: Tue, 29 Sep 2020 20:11:26 GMT
< Content-Length: 11
< Via: 1.1 vegur
<
* Connection #0 to host api.ipify.org left intact

=> "3.92.XX.XXX" // This is my instance IP
  • The application is running in a docker container hosted in a EC2 Instance on AWS;
  • The problem seems to occur only on AWS;
  • The proxy server is working fine. We tried Squid Cache Proxy and CCProxy and both have the same issue;
  • Performing a cURL request from the docker container on AWS also works (see logs below).
my-aws-docker-user@fb14363368ff:/var/www/html$ curl -x http://54.234.XXX.XX:808 -L https://api.ipify.org/ -v
* Expire in 0 ms for 6 (transfer 0x55abb8f38f50)
*   Trying 54.234.XXX.XX...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x55abb8f38f50)
* Connected to 54.234.XXX.XX (54.234.XXX.XX) port 808 (#0)
* allocate connect buffer!
* Establish HTTP proxy tunnel to api.ipify.org:443
> CONNECT api.ipify.org:443 HTTP/1.1
> Host: api.ipify.org:443
> User-Agent: curl/7.64.0
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 Connection established
< Proxy-agent: CCProxy
<
* Proxy replied 200 to CONNECT request
* CONNECT phase completed!
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: none
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* CONNECT phase completed!
* CONNECT phase completed!
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server did not agree to a protocol
* Server certificate:
*  subject: OU=Domain Control Validated; OU=PositiveSSL Wildcard; CN=*.ipify.org
*  start date: Jan 24 00:00:00 2018 GMT
*  expire date: Jan 23 23:59:59 2021 GMT
*  subjectAltName: host "api.ipify.org" matched cert's "*.ipify.org"
*  issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Domain Validation Secure Server CA
*  SSL certificate verify ok.
> GET / HTTP/1.1
> Host: api.ipify.org
> User-Agent: curl/7.64.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: Cowboy
< Connection: keep-alive
< Content-Type: text/plain
< Vary: Origin
< Date: Tue, 29 Sep 2020 20:32:25 GMT
< Content-Length: 13
< Via: 1.1 vegur
<
* Connection #0 to host 54.234.XXX.XX left intact
54.234.XXX.XX // This is my proxy IP
0 likes
5 replies
laracoft's avatar

@claudsonm the info provided is quite hard to follow, but what are you suspecting?

  1. GuzzleHttp?
  2. Proxy?

I'm much more inclined to believe it is the Proxy or possibly the network. Can you try another proxy? Or another network to narrow down the culprit?

If you think it's Guzzle, have you tried cURL?

claudsonm's avatar

As I said,

Performing a cURL request from the docker container on AWS also works (see logs below).

It looks like it's something related with Laravel running on AWS. Never tried to call guzzle directly. The way we are doing right now is to use a custom facade, instead of \Illuminate\Support\Facades\Http, performing Facade::clearResolvedInstance(Factory::class); before return in the getFacadeAccessor.

/**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        if (! app()->runningUnitTests()) {
            Facade::clearResolvedInstance(Factory::class);
        }

        return Factory::class;
    }
laracoft's avatar

@claudsonm

Pardon me, but not facing the issue, it's a lot to hold in my mind trying to visualize it.

Now, you mentioned, "working only on first request" and not subsequent.

I suppose you can replicate the problem, how do you get it back to the first request?

Restart the proxy?

claudsonm's avatar

First request is when Laravel performs the first call using the Http::get/post/put. The first one works. The others dont.

The proxy is fine. Like I said: already tried Squid Cache Proxy and CCProxy and I got the same thing.

If in your application lifecycle you make 2 calls using Http::withOptions(['proxy' => $credentials])->get(), only the first one will be proxied.

laracoft's avatar

@claudsonm ok, means in every lifecycle you can only call via a proxy once. 2nd one onward fails. Let me try it out and get back. Starting to sound like Guzzle to me.

Please or to participate in this conversation.