如何强制CURL请求http / 1.1?也许还有另一个问题,不确定 [英] How to force CURL to ask for http/1.1? Or maybe there's another issue, not sure

查看:269
本文介绍了如何强制CURL请求http / 1.1?也许还有另一个问题,不确定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一个框架中有一段代码(即代码A),我想使其在另一个框架中工作。该代码段使用CURL发出了这样的成功POST请求(使用CURLOPT_VERBOSE的请求):

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

此处的http框架(yii2 / httpclient,具体来说)具有太多的依赖关系,无法将其带到另一个项目,因此我正在尝试像这样在较低级别上重新创建它(我们将其命名为代码B):

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>

而不是有效的响应,我收到错误505:不支持HTTP版本。我看到的唯一区别是,工作代码尝试使用 ALPN,提供http / 1.1,而后者则没有。然后是证书部分,但是代码A中从未提及过它,所以我不确定它提供了什么。

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.

两个版本的代码都在上面运行同一台服务器,同一版本的PHP(5.6)和CURL(7.51.0)。详细日志的区别始于发送任何数据之前,因此我想这与任何数据或标头设置不正确有关。

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):


  1. curl_setopt($ ch,CURLOPT_SSL_ENABLE_ALPN,等等)-不起作用,因为根本没有定义CURLOPT_SSL_ENABLE_ALPN(尽管必须定义)处于此版本的CURL中,不知道出了什么问题)

  2. curl_setopt($ ch,CURLOPT_SSL_VERIFYPEER,无论如何)

  3. curl_setopt($ ch,CURLOPT_SSL_VERIFYHOST,

  4. curl_setopt($ ch,CURLOPT_SSLVERSION,等等)

  5. 其他一些绝望的愚蠢的东西,我很as愧在这里展示

  1. curl_setopt($ch, CURLOPT_SSL_ENABLE_ALPN, whatever) - does not work because CURLOPT_SSL_ENABLE_ALPN is not defined at all (although it must be in this version of CURL, not sure what's wrong)
  2. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, whatever)
  3. curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, whatever)
  4. curl_setopt($ch, CURLOPT_SSLVERSION, whatever)
  5. some other desperate silly stuff I'm even ashamed to show here

我尝试了尽可能深入地学习工作代码,但似乎它在简单的HTTP POST上没有任何作用。我跟踪了它产生的每个curl_setopt,似乎我的代码中只使用了这些curl_setopt,没有什么多余的。

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"

得到正确的结果:

*   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


推荐答案

好的,我知道了。

实际上,在那段代码之前在代码B中,使用另一个库(准确地说是Httpful)执行了另一个请求,并且该请求似乎以某种方式弄乱了事情。我不知道有什么事情会影响使用clean curl_init()执行的请求。

Actually, BEFORE that piece of code in Code B there was another request executed using yet another library (Httpful, to be exact) and it seems that request messed things up somehow. I did not know that something can affect a request performed with a clean curl_init().

无论如何,当我将所有有问题的Httpful调用替换为低之前级别的设备,一切正常。

Anyway, when I replaced all those Httpful calls prior to the request in question with low level ones, everything worked fine.

这篇关于如何强制CURL请求http / 1.1?也许还有另一个问题,不确定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆