0

My little application works in this way: in a simple text input user are asked to insert an url. on change my script tries to extract and display the first 10 images found on this page.

<input type="text" name="url" id="url" value="">

$("form.link-form input#url").change(function() {
  var request =     $.ajax({
                      type: "GET",
                      url: "funzioni/ajax/loadImagestFromUrl.php",
                      data: "url=" + insertedUrl,
                      dataType: "html",
                      timeout: 5000,
                      success: function(res) {
                        loadUrlImages2div(msg99);
                      },
                      error: function() {
                         request.abort();
                      }
                    });
});

the PHP script loadImagestFromUrl.php run this code, using PHP Simple HTML DOM Parser library:

set_time_limit(5);
$html = file_get_html($url); // load into this variable the entire html of the page
$count=1;
foreach($html->find('img') as $key=>$element) { // only images
    if ($count==11) break; //only first 10 images
        echo "<img class=\"imgFromUrl\" src=\"".$element->src."\" />\n";
    }
    $count++;
}

This work great on most cases but there are some urls that are not available in few seconds, or protected under password and the server keep executing something even if I set a timeout of 5 seconds for the ajax request and 5 second for the execution of php code.

When this happens everything get blocked, even refreshing the page is impossible, because it load and load and only after a lot of time it returns "504 Gateway Time-out. The server didn't respond in time."

Can somene help me in understanding how to completely block this request and let the server keep working?

fox
  • 1
  • 2
  • Perhaps this is useful https://stackoverflow.com/questions/10236166/does-file-get-contents-have-a-timeout-setting – mplungjan Sep 29 '18 at 15:19
  • In short, the ajax response sends a request and waits for an answer. If you cancel waiting for an answer, the script started by your request does not get stopped (it doesn't know you stopped waiting for it). So if you want to prevent the server from trying after a set amount of time, you need to do it on the backend side. Once you decide you should cancel, you should return a response to ajax informing it it should stop waiting. – tao Sep 29 '18 at 15:47
  • Also note [`set_time_limit()`](http://php.net/manual/en/function.set-time-limit.php) has no effect when PHP is running in [safe mode](http://php.net/manual/en/ini.sect.safe-mode.php#ini.safe-mode). There is no workaround. – tao Sep 29 '18 at 15:51
  • Provided you are able to make use of the cURL module, you could use it to specify a timeout in its options. See https://stackoverflow.com/a/26877132/694400 – Wieger Sep 30 '18 at 20:44

1 Answers1

0

Got that the solution must be find in the php code timeout and not with ajax timeout. This is clear.

I found this interesting discussion Great answer: Handling delays when retrieving files from remote server in PHP that suggests to use context parameter in the file_get_contents function. But actually it doesn’t work on my app.

So, as suggested by Wieger I have tried to use curl instead of file_get content. I defined this function

function file_get_contents_curl($url) {
  $ch = curl_init();
  $timeout=2;

  curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
  curl_setopt($ch, CURLOPT_HEADER, 0);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);
  curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
  curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);       

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

  return $data;
}

and used it instead of file_get_contents inside the parser library.

Again, it works for most of case, but some url make the server load for a lot of time until gateway timeout.

fox
  • 1
  • 2