PHP: SOAP-Webservice Fehler – Could not connect to host…

Die Ausgangssituation: Ein Webservice stellt eine Methode „readfile()“ zur verfügung.
Dieser Webservice liegt intern auf einem Server und ist über port 80 zu erreichen.
Um extern auf den Webservice zuzugreifen, wurde der Port 8000 (extern) verwendet und auf Port 80 (Intern) dieses Servers mit dem Webservice weiter geleitet.

Der Client ist ein PHP-Script, welches den Webservice über die Öffentliche (externe) IP konsumiert.
Beim Testet des Scriptes tauchte nun ein Fehler auf:

Fatal error: Uncaught SoapFault exception: [HTTP] Could not connect to host in...


Duch etwas googeln wurde die Ursache schnell gefunden.
Erklärung: Da durch, dass die Anfragen auf Port 8000 passieren, aber die Antworten intern von Port 80 kommen, versucht der Client die nachfolgenden Anfragen an die Antwort-Adresse (Port 80) zu senden – dort befindet sich aber kein Webservice, darum „Could not Connect…“.

Ein Workaround dieses Problemes ist es, den Standard SOAP-Client vom PHP zu erweitern in dem man bei JEDEM Request aufs neue den korekten Port mit sendet.

Das ganze sieht dann so aus:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Ext_SoapClient extends SoapClient {
 
    public function __construct($wsdl, $options) {
        $url = parse_url($wsdl);
        if ($url['port']) {
            $this->_port = $url['port'];
        }
        return parent::__construct($wsdl, $options);
    }
 
    public function __doRequest($request, $location, $action, $version) {
        $parts = parse_url($location);
        if ($this->_port) {
            $parts['port'] = $this->_port;
        }
        $location = $this->buildLocation($parts);
 
        $return = parent::__doRequest($request, $location, $action, $version);
        return $return;
    }
 
    public function buildLocation($parts = array()) {
        $location = '';
 
        if (isset($parts['scheme'])) {
            $location .= $parts['scheme'].'://';
        }
        if (isset($parts['user']) || isset($parts['pass'])) {
            $location .= $parts['user'].':'.$parts['pass'].'@';
        }
        $location .= $parts['host'];
        if (isset($parts['port'])) {
            $location .= ':'.$parts['port'];
        }
        $location .= $parts['path'];
        if (isset($parts['query'])) {
            $location .= '?'.$parts['query'];
        }
 
        return $location;
    }
}

Und im Script selbst dann statt:

1
$soapclient = new SoapClient("http://meineadresse.dyndns.org:8000/Service1.asmx?WSDL", array());

Den Client wie folgt aufrufen:

1
$soapclient = new Ext_SoapClient("http://meineadresse.dyndns.org:8000/Service1.asmx?WSDL", array());

Und alles funktioniert auch mit umgebogenen Ports 🙂

leave your comment


*

Unterstütze den Frickelblog!