2013-06-06 14 views
10

Nasze środowisko wymaga użycia zewnętrznego serwera proxy dla usług zewnętrznych. Zwykle nie stanowi to problemu. W takim przypadku w przypadku Twilio zwracany dodatkowy nagłówek powoduje zerwanie klienta.Co zrobić z dodatkowym nagłówkiem HTTP z serwera proxy?

nagłówki wychodzące:

POST /2010-04-01/Accounts/FOO/SMS/Messages.json HTTP/1.1 
Authorization: Basic FOO== 
User-Agent: twilio-php/3.10.0 
Host: api.twilio.com 
Accept: */* 
Accept-Charset: utf-8 
Content-Type: application/x-www-form-urlencoded 
Content-Length: 108 

nagłówki odpowiedzi:

HTTP/1.0 200 Connection established 

HTTP/1.1 201 Created 
Server: nginx 
Date: Thu, 06 Jun 2013 14:39:24 GMT 
Content-Type: application/json; charset=utf-8 
Content-Length: 551 
Connection: close 
X-Powered-By: PHP/5.3.11 

Mogę tylko przypuszczać, pełnomocnik jest dodanie dodatkowego nagłówka HTTP.

Twilio klient musi sprawdzić:

list($head, $body) = ($parts[0] == 'HTTP/1.1 100 Continue') 

Jak rozumiem, są chwile, lub wersje curl, która będzie automatycznie dodać Expect nagłówka w żądaniu, a HTTP 100 będzie zwrócony w odpowiedź, ale w tym przypadku tak nie jest, a odpowiedź wynosi 200 Połączenie ustanowione. Na co warto dodać pustego Oczekiwano: lub Oczekiwano: boczek nie zmienił wyników.

Naprawdę wolałbym nie włamać się tutaj zbytnio do klienta Twilio, a szczególnie chciałbym uniknąć dodania || $ parts [0] == 'HTTP/1.0 200 Połączenie ustanowione "ponieważ wygląda na to, że jest brudny.

Czy można wysłać nagłówek żądania, który ukryje dodatkowy nagłówek? Lub, opcja zwijania nie zamierzam tego zignorować?

Pełnomocnik wychodzące jest Linux/Squid

+1

to mnie naprawdę zaskoczyło. –

+0

@ TheSurrican co to jest? – somedev

+0

zgodnie ze specyfikacją istnieje tylko jeden "wiersz statusu" w odpowiedzi http, a następnie definicje nagłówków. to znaczy, jeśli dobrze to przeczytam ... http://www.w3.org/Protocols/rfc2616/rfc2616-sec6.html#sec6 –

Odpowiedz

13

Kwestia proxy jest czymś dużo skryptów stoją. Preferowanym rozwiązaniem, które mogę znaleźć w Internecie, jest dodanie następujących wierszy kodu.

<?php 
// cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string 
if (false !== stripos($response, "HTTP/1.0 200 Connection established\r\n\r\n")) { 
    $response = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $response); 
} 
?> 

Teraz, aby dodać to do klienta twilio, byłoby trochę nieporządnie. Na szczęście możesz użyć przestrzeni nazw do odtworzenia natywnych funkcji. Zobacz następujący przykład.

<?php 
namespace FakeCurl; 

//create curl_exec function with same name, but its created in the FakeCurl namespace now. 
function curl_exec($ch) { 
    //execute the actual curl_exec function in the main namespace 
    $response = \curl_exec($ch); 

    // cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string 
    if (false !== stripos($response, "HTTP/1.0 200 Connection established\r\n\r\n")) { 
    $response = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $response); 
    } 

    return "ADDED TO RESPONSE\r\n\r\n".$response; 
} 

//make a regular curl request, no alterations. 

$curl = curl_init(); 
curl_setopt_array($curl, array(
    CURLOPT_HEADER => true, 
    CURLOPT_NOBODY => true, 
    CURLOPT_RETURNTRANSFER => true, 
    CURLOPT_URL => 'http://stackoverflow.com')); 
$response = curl_exec($curl); 
curl_close($curl); 

echo '<pre>'.$response.'</pre>'; 

?> 

Wyjście

ADDED TO RESPONSE 

HTTP/1.1 200 OK 
Cache-Control: public, max-age=11 
Content-Length: 191951 
Content-Type: text/html; charset=utf-8 
Expires: Wed, 12 Jun 2013 07:09:02 GMT 
Last-Modified: Wed, 12 Jun 2013 07:08:02 GMT 
Vary: * 
X-Frame-Options: SAMEORIGIN 
Date: Wed, 12 Jun 2013 07:08:49 GMT 

więc korzystać z klientem Twilio, trzeba umieścić na samym początku skryptu następujące:

<?php 
namespace FakeCurl; 
function curl_exec($ch) { 
    $response = \curl_exec($ch); 

    // cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string 
    if (false !== stripos($response, "HTTP/1.0 200 Connection established\r\n\r\n")) { 
    $response = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $response); 
    } 

    return $response; 
} 

include("twilio.php"); 
?> 

Jeżeli opcja nazw nie dla z jakiegoś powodu dodałem prostą funkcję poza klientem twilio.

<?php 
function fixProxyResponse($response) { 
    // cURL automatically handles Proxy rewrites, remove the "HTTP/1.0 200 Connection established" string 
    if (false !== stripos($response, "HTTP/1.0 200 Connection established\r\n\r\n")) { 
    $response = str_ireplace("HTTP/1.0 200 Connection established\r\n\r\n", '', $response); 
    } 

    return $response; 
} 

A potem zmieniać skrypt Twilio TinyHttp.php i zmienić tylko następującą linię (~ linenr 63)

if ($response = curl_exec($curl)) { 
    $parts = explode("\r\n\r\n", $response, 3); 
    list($head, $body) = ($parts[0] == 'HTTP/1.1 100 Continue') 

do

if ($response = curl_exec($curl)) { 
    $parts = explode("\r\n\r\n", fixProxyResponse($response), 3); 
    list($head, $body) = ($parts[0] == 'HTTP/1.1 100 Continue') 
+0

Musisz czekać godzinę, by nagrodzić, ale dzięki. Potwierdziłeś moje myśli, że nie mogę uciec od modyfikacji kodu TinyHttp z Twilio, a ja po prostu pójdę do przodu. – somedev

+1

Zawsze dobrze jest poczekać do końca nagrody. Czasami ludzie wymyślają świetne rozwiązania, gdy znajdują się na szczycie listy. –

+0

Dobra rada, jeszcze raz dziękuję – somedev

3

Niektóre bardzo późno wyjaśnienie. Gdy łączysz się z serwerem SSL/TLS za pośrednictwem serwera proxy, serwer proxy tworzy tunel za pomocą protokołu HTTP CONNECT. Obejmuje to RFC2817 i wygasła tunneling spec, a nie RFC2616.

Oryginalna specyfikacja tunelowania wymagała, aby serwer proxy zwrócił "200 połączeń nawiązanych" do klienta po pomyślnym połączeniu się z serwerem, co właśnie widzisz. Po tym potencjalnie następuje więcej nagłówków, a następnie pusta linia, zanim połączenie stanie się przezroczyste i otrzymasz faktyczną odpowiedź z serwera. Otrzymujesz dwa zestawy nagłówków. RFC 2817 rozluźnia to i umożliwia dowolną odpowiedź 2xx na żądanie CONNECT.

Co oznacza w skrócie, że nie można polegać na wykrywaniu i usuwaniu pojedynczej linii nagłówka za pomocą kodu php powyżej. Może istnieć więcej niż jedna linia, a pierwsza linia może nie mieć kodu 200 i może nie zawierać łańcucha "nawiązanie połączenia". Musisz być przygotowany na wykrycie dwóch pełnych zestawów nagłówków.

cURL usunął początkową odpowiedź połączenia do 7.11.1 w 2004 roku, ale teraz wysyła wszystko z powrotem do klienta. Aby uzyskać szczegółowe informacje, patrz here.