Squid zmienia WSDL?

Z używaniem SOAP-a przez proxy w PHP bywają problemy, o czym już pisałem. Dzisiaj w podobnej sytuacji natknąłem się na inną zagwostkę. Podczas pisania integracji z usługą eraty.pl prosty kod z instrukcji:

$client = new \SoapClient('https://www.eraty.pl:8443/eRatyWSService/eRatyWS?wsdl');
$identyfikacja['login'] = 'ERatyTest';
$identyfikacja['haslo'] = 'ERatyTest!1';
$identyfikacja['numerSklepu'] = 13010005;
$identyfikacja['typProduktu'] = 0;
$identyfikacja['wariantSklepu'] = 1;
try
{
	$result = $client->pobierzLinieKredytowe($identyfikacja);
}
catch (\Exception $e)
{
	echo $e->faultstring;
}

rzucał mi wyjątkiem „Could not connect to host”. Oczywiście zarówno firewall i proxy zezwałały na dostęp do eraty.pl, a ten sam kod uruchomiony na innym serwerze działał bez zająknięcia. Nad znalezieniem rozwiązania trochę musiałem posiedzieć, aż w końcu w stack trace’ie zauważyłem, że metoda SoapClient::__doRequest() jako drugi parametr dostaje http://www.eraty.pl:8080/eRatyWSService/eRatyWS (hint: numer portu). Nie mam pojęcia skąd to się bierze, zakładam, że to coś linii PHP-Squid, ale z tą wiedzą rozwiązanie było proste. Wystarczyło wymusić poprawną lokalizację usługi przy tworzeniu obiektu SoapClient:

$client = new \SoapClient('https://www.eraty.pl:8443/eRatyWSService/eRatyWS?wsdl',
	array('location' => 'https://www.eraty.pl:8443/eRatyWSService/eRatyWS')
	);

Połączenia HTTP z PHP za serwerem proxy

Dzisiaj zmierzyłem się z problemem wywoływania usługi SOAP z poziomu PHP działającego na serwerze schowanym za proxy. Ostatecznie okazało się to prostsze niż myślałem, wystarczy przekazać dodatkowe parametry do konstruktora obiektu SoapClient.

$soap = new SoapClient('http://domena.pl/usluga?wsdl', array(
  'proxy_host' => '10.107.10.69',
  'proxy_port' => 8080,
  'proxy_login' => 'nazwa.uzytkownika',
  'proxy_password' => 'haslo'
  ));

Zabrało mi to jednak trochę czasu bo zacząłem od szukania rozwiązania na niższym poziomie czyli modyfikacji parametrów używanych przez PHP do wykonywania połączeń HTTP. Metodą guglania, prób i błędów dotarłem do takiego rozwiązania, które również działa.

$default = stream_context_get_default(array(
  'http' => array(
    'proxy' => 'tcp://10.107.10.69:8080',
    'request_fulluri' => true,
    'header' => 'Proxy-Authorization: Basic ' . base64_encode('nazwa.uzytkownika:haslo'),
    )
  ));

Dzięki tej metodzie z proxy zaczynają współpracować wszystkie funkcje wykorzystujące protokół HTTP, np. readfile() z plikiem na zdalnym serwerze.

readfile('http://www.google.com/');