troydavisson / PHRETS

PHP client library for interacting with a RETS server to pull real estate listings, photos and other data made available from an MLS system
http://troda.com
MIT License
450 stars 235 forks source link

GetObject return Invalid header syntax error #322

Open san8work opened 1 year ago

san8work commented 1 year ago

In laravel It working fine on some mls but some mls return error Invalid header syntax

$photos = $rets->GetObject("Property", "Photo",'S6673582);

aconital commented 1 year ago

I'm getting the same error. This is the crash:

` Invalid header syntax #0 /var/www/api/vendor/guzzlehttp/psr7/src/Message.php(235): GuzzleHttp\Psr7\Message::parseMessage()

1 /var/www/api/vendor/troydavisson/phrets/src/Parsers/GetObject/Multiple.php(52): GuzzleHttp\Psr7\Message::parseResponse()

2 /var/www/api/vendor/troydavisson/phrets/src/Session.php(136): PHRETS\Parsers\GetObject\Multiple->parse()

3 /var/www/api/app/Traits/ListingSyncTrait.php(1914): PHRETS\Session->GetObject()`

Here is the response from feed:

  #response: GuzzleHttp\Psr7\Response^ {#6225
    -reasonPhrase: "OK"
    -statusCode: 200
    -headers: array:10 [
      "Date" => array:1 [
        0 => "Fri, 13 Oct 2023 19:11:32 GMT"
      ]
      "Content-Type" => array:1 [
        0 => "multipart/parallel; boundary=StratusRETS-XYZZY;charset=utf-8"
      ]
      "Transfer-Encoding" => array:1 [
        0 => "chunked"
      ]
      "Connection" => array:1 [
        0 => "keep-alive"
      ]
      "Set-Cookie" => array:2 [
        0 => "AWSALB=cookie; Expires=Fri, 20 Oct 2023 19:11:32 GMT; Path=/"
        1 => "AWSALBCORS=cookie; Expires=Fri, 20 Oct 2023 19:11:32 GMT; Path=/; SameSite=None"
      ]
      "RETS-Version" => array:1 [
        0 => "RETS/1.5"
      ]
      "cache-control" => array:1 [
        0 => "private"
      ]
      "Server" => array:1 [
        0 => "StratusRETS/1.7"
      ]
      "MIME-Version" => array:1 [
        0 => "1.0"
      ]
      "x-encoded-content-encoding" => array:1 [
        0 => "gzip"
      ]
    ]
    -headerNames: array:10 [
      "date" => "Date"
      "content-type" => "Content-Type"
      "transfer-encoding" => "Transfer-Encoding"
      "connection" => "Connection"
      "set-cookie" => "Set-Cookie"
      "rets-version" => "RETS-Version"
      "cache-control" => "cache-control"
      "server" => "Server"
      "mime-version" => "MIME-Version"
      "x-encoded-content-encoding" => "x-encoded-content-encoding"
    ]
    -protocol: "1.1"
    -stream: GuzzleHttp\Psr7\Stream^ {#6227
      -stream: stream resource {@1566
        wrapper_type: "PHP"
        stream_type: "TEMP"
        mode: "w+b"
        unread_bytes: 0
        seekable: true
        uri: "php://temp"
        options: []
      }
      -size: null
      -seekable: true
      -readable: true
      -writable: true
      -uri: "php://temp"
      -customMetadata: []
    }
  }
}

And this is $response->getBody() from phrets/src/Parsers/GetObject/Multiple.php

  -stream: stream resource {@1566
    wrapper_type: "PHP"
    stream_type: "TEMP"
    mode: "w+b"
    unread_bytes: 0
    seekable: true
    uri: "php://temp"
    options: []
  }
  -size: null
  -seekable: true
  -readable: true
  -writable: true
  -uri: "php://temp"
  -customMetadata: []
}

$boundary value is StratusRETS-XYZZY

So it seems some of the $part s cannot be parsed. Here is part that parseResponse can't parse:

https://drive.google.com/file/d/1KaIEL__NPNiy4-IvnY1SgVoLF9-cF358/view?usp=sharing

And this is the full body before this library removes boundary and cleans up any preamble/epilogue:

https://drive.google.com/file/d/1KBSlejFsV7dTDMR-MLSZlCFbFahHRbRu/view?usp=sharing

@troydavisson is there anything else I can provide to assist with this?

aconital commented 1 year ago

Update: I think I know what's going on. When "Description:" value has line break and is in multiline like the example I provided above:

Content-Type: image/jpeg
Content-ID: C7063702
Object-ID: 10
Description: QUARTZ COUNTERS MARBLE
BACKSPLASH

The code fails to parse. I tried removing the value and it worked. I added the following code to troydavisson/phrets/src/Parsers/GetObject/Multiple.php line 39

$fieldToUpdate = 'Description';
// Create a regular expression pattern to match the field and its value
$pattern = "/{$fieldToUpdate}:(.*?)(\r?\n\r?\n|$)/si";
// Use preg_replace to remove the value until an empty line is reached
$body = preg_replace($pattern, "{$fieldToUpdate}:\r\n\r\n", $body);

I'll open a PR shortly.

aconital commented 1 year ago

@troydavisson The PR is up if you are okay with the change

https://github.com/troydavisson/PHRETS/pull/323