CodeIgniter4
CodeIgniter4 copied to clipboard
Bug: [CURLRequest] body contains "HTTP/1.0 200 Connection established"
PHP Version
8.1
CodeIgniter4 Version
4.4.4
CodeIgniter4 Installation Method
Composer (using codeigniter4/appstarter
)
Which operating systems have you tested for this bug?
Windows
Which server did you use?
apache
Database
No response
What happened?
$response = $this->curlClient->request('POST', $url); echo $response->getBody();
Body return this
HTTP/1.0 200 Connection established HTTP/1.1 200 OK referrer-policy: no-referrer x-frame-options: SAMEORIGIN strict-transport-security: max-age=16070400; includeSubDomains cache-control: no-store x-content-type-options: nosniff set-cookie: KC_RESTART=; Version=1; Expires=Thu, 01-Jan-1970 00:00:10 GMT; Max-Age=0; Path=/a/; Secure; HttpOnlyHttpOnly;SameSite=none; Secure pragma: no-cache x-xss-protection: 1; mode=block content-type: application/json content-length: 2684 x-envoy-upstream-service-time: 38 date: Wed, 07 Feb 2024 07:06:40 GMT server: istio-envoy
{"data":1,"expires_in":1800}
Steps to Reproduce
$response = $this->curlClient->request('POST', $url); echo $response->getBody();
Expected Output
echo $response->getBody(); == {"data":1,"expires_in":1800}
I understand that getBody returns all the information returned by the server. But I guess it should be that $response->headers() returns the headers and $response->getBody() returns the data.
Anything else?
executing curl from the command line returns only data correctly. Postman also returns the data correctly
Thank you for reporting! But we cannot reproduce the issue. Can you show the exact steps to reproduce the issue?
I changed
if (strpos($output, 'HTTP/1.1 100 Continue') === 0) { $output = substr($output, strpos($output, $breakString) + 4); }
if (strpos($output, 'HTTP/1.1 200 Connection established') === 0) {
$output = substr($output, strpos($output, $breakString) + 4);
}
to
if (strpos($output, 'HTTP/1.0 100 Continue') === 0) { $output = substr($output, strpos($output, $breakString) + 4); }
if (strpos($output, 'HTTP/1.0 200 Connection established') === 0) {
$output = substr($output, strpos($output, $breakString) + 4);
}
and it works properly
see what header the server returns
HTTP/1.0 200 Connection established HTTP/1.1 200 OK
As part of the explanation. The protocol header can take several values https://everything.curl.dev/http/versions HTTP/1.0 100 Continue HTTP/1.0 200 Connection established HTTP/1.1 100 Continue HTTP/1.1 200 Connection established HTTP/2 100 Continue HTTP/2 200 Connection established HTTP/3 100 Continue HTTP/3 200 Connection established
and in the code we have it rigid
if (strpos($output, 'HTTP/1.1 100 Continue') === 0) { $output = substr($output, strpos($output, $breakString) + 4); }
This code reuest to www.google.pl return HTTP/1.0 200 Connection established HTTP/2 200
$client = \Config\Services::curlrequest();
$options = [
'http_errors' => false,
'debug' => true,
'proxy' => 'ip_proxy',
];
$adr ='https://www.google.pl';
$response = $client->request('GET', $adr, $options);
foreach ($response->headers() as $name => $value) {
echo $name . ': ' . $response->getHeaderLine($name) . "\n";
}
echo $response->getBody();
Cannot reproduce. Why do you still use HTTP/1.0
?
$ docker pull ubuntu/squid
$ docker run -d --name squid-container -e TZ=UTC -p 3128:3128 ubuntu/squid
$ curl -v --proxy http://localhost:3128 https://www.google.pl
* Host localhost:3128 was resolved.
* IPv6: ::1
* IPv4: 127.0.0.1
* Trying [::1]:3128...
* Connected to localhost (::1) port 3128
* CONNECT tunnel: HTTP/1.1 negotiated
* allocate connect buffer
* Establish HTTP proxy tunnel to www.google.pl:443
> CONNECT www.google.pl:443 HTTP/1.1
> Host: www.google.pl:443
> User-Agent: curl/8.5.0
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 200 Connection established
<
* CONNECT phase completed
* CONNECT tunnel established, response 200
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / x25519 / id-ecPublicKey
* ALPN: server accepted h2
* Server certificate:
* subject: CN=*.google.pl
* start date: Jan 9 06:34:13 2024 GMT
* expire date: Apr 2 06:34:12 2024 GMT
* subjectAltName: host "www.google.pl" matched cert's "*.google.pl"
* issuer: C=US; O=Google Trust Services LLC; CN=GTS CA 1C3
* SSL certificate verify ok.
* Certificate level 0: Public key type EC/prime256v1 (256/128 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 1: Public key type RSA (2048/112 Bits/secBits), signed using sha256WithRSAEncryption
* Certificate level 2: Public key type RSA (4096/152 Bits/secBits), signed using sha384WithRSAEncryption
* using HTTP/2
* [HTTP/2] [1] OPENED stream for https://www.google.pl/
* [HTTP/2] [1] [:method: GET]
* [HTTP/2] [1] [:scheme: https]
* [HTTP/2] [1] [:authority: www.google.pl]
* [HTTP/2] [1] [:path: /]
* [HTTP/2] [1] [user-agent: curl/8.5.0]
* [HTTP/2] [1] [accept: */*]
> GET / HTTP/2
> Host: www.google.pl
> User-Agent: curl/8.5.0
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
< HTTP/2 200
< date: Thu, 08 Feb 2024 02:33:26 GMT
< expires: -1
< cache-control: private, max-age=0
< content-type: text/html; charset=ISO-8859-2
< content-security-policy-report-only: object-src 'none';base-uri 'self';script-src 'nonce-iP9bOGIZesCEhajHCzCyYg' 'strict-dynamic' 'report-sample' 'unsafe-eval' 'unsafe-inline' https: http:;report-uri https://csp.withgoogle.com/csp/gws/other-hp
< p3p: CP="This is not a P3P policy! See g.co/p3phelp for more info."
< server: gws
< x-xss-protection: 0
< x-frame-options: SAMEORIGIN
< set-cookie: 1P_JAR=2024-02-08-02; expires=Sat, 09-Mar-2024 02:33:26 GMT; path=/; domain=.google.pl; Secure
< set-cookie: AEC=Ae3NU9PVS9ERTsF4MBaHEHkFIpmqIbkOuLRcgNpHYHUUBRKYAD0stHx2Sok; expires=Tue, 06-Aug-2024 02:33:26 GMT; path=/; domain=.google.pl; Secure; HttpOnly; SameSite=lax
< set-cookie: NID=511=UfuEJr8IAiuabesErKhUm8XK_shijk-0oa_lw1ouTTKbhvhOVvlTSmnR_D3d_VTJwbVZu-0CIDzCYlUliNZmDphIXDndV_DCmDKc-asSmjILCQ7DB4cHQEjAE9EO9TDl9Ts17qhOiHraSA1LHHF-Fz8_E0o9cMc0SokTdcALKR8; expires=Fri, 09-Aug-2024 02:33:26 GMT; path=/; domain=.google.pl; HttpOnly
< alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
< accept-ranges: none
< vary: Accept-Encoding
<
<!doctype html>...
I admit that my case is isolated. I deliberately don't use HTTP/1.0. I connect to different external services through different proxies and one of them uses an old protocol. I have no influence on it. But Codeigniter shouldn't be limited to just one HTTP/1.1 This piece of code solves my problem
if (preg_match('/HTTP\/\d\.\d 200 Connection established/', $output)) {
$output = substr($output, strpos($output, $breakString) + 4);
}
I'm not the only one who has this problem. The problem is that the proxy returns its own header and the curl library returns too much https://stackoverflow.com/questions/16965530/what-to-do-with-extra-http-header-from-proxy https://github.com/cfug/dio/issues/2053
A small update. I migrated from 4.4.4 to 4.5.1. My proxy sends headers:
HTTP/1.0 200 Connection established
HTTP/1.1 200 OK
cache-control: no-store
pragma: no-cache
content-length: 2684
content-type: application/json
\vendor\codeigniter4\framework\system\HTTP\CURLRequest.php
Line 392 in version 4.5.1 has been changed to :
if (str_starts_with($output, 'HTTP/1.1 200 Connection established')) {
$output = substr($output, strpos($output, $breakString) + 4);
}
But the problem was not solved My solution also stopped working
Don't set it rigidly. str_starts_with($output, 'HTTP/1.1 200 Connection established') The protocol will change and there will be a problem