I've got a piece of code (let's name it Code A) working in a framework and I want to make it work in another framework. The working piece of code makes a successful POST request using CURL like this (request with CURLOPT_VERBOSE on):
* Connected to android.clients.google.com (216.58.209.238) port 443 (#0) * ALPN, offering http/1.1 * Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH * successfully set certificate verify locations: * CAfile: /Applications/MAMP/Library/OpenSSL/cert.pem CApath: none * SSL connection using TLSv1.2 / ECDHE-ECDSA-AES128-GCM-SHA256 * ALPN, server accepted to use http/1.1 * Server certificate: * subject: C=US; ST=California; L=Mountain View; O=Google Inc; CN=*.google.com * start date: Jan 18 19:17:59 2017 GMT * expire date: Apr 12 18:51:00 2017 GMT * subjectAltName: host "android.clients.google.com" matched cert's "android.clients.google.com" * issuer: C=US; O=Google Inc; CN=Google Internet Authority G2 * SSL certificate verify ok. > POST /auth HTTP/1.1 Host: android.clients.google.com Accept: */* Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Content-Length: 97
The http framework here (yii2/httpclient, to be specific) has too many dependencies to bring it to the other project so I'm trying to recreate it on low level like this (let's name it Code B):
<?php $ch = curl_init(); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, 'post-data-here'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_URL, 'https://android.clients.google.com/auth'); curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/x-www-form-urlencoded; charset=UTF-8"]); // just because I'm desperate curl_setopt($ch, CURLOPT_VERBOSE, true); $content = curl_exec($ch);
I'm expecting that to have the same result, but this is what I get:
* Connected to android.clients.google.com (216.58.209.238) port 443 (#0) * TLS 1.2 connection using TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 * Server certificate: *.google.com * Server certificate: Google Internet Authority G2 * Server certificate: GeoTrust Global CA > POST /auth HTTP/1.1 Host: android.clients.google.com Accept: */* Content-Type: application/x-www-form-urlencoded; charset=UTF-8 Content-Length: 97 * upload completely sent off: 97 out of 97 bytes < HTTP/1.1 200 OK < Content-Type: text/plain; charset=utf-8 < Cache-Control: no-cache, no-store, max-age=0, must-revalidate < Pragma: no-cache < Expires: Mon, 01 Jan 1990 00:00:00 GMT < Date: Fri, 27 Jan 2017 12:07:12 GMT < X-Content-Type-Options: nosniff < X-Frame-Options: SAMEORIGIN < X-XSS-Protection: 1; mode=block < Server: GSE < Alt-Svc: clear < Accept-Ranges: none < Vary: Accept-Encoding < Transfer-Encoding: chunked <HTML> <HEAD> <TITLE>HTTP Version Not Supported</TITLE> </HEAD> <BODY BGCOLOR="#FFFFFF" TEXT="#000000"> <H1>HTTP Version Not Supported</H1> <H2>Error 505</H2> </BODY> </HTML>
And instead of a valid response I get "Error 505: HTTP Version Not Supported". The only difference I see is that the working code tries to "ALPN, offering http/1.1" while the latter code doesn't do that. And the certificate part after that, but it's never ever mentioned in code A so I'm not sure what does it do to provide it.
Both versions of code run on the same server, same version of PHP (5.6) and CURL (7.51.0). The difference in verbose log starts BEFORE any data being sent, so I guess it's not about any data or headers being set incorrectly.
What I tried so far (with little or no effect):
I've tried to learn the working code as deep as I could but it seems that it doesn't do anything over the simple HTTP POST. I tracked every curl_setopt it makes and it seems there are only these curl_setopt I used in my code, nothing extra. Still, it works and my code doesn't.
I've tried making the same using the command line:
$ curl https://android.clients.google.com/auth -v --http1.1 -X POST --no-alpn --no-npn --data "copypasted-post-data-from-code-B-and-yes-its-urlencoded"
Got the correct result:
* Trying 216.58.209.238... * TCP_NODELAY set * Connected to android.clients.google.com (216.58.209.238) port 443 (#0) * Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH * successfully set certificate verify locations: * CAfile: /Applications/MAMP/Library/OpenSSL/cert.pem CApath: none ... > POST /auth HTTP/1.1 > Host: android.clients.google.com > User-Agent: curl/7.51.0 > Accept: */* > Content-Length: 97 > Content-Type: application/x-www-form-urlencoded > * upload completely sent off: 97 out of 97 bytes < HTTP/1.1 200 OK < Content-Type: text/plain; charset=utf-8 < Cache-Control: no-cache, no-store, max-age=0, must-revalidate < Pragma: no-cache < Expires: Mon, 01 Jan 1990 00:00:00 GMT < Date: Fri, 27 Jan 2017 13:22:27 GMT < X-Content-Type-Options: nosniff < X-Frame-Options: SAMEORIGIN < X-XSS-Protection: 1; mode=block < Server: GSE < Alt-Svc: clear < Accept-Ranges: none < Vary: Accept-Encoding < Transfer-Encoding: chunked < SID=BAD_COOKIE LSID=BAD_COOKIE Auth=here-s-the-data-i-need
To make a GET request using Curl, run the curl command followed by the target URL. Curl automatically selects the HTTP GET request method unless you use the -X, --request, or -d command-line option.
curl defaults to HTTP/1.1 for HTTP servers but if you connect to HTTPS and you have a curl that has HTTP/2 abilities built-in, it attempts to negotiate HTTP/2 automatically or falls back to 1.1 in case the negotiation failed. Non-HTTP/2 capable curls get 1.1 over HTTPS by default.
From Chrome and Edge On the line of the specific resource you are interested in, you right-click with the mouse and you select "Copy as cURL" and it will generate a command line for you in your clipboard. Paste that in a shell to get a curl command line that makes the transfer.
The syntax for the curl command is as follows: curl [options] [URL...] In its simplest form, when invoked without any option, curl displays the specified resource to the standard output. The command will print the source code of the example.com homepage in your terminal window.
Error 505: HTTP Version Not Supported
is not an error string that is returned by curl/libcurl, that sounds like content that you receive from the server you're communicating with. If you would show us the full HTTP response including headers, we could probably have seen that.
So, all your playing around with different curl options was to no gain because curl worked fine every single time. You could also verify that with using the curl command line tool against the host you're trying to get to work:
curl https://android.clients.google.com/auth -v --http1.1 -X POST --no-alpn --no-npn
This command line shows that both the TLS and HTTP "layers" are fine.
Another question here got a similar error when they passed in the wrong data (not url encoded). Maybe you have something similar and because of your switch to a new framework you missed it?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With