What's wrong with my Curl call?

Curl call doesn’t return anything. I’ve verified it does work with Postman.

$params will eventually be an array, but since the API accepts literal $ in variables, I’ll have to find something to use other than http_build_query(), since it encodes the $.

The API should return a JSON array.

    $base_url = 'https://resoapi.com/reso/odata/';
    $endpoint = 'Property';
    $params = '$top=10';

    $url = $base_url. $endpoint . '?' . $params;
    $access_token = 'mytoken';
    $cURLConnection = curl_init();

    
    curl_setopt($cURLConnection, CURLOPT_URL, $url);
    curl_setopt($cURLConnection, CURLOPT_HTTPHEADER, array(
        "Authorization: Bearer ".$access_token
    ));
    
    
    curl_setopt($cURLConnection, CURLOPT_RETURNTRANSFER, true);
    
    $phoneList = curl_exec($cURLConnection);
    curl_close($cURLConnection);
    
    $jsonArrayResponse - json_decode($phoneList);

    var_dump($jsonArrayResponse);

You have documentation for this API? Is it expecting a POST request instead of a GET one?

I have documentation, but nothing that gave me any clues as to what I am doing wrong.

When using Postman, I get a response as expected with GET https://resoapi.com/reso/odata/Property?$top=10 and adding the appropriate bearer token.

POST isn’t supported, it has to be a GET.

Documentation

Their documentation oddly doesnt say the word “bearer” should be in the header…

When using Postman, the word “Bearer” is present, and it returns data.

If I remove the Postman “Authorization” method, and just enter add ‘Authorization: mytoken’ manually. It still works the same. Doesn’t seem to make a difference if the word “Bearer” is present.

and just for sanity… you’re sending the request to https://resoapi.utahrealestate.com/reso/odata, not

(missing the “utahrealestate” part), right?

I’m using the correct API url in the actual code. Technically I am using https://resoapi.rmlsweb.com/reso/odata… which is the same implementation, but a different server.

When I execute the code manually via commandline, I get a return of “Undefined variable $jsonArrayResponse…”

When I try to use the code example in the documentation (which doesn’t use a curl call), I get SSL re-nogitaiton errors…

$token = 'YourBearerToken';

/* Create the base url for the Property resource */

$url = 'https://resoapi.utahrealestate.com/reso/odata/Property?$orderby=ListingKeyNumeric';

/* Apply any filters (ie. Active Residential). Skip this if you want all listings */

$filters = array("StandardStatus eq Odata.Models.StandardStatus'Active'", "PropertyType eq Odata.Models.PropertyType'Residential'");

$url .= '&$filter=' . implode(' and ', $filters);

/* Apply the $top option. This is the number of listings that can be pulled in one request. 
This value may vary depending on vendor configuration 
*/

$top = 200;

$url .= '&$top=' . $top;

/* Create a function for making the request */

function getResponse($url, $token){

    $opts = [
        "http" => [
            "method" => "GET",
            "header" => "Authorization: Bearer $token"
        ]
    ];

    $context = stream_context_create($opts);

    $url = str_replace(" ", "%20", $url);    //make sure white spaces are encoded

    $response = file_get_contents($url, false, $context);

    return $response;
}

/* Start the $skip option at 0. This is the offset and needs to be incremented by the value in $top with each request. */

$skip = 0;

do{

    $request_url = $url . '&$skip=' . $skip;

    $response = getResponse($request_url, $token);

    $json = json_decode($response, true);

    $listings = $json['value'];

    foreach($listings as $listing){

        //write or update $listing to db
    }

    $skip += $top;

}while(count($listings) > 0);

PHP Warning: file_get_contents(): SSL operation failed with code 1. OpenSSL Error messages:
error:0A000152:SSL routines::unsafe legacy renegotiation disabled in /…/cr-rmls.php on line 48
PHP Warning: file_get_contents(): Failed to enable crypto in /…/cr-rmls.php on line 48
PHP Warning: file_get_contents(https://resoapi.rmlsweb.com/reso/odata/Property?$orderby=ListingKeyNumeric&$filter=StandardStatus%20eq%20Odata.Models.StandardStatus’Active’%20and%20PropertyType%20eq%20Odata.Models.PropertyType’Residential’&$top=200&$skip=0): Failed to open stream: operation failed in /…/cr-rmls.php on line 48
PHP Warning: Trying to access array offset on value of type null in /…/cr-rmls.php on line 65
PHP Warning: foreach() argument must be of type array|object, null given in /…/cr-rmls.php on line 67
PHP Fatal error: Uncaught TypeError: count(): Argument #1 ($value) must be of type Countable|array, null given in /…/cr-rmls.php:74

So why don’t you print out the response of your requests? Also there is something called return status für a http request which you can fetch with

$httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);

There is also a function called curl_error. Maybe it makes sense to use that also?

Also your curl headers look very much to small for me. What about content type, return transfer, accept etc parameters?

Also you are replacing spaces in the url but what about other special Chars? Use urlencode() instead

as Thallius says, your current code isnt checking the result of the call before trying to use it.

The SSL failure with fetch_contents may be a clue, but the error would tell you more.

You can TRY this option; I must put big red flashy warning text around this) THIS OPTION IS A SECURITY HOLE. DO NOT USE IF YOU CAN AT ALL AVOID IT. THIS IS FOR DEBUGGING EFFORTS ONLY. ATTEMPT TO USE THE CAINFO or CAPATH options instead.
curl_setopt($cURLConnection, CURLOPT_SSL_VERIFYPEER, false);

If it suddenly works with verifypeer disabled, curl was bouncing off the same SSL problem. In that case, you may need to see if you can get a CA cert stack from somewhere (https://curl.se/docs/caextract.html for example), stick it in using the CAINFO option, and see if it resolves the SSL issue for you.

I’ve also noticed cURL doesn’t like it when intermediate certs aren’t installed on the server, whereas browsers are perfectly okay with that.

Still nothing returned when adding curl_setopt($cURLConnection, CURLOPT_SSL_VERIFYPEER, false);

and did you pull the curl_error and httpcode like Thallius suggested?

Yepp, still returns NULL

$base_url = 'https://resoapi.rmlsweb.com/';
$endpoint = 'Property';
$params = '$top=2';

$url = $base_url. $endpoint . '?' . $params;
$access_token = 'mytoken';
$cURLConnection = curl_init();


curl_setopt($cURLConnection, CURLOPT_URL, $url);
curl_setopt($cURLConnection, CURLOPT_HTTPHEADER, array(
    "Authorization: Bearer ".$access_token,
    'Content-Type: application/json',
    'Accept-Encoding: gzip, deflate, br',
    'Connection: Keep-Alive',

    ));


curl_setopt($cURLConnection, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($cURLConnection, CURLOPT_RETURNTRANSFER, true);

$httpcode = curl_getinfo($cURLConnection, CURLINFO_HTTP_CODE);
var_dump($httpcode);

$jsonListings = curl_exec($cURLConnection);
curl_close($cURLConnection);

$listings = json_decode($jsonListings);

var_dump($listings);

Sure did. curl_getinfo returns 0 and curl_error returns empty string

cant get error or code before you exec

Using curl_setopt($ch, CURLOPT_VERBOSE, true); gives me

  • Trying 216.40.13.55:443…
  • Connected to resoapi.rmlsweb.com (216.40.13.55) port 443 (#0)
  • ALPN, offering h2
  • ALPN, offering http/1.1
  • error:0A000152:SSL routines::unsafe legacy renegotiation disabled
  • Closing connection 0

I installed the same script on a Ubuntu 20.04 machine and I get string(0) “”

  • Trying 216.40.13.55:443…
  • TCP_NODELAY set
  • Connected to resoapi.rmlsweb.com (216.40.13.55) port 443 (#0)
  • ALPN, offering h2
  • ALPN, offering http/1.1
  • successfully set certificate verify locations:
  • CAfile: /etc/ssl/certs/ca-certificates.crt
    CApath: /etc/ssl/certs
  • SSL connection using TLSv1.2 / AES256-SHA
  • ALPN, server accepted to use http/1.1
  • Server certificate:
  • subject: CN=*.rmlsweb.com
  • start date: Aug 24 00:00:00 2022 GMT
  • expire date: Aug 27 23:59:59 2023 GMT
  • issuer: C=US; O=DigiCert, Inc.; CN=GeoTrust Global TLS RSA4096 SHA256 2022 CA1
  • SSL certificate verify ok.

GET /Property HTTP/1.1
Host: resoapi.rmlsweb.com
Authorization: MyToken
Content-Type: application/json
Accept: /
Accept-Encoding: gzip, deflate, br
Connection: Keep-Alive

  • Mark bundle as not supporting multiuse
  • HTTP 1.0, assume close after body
    < HTTP/1.0 404 Not Found
    < Date: Tue, 21 Feb 2023 00:18:32 GMT
    < Server: Apache/2.4.29 (Ubuntu)
    < Vary: Authorization
    < Cache-Control: no-cache, private
    < X-SERVER: production 3
    < Content-Length: 1482
    < Connection: close
    < Content-Type: text/html; charset=UTF-8
    <
  • Closing connection 0
    NULL

Well the logging says…

So… you SURE the other website uses the exact same endpoints as Utah does? and are you SURE you’ve spelled everything correctly? Cause… that log says something isnt there.

You said it works in Postman… when you export Postman’s query call to cURL, what code does it give you?

Maybe this is your problem. Shouldn’t it be https://resoapi.utahrealestate.com/reso/odata/Property?

Your code is saying one thing and the error is saying another. Your code is using file_get_contents(), but you’re asking for help with cURL. Also, the URLs don’t align when comparing the errors and what you have in the code. So I would say try to be consistent (aka stay on topic if you will) when trouble shooting. Don’t go and randomly searching for things that has nothing to do with your issue because this will confuse you even more or cause even more errors which it’s sort of showing in this thread. Since the issue is with cURL, you should use the URL I gave because that actually seems to be the correct one. I can confirm it to be the correct one because when I do the same thing using my own cURL method, I get this response.

{"response_code":401,"message":"Unauthorized"} 

Rather than your 404 error response.

Here’s the cURL snippet I used.

public function index(): void {

	$access_token = 'someRandomToken';

	$listings = $this->get('https://resoapi.utahrealestate.com/reso/odata/Property', [
		'Authorization: Bearer ' . $access_token,
		'Content-Type: application/json',
		'Accept-Encoding: gzip, deflate, br',
		'Connection: Keep-Alive',
	]);

	print_r($listings);

}

private function get(string $url, array $headers): string {

	$curl = curl_init();

	curl_setopt($curl, CURLOPT_HEADER, 0);
	curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
	curl_setopt($curl, CURLOPT_URL, $url);
	curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1);

	if(!empty($headers)) {
		curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
	}

	$data = curl_exec($curl);
	curl_close($curl);

	return $data;

}

Well, it turns out that it’s a problem with the RMLS server and incompatibility with Open SSL 3 (which comes standard with Ubuntu 22.04).

When I run the CURL from a Ubuntu 18.04 machine, it returns data just fine.

The RMLS is apparently aware of the issue, but won’t be upgrading their SSL stack for a few months, at least.

Is it possible to specify a different (though technically less secure) ssl configuration for just this script?