0

I am trying to get response from YTS API, however I can't understand what went wrong here. I do believe that status and status_message are objects.

Errors

PHP Notice:  Trying to get property 'status' of non-object in /var/www/html/movies/inc/YTS.php on line 232

Notice: Trying to get property 'status' of non-object in /var/www/html/movies/inc/YTS.php on line 232
PHP Notice:  Trying to get property 'status_message' of non-object in /var/www/html/movies/inc/YTS.php on line 233

Notice: Trying to get property 'status_message' of non-object in /var/www/html/movies/inc/YTS.php on line 233
PHP Fatal error:  Uncaught Exception: API request failed. Error was:  in /var/www/html/movies/inc/YTS.php:233

Code:

$url = "https://yts.mx/api/v2/list_movies.json?limit=1";

    private function getFromApi($url)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($curl);
        
        
        if($e = curl_error($curl)) {
            throw new Exception("Curl request failed: " . $e);
        } 
        else {
            $data = json_decode($response);
    
            if ($data->status != 'ok') {
                throw new Exception("API request failed. Error was: " . $data->status_message);
            }
            return $data->data;
        }
        curl_close($curl);
    }

var_dump($data)

object(stdClass)#1 (4) { ["status"]=> string(2) "ok" ["status_message"]=> string(20) "Query was successful" ["data"]=> object(stdClass)#2 (4) { ["movie_count"]=> int(40807) ["limit"]=> int(1) ["page_number"]=> int(1) ["movies"]=> array(1) { [0]=> object(stdClass)#3 (26) { ["id"]=> int(41604) ["url"]=> string(66) "https://yts.mx/movies/a-chinese-odyssey-part-one-pandoras-box-1995" ["imdb_code"]=> string(9) "tt0112778" ["title"]=> string(41) "A Chinese Odyssey Part One: Pandora's Box" ["title_english"]=> string(41) "A Chinese Odyssey Part One: Pandora's Box" ["title_long"]=> string(48) "A Chinese Odyssey Part One: Pandora's Box (1995)" ["slug"]=> string(44) "a-chinese-odyssey-part-one-pandoras-box-1995" ["year"]=> int(1995) ["rating"]=> float(7.6) ["runtime"]=> int(87) ["genres"]=> array(3) { [0]=> string(6) "Action" [1]=> string(9) "Adventure" [2]=> string(6) "Comedy" } ["summary"]=> string(391) "Fantasy adventure about the arrival of Buddhism in China. When the Goddess of Happiness tosses the Longevity Monk and his disciples out of heaven (because the Monkey King tried to attain immortality), the Monkey King is reincarnated as the Joker. He now spends his time chasing two jealous women. When one of them is dying, the Joker goes back in time in an attempt to save her. —Anonymous" ["description_full"]=> string(391) "Fantasy adventure about the arrival of Buddhism in China. When the Goddess of Happiness tosses the Longevity Monk and his disciples out of heaven (because the Monkey King tried to attain immortality), the Monkey King is reincarnated as the Joker. He now spends his time chasing two jealous women. When one of them is dying, the Joker goes back in time in an attempt to save her. —Anonymous" ["synopsis"]=> string(391) "Fantasy adventure about the arrival of Buddhism in China. When the Goddess of Happiness tosses the Longevity Monk and his disciples out of heaven (because the Monkey King tried to attain immortality), the Monkey King is reincarnated as the Joker. He now spends his time chasing two jealous women. When one of them is dying, the Joker goes back in time in an attempt to save her. —Anonymous" ["yt_trailer_code"]=> string(11) "ZPri1X1RVeo" ["language"]=> string(2) "cn" ["mpa_rating"]=> string(0) "" ["background_image"]=> string(95) "https://yts.mx/assets/images/movies/a_chinese_odyssey_part_one_pandoras_box_1995/background.jpg" ["background_image_original"]=> string(95) "https://yts.mx/assets/images/movies/a_chinese_odyssey_part_one_pandoras_box_1995/background.jpg" ["small_cover_image"]=> string(96) "https://yts.mx/assets/images/movies/a_chinese_odyssey_part_one_pandoras_box_1995/small-cover.jpg" ["medium_cover_image"]=> string(97) "https://yts.mx/assets/images/movies/a_chinese_odyssey_part_one_pandoras_box_1995/medium-cover.jpg" ["large_cover_image"]=> string(96) "https://yts.mx/assets/images/movies/a_chinese_odyssey_part_one_pandoras_box_1995/large-cover.jpg" ["state"]=> string(2) "ok" ["torrents"]=> array(2) { [0]=> object(stdClass)#4 (10) { ["url"]=> string(72) "https://yts.mx/torrent/download/0575F561D71DD1961F01FC2CBBE22AF5598A6CF1" ["hash"]=> string(40) "0575F561D71DD1961F01FC2CBBE22AF5598A6CF1" ["quality"]=> string(4) "720p" ["type"]=> string(6) "bluray" ["seeds"]=> int(0) ["peers"]=> int(0) ["size"]=> string(9) "810.78 MB" ["size_bytes"]=> int(850164449) ["date_uploaded"]=> string(19) "2022-04-20 20:07:01" ["date_uploaded_unix"]=> int(1650478021) } [1]=> object(stdClass)#5 (10) { ["url"]=> string(72) "https://yts.mx/torrent/download/633A2CAE8DE3C9F50B2E3B89A5BC6304E4770BFE" ["hash"]=> string(40) "633A2CAE8DE3C9F50B2E3B89A5BC6304E4770BFE" ["quality"]=> string(5) "1080p" ["type"]=> string(6) "bluray" ["seeds"]=> int(0) ["peers"]=> int(0) ["size"]=> string(7) "1.63 GB" ["size_bytes"]=> int(1750199173) ["date_uploaded"]=> string(19) "2022-04-20 21:16:40" ["date_uploaded_unix"]=> int(1650482200) } } ["date_uploaded"]=> string(19) "2022-04-20 20:07:01" ["date_uploaded_unix"]=> int(1650478021) } } } ["@meta"]=> object(stdClass)#6 (4) { ["server_time"]=> int(1650488761) ["server_timezone"]=> string(3) "CET" ["api_version"]=> int(2) ["execution_time"]=> string(4) "0 ms" } } Query was successful

Code that was working using file_get_content(), but knew to fail sometimes and so I was told to use curl.

    private function getFromApi($url)
    {
        if (!$data = file_get_contents($url)) {
            $error = error_get_last();

            throw new Exception("HTTP request failed. Error was: " . $error['message']);
        } else {
            $data = json_decode($data);

            if ($data->status != 'ok') {
                throw new Exception("API request failed. Error was: " . $data->status_message);
            }

            return $data->data;
        }
    }

Current code


<?php

    $url = "https://yts.mx/api/v2/list_movies.json?limit=1";

    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    $response = curl_exec($curl);
    
    
    if($e = curl_error($curl)) {
        throw new Exception("Curl request failed: " . $e);
    }
    curl_close($curl);

    $data = json_decode($response);
    var_dump($data);
    if (!$data) {
        throw new Exception("JSON decode error: " . json_last_error_msg());
    }

    if ($data->status != 'ok') {
        throw new Exception("API request failed. Error was: " . $data->status_message);
    }
    return $data->data;
Benjamin K
  • 13
  • 4

1 Answers1

0

You're probably getting an empty response, so json_decode() is failing. You need to check for this, since an empty response doesn't necessarily trigger a curl error.

    private function getFromApi($url)
    {
        $curl = curl_init();
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($curl);
        
        
        if($e = curl_error($curl)) {
            throw new Exception("Curl request failed: " . $e);
        }
        curl_close($curl);

        $data = json_decode($response);
        if (!$data) {
            throw new Exception("JSON decode error: " . json_last_error_msg());
        }

        if ($data->status != 'ok') {
            throw new Exception("API request failed. Error was: " . $data->status_message);
        }
        return $data->data;
    }

Also, there's no need to use else if the if block throws, since it never returns.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • Hi, thank you for answering. I'll take that advice. Results of the code that you provided: `PHP Fatal error: Uncaught Exception: JSON decode error: 4 in /var/www/html/movies/inc/YTS.php:231 Stack trace: #0 /var/www/html/movies/inc/YTS.php(71): YTS->getFromApi()` – Benjamin K Apr 20 '22 at 21:39
  • I guess the response isn't empty when I can var_dump it successfully – Benjamin K Apr 20 '22 at 21:43
  • That's `JSON_ERROR_SYNTAX`. There's a syntax error in the JSON response. – Barmar Apr 20 '22 at 21:43
  • I've changed the answer to use `json_last_error_msg()` so it displays the reason in English. – Barmar Apr 20 '22 at 21:45
  • I'm not sure why you're getting that error. I went to the URL and the JSON is correct. – Barmar Apr 20 '22 at 21:46
  • That's really weird. I have updated the question with the code I had before using file_get_content, the principe should be the same, I think – Benjamin K Apr 20 '22 at 21:53
  • I can't reproduce the error. `curl` and `file_get_contents()` should both work for this. – Barmar Apr 20 '22 at 21:56
  • I suspect you're hitting a rate limit. – Barmar Apr 20 '22 at 21:57
  • Just in case, I have now double checked. Old code with file_get_content works flawlessly, while this produces these errors. Not rate limit for sure, old code used to loop all day long... and it still works. *Mind blowing* – Benjamin K Apr 20 '22 at 22:01
  • If the old code works, why are you changing it? The question says it's know to fail sometimes. I suspect it fails for the same reason curl fails. They're both doing essentially the same thing. – Barmar Apr 20 '22 at 22:04
  • That function is called inside a loop, going through pages... file_get_content doesn't fail right away like curl do, but literally randomly from 500-1600th page, always different with error `PHP file_get_contents() returns "failed to open stream: HTTP request failed!"`. Researching the web, found this [link](https://stackoverflow.com/questions/697472/php-file-get-contents-returns-failed-to-open-stream-http-request-failed) where people advice to switch to Curl. – Benjamin K Apr 20 '22 at 22:12
  • That's the exact problem I would expect to occur due to a rate limit. And the advice to switch to curl is just a kneejerk that has no basis in fact. – Barmar Apr 20 '22 at 22:14
  • Occasionally `curl` is useful because you can control the headers sent more precisely, such as customizing the user agent. But it's not a magic bullet that fixes all problems. You need to know WHY `file_get_contents()` is failing in the first place, then fix that with the curl options. – Barmar Apr 20 '22 at 22:16
  • Yeah I understand that it could happen but I do want to try curl. 'That error can't be happening at the same time as that var_dump output. ' - the only difference if that I ran the script using therminal, while I var dumped it accessing the test page and code was outside the function. Does that explain something? I'm not sure. – Benjamin K Apr 20 '22 at 22:18
  • How can you be dumping it outside the function? You should put `var_dump($code);` right after `$code = json_decode($response);`. Otherwise it's not dumping the same thing you're trying to use. – Barmar Apr 20 '22 at 22:20
  • Alright, I'm not so stubborn, I would use file_get_content if it was working. Do you have any advice on how to I prevent the rate limit if there is one? i have read about timeouts but I'm not so sure. – Benjamin K Apr 20 '22 at 22:20
  • What I've done in situations like this is put the code into a loop that retries up to N times with a delay when the response is empty. – Barmar Apr 20 '22 at 22:21
  • Look, I have updated the question with current code at the bottom and you can live preview it here [link](http://193.164.131.125/test.php) (var_dump) – Benjamin K Apr 20 '22 at 22:24
  • I'm not seeing an error when I try that. – Barmar Apr 20 '22 at 22:26
  • At the end, it looks like there was an error in the url (It is being changed in the loop), but here I used this one for testing purpose. That explains why it works here and there not. Sorry and thank you very much for going this far. ps: still unclear why file_get_contents actually provides no errors, maybe it processes urls differently, eg removing spaces etc. (I'm guessing) – Benjamin K Apr 20 '22 at 22:34