J'ai un morceau de code (appelons-le Code A) travaillant dans un cadre et je veux le faire fonctionner dans un autre cadre. Le morceau de code de travail génère une POST requête en utilisant CURL comme ceci (requête avec CURLOPT_VERBOSE activée):
* 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
Le cadre http ici (yii2/httpclient, pour être spécifique) a trop de dépendances pour l'amener à l'autre projet, donc j'essaie de le recréer à bas niveau comme ça (appelons-le 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);
Je m'attends à ce que le résultat soit le même, mais voici ce que j'obtiens:
* 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>
Et au lieu d'une réponse valide, j'obtiens "Erreur 505: Version HTTP non prise en charge". La seule différence que je vois est que le code de travail essaie de "ALPN, offrant http/1.1" alors que le dernier code ne fait pas cela. Et la partie certificat après cela, mais elle n'est jamais mentionnée dans le code A, donc je ne sais pas quoi faire pour le fournir.
Les deux versions de code s'exécutent sur le même serveur, la même version de PHP (5.6) et CURL (7.51.0). La différence dans le journal détaillé commence AVANT toute donnée envoyée, donc je suppose que c'est pas de données ou d'en-têtes mal définis.
Ce que j'ai essayé jusqu'à présent (avec peu ou pas d'effet):
J'ai essayé d'apprendre le code de travail aussi profondément que possible, mais il semble que cela ne fasse rien sur le simple HTTP POST. J'ai suivi chaque curl_setopt qu'il fait et il semble qu'il n'y ait que ces curl_setopt que j'ai utilisés dans mon code, rien de plus. Pourtant, cela fonctionne et mon code ne fonctionne pas.
J'ai essayé de faire la même chose en utilisant la ligne de commande:
$ 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"
Vous avez le bon résultat:
* 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
D'accord, je l'ai compris.
En fait, AVANT ce morceau de code dans le code B, une autre demande a été exécutée à l'aide d'une autre bibliothèque (Httpful, pour être exact) et il semble que cette demande ait gâché les choses. Je ne savais pas que quelque chose pouvait affecter une requête effectuée avec un curl_init () propre.
Quoi qu'il en soit, lorsque j'ai remplacé tous ces appels Httpful avant la demande en question par des appels de bas niveau, tout a bien fonctionné.
Error 505: HTTP Version Not Supported
n'est pas une chaîne d'erreur renvoyée par curl/libcurl, qui ressemble au contenu que vous recevez du serveur avec lequel vous communiquez. Si vous nous montriez la réponse HTTP complète, y compris les en-têtes, nous aurions probablement pu le voir.
Donc, tout votre jeu avec différentes options de boucle était sans gain car la boucle fonctionnait bien à chaque fois. Vous pouvez également vérifier qu'en utilisant l'outil de ligne de commande curl contre l'hôte, vous essayez de travailler:
curl https://Android.clients.google.com/auth -v --http1.1 -X POST --no-alpn --no-npn
Cette ligne de commande montre que les "couches" TLS et HTTP sont correctes.
Une autre question ici a obtenu une erreur similaire quand ils ont passé les mauvaises données (non encodées en URL). Peut-être avez-vous quelque chose de similaire et à cause de votre passage à un nouveau cadre, vous l'avez manqué?