1

I'm writing a script that communicates with a server via XML. I can tell I'm making successful requests to the server's API because I can see in a log on the server it's receiving them, however I'm having a hard time receiving the response (XML). I do not own the server and unfortunately cannot modify any of the programs sending the response.

I don't think the server is specifying the end of the file, so doing a while (!feof($fp)) { ... } hangs. And unfortunately I don't think I have any way (to my knowledge) of determining the size of the response before reading it.

What I am doing and what I have attempted:

function postXMLSocket ($server, $path, $port, $xmlDocument) {
  $contentLength = strlen($xmlDocument);
  $result = '';
  // Handling error case in else statement below
  if ($fp = @fsockopen($server, $port, $errno, $errstr, 30)) {
    $out =  "POST / HTTP/1.0\r\n";
    $out .= "Host: ".$server."\r\n";
    $out .= "Content-Type: text/xml\r\n";
    $out .= "Content-Length: ".$contentLength."\r\n";
    $out .= "Connection: close\r\n";
    $out .= "\r\n"; // all headers sent
    $out .= $xmlDocument;
    fwrite($fp, $out);

    // ATTEMPT 5: Read until we have a valid XML doc -- hangs
    // libxml_use_internal_errors(true);

    // do {
    //   $result .= fgets($fp, 128);
    //   $xmlTest = simplexml_load_string($result);
    // } while ($xmlTest === false);

    // ATTEMPT 4: Read X # of lines -- works but I can't know how many lines response will be
    // for ($i = 0; $i < 10; $i++) {
    //   $result .= fgets($fp, 128);
    // }

    // ATTEMPT 3: Read until the lines being read are empty -- hangs
    // do {
    //   $lineRead = fgets($fp, 500);
    //   $result .= $lineRead;
    // } while (strlen($lineRead) > 0);

    // ATTEMPT 2: Read the whole file w/ fread -- only reads part of file
    // $result = fread($fp, 8192);

    // ATTEMPT 1: Read to the EOF -- hangs
    // while (!feof($fp)) {
    //   $result .= fgets($fp, 128);
    // }

    fclose($fp);
  }
  else {
    // Could not connect to socket
    return false;
  }
  return $result;
}

Attempt descriptions:

1) First I just tried reading lines until reaching the end of the file. This keeps hanging and resulting in a time out and I think it's because the server isn't marking the end of the XML file it's responding with, so it's getting caught in an infinite loop.

2) Second I tried to read response as one whole file. This worked and I got something back, but it was incomplete (seems the response is quite large). While this works, I don't have any way of knowing how big the response will be before reading it, so I don't think this is an option.

3) Next I tried reading until fgets is returning an empty string. I made the assumption it would do this if it's reading lines after passing the end of the file, but this hangs as well.

4) For this attempt I just tried to read a hardcoded number of lines (10 in this case), but this has similar problems to attempt 2 above where I can't accurately know how many lines the response will have until after reading it.

5) This is where I thought I was getting clever. I know the response will be XML, and will be contained in a <Response> node. Therefore I thought I could get away with reading until the $result variable contained a valid XML string, however this seems to hang as well.

saricden
  • 2,084
  • 4
  • 29
  • 40
  • Try echoing `$result` – Vinay Apr 06 '18 at 04:30
  • Does `while (!feof($fp))` work in PHP? In many other languages it does not. https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong?s=1|195.6451 – Yunnosch Apr 06 '18 at 04:51

1 Answers1

0

Using a higher level approach to HTTP requests will probably help you. Try this:

$stringWithSomeXml = "your payload xml here";
postXml("www.google.com", "/path/on/server", 80, $stringWithSomeXml);

function postXml($server, $path, $port, $xmlPayload)
{
    $ch = curl_init();
    $path = ltrim($path, "/");
    if ($port == 80) {
        $url = "https://{$server}/{$path}";
    } else {
        $url = "https://{$server}:{$port}/{$path}";
    }

    echo "\n$url\n";
    curl_setopt(
        $ch,
        CURLOPT_URL,
        $url
    );
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

    curl_setopt(
        $ch,
        CURLOPT_HTTPHEADER,
        [
            "Content-type: application/xml",
            "Content-Length: ".strlen($xmlPayload)
        ]
    );

    curl_setopt($ch, CURLOPT_POSTFIELDS, $xmlPayload);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);

    $result = curl_exec($ch);
    echo "length: " . strlen($result) . "\n";
    echo "content: " . $result . "\n";

    curl_close($ch);
}
Ryan Wright
  • 177
  • 1
  • 10