tags:

views:

3222

answers:

10

Hello all,

I wish to make a simple GET request to another script on a different server. How do I do this?

In one case, I just need to request an external script without the need for any output.

make_request('http://www.externalsite.com/script1.php?variable=45'); //example usage

In the second case, I need to get the text output.

$output = make_request('http://www.externalsite.com/script2.php?variable=45');
echo $output; //string output

To be honest, I do not want to mess around with CURL as this isn't really the job of CURL. I also do not want to make use of http_get as I do not have the PECL extensions.

Would fsockopen work? If so, how do I do this without reading in the contents of the file? Is there no other way?

Thanks all

Update

I should of added, in the first case, I do not want to wait for the script to return anything. As I understand file_get_contents() will wait for the page to load fully etc?

+11  A: 

file_get_contents will do what you want

$output = file_get_contents('http://www.example.com/');
echo $output;

Edit: One way to fire off a GET request and return immediately.

Quoted from http://petewarden.typepad.com/searchbrowser/2008/06/how-to-post-an.html

function curl_post_async($url, $params)
{
    foreach ($params as $key => &$val) {
      if (is_array($val)) $val = implode(',', $val);
        $post_params[] = $key.'='.urlencode($val);
    }
    $post_string = implode('&', $post_params);

    $parts=parse_url($url);

    $fp = fsockopen($parts['host'],
        isset($parts['port'])?$parts['port']:80,
        $errno, $errstr, 30);

    $out = "POST ".$parts['path']." HTTP/1.1\r\n";
    $out.= "Host: ".$parts['host']."\r\n";
    $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
    $out.= "Content-Length: ".strlen($post_string)."\r\n";
    $out.= "Connection: Close\r\n\r\n";
    if (isset($post_string)) $out.= $post_string;

    fwrite($fp, $out);
    fclose($fp);
}

What this does is open a socket, fire off a get request, and immediately close the socket and return.

Marquis Wang
curl_post_async sends a POST request, not a GET.
Vinko Vrsalovic
Yeah, why would you want a POST request? In fact, I think a HEAD request would make the most sense.
musicfreak
Er yeah good point. Make that curl_get_async and use replace POST with GET. I also think that a HEAD request would make more sense, but this would be slightly faster? I think?
Marquis Wang
Changing the POST to GET alone didn't solve the problem. So I kept it as a POST and I finally have an immediate return of my script! :)
Abs
@Abs: My answer below shows how to use GET instead of POST to achieve the same results.
catgofire
+1  A: 
$output = file_get_contents('http://foo.com/file.txt')

is indeed the way to do that. The caveat is explained here:

http://php.net/manual/en/filesystem.configuration.php#ini.allow-url-fopen

The allow_url_fopen option has to be set in php.ini to true for this to work.

Vinko Vrsalovic
+4  A: 

If you don't have access to http_get, and you don't need the response from the request, I'm sorry to say your best bet would be cURL. I know that's not the answer you wanted, but you're wrong in thinking that "this isn't really the job of CURL." In fact, this is exactly what cURL was made for, so I recommend using it. Something like this should work:

$handle = curl_init("http://www.example.com/");
curl_setopt($handle, CURLOPT_NOBODY, true);
curl_exec($handle);
curl_close($handle);

The CURLOPT_NOBODY option makes it a HEAD request, which essentially only returns a response header, not the full body (so you don't have to wait for the whole page to be sent). When you need the response, you can just use file_get_contents as suggested above.

musicfreak
Thanks for your reply. I think you are right, I dismissed CURL too quickly. I have used your code and I still see some waiting from that CURL call? Would there be a reason for this? The script I am calling is one that will take time to complete execution and I think it returns headers after completion of what it needs to do.
Abs
It still waits for a response, but it doesn't ask for a body. Do you not want it to wait at all? In that case, I'm not sure that's possible. You could work around it by setting the timeout (CURLOPT_CONNECTTIMEOUT) to something really small, like 0.1. I've never done that so I can't guarantee anything.
musicfreak
Actually, scratch my last comment. I just realized that it would cancel the connection if it still hasn't connected in 0.1 seconds.
musicfreak
+2  A: 

Interesting problem. I'm guessing you just want to trigger some process or action on the other server, but don't care what the results are and want your script to continue. There is probably something in cURL that can make this happen, but you may want to consider using exec() to run another script on the server that does the call if cURL can't do it. (Typically people want the results of the script call so I'm not sure if PHP has the ability to just trigger the process.) With exec() you could run a wget or even another PHP script that makes the request with file_get_conents().

Darryl Hein
+2  A: 

Regarding your update, about not wanting to wait for the full page to load - I think a HTTP HEAD request is what you're looking for..

get_headers should do this - I think it only requests the headers, so will not be sent the full page content.

"PHP / Curl: HEAD Request takes a long time on some sites" describes how to do a HEAD request using PHP/Curl

If you want to trigger the request, and not hold up the script at all, there are a few ways, of varying complexities..

  • Execute the HTTP request as a background process, http://stackoverflow.com/questions/45953/php-execute-a-background-process/45966 - basically you would execute something like "wget -O /dev/null $carefully_escaped_url" - this will be platform specific, and you have to be really careful about escaping parameters to the command
  • Executing a PHP script in the background - basically the same as the UNIX process method, but executing a PHP script rather than a shell command
  • Have a "job queue", using a database (or something like beanstalkd which is likely overkill). You add a URL to the queue, and a background process or cron-job routinely checks for new jobs and performs requests on the URL
dbr
+1  A: 

You don't. While PHP offers lots of ways to call a URL, it doesn't offer out of the box support for doing any kind of asynchronous/threaded processing per request/execution cycle. Any method of sending a request for a URL (or a SQL statement, or a etc.) is going to wait for some kind of response. You'll need some kind of secondary system running on the local machine to achieve this (google around for "php job queue")

Alan Storm
A: 

Try:

//Your Code here
$pid = pcntl_fork();
if ($pid == -1) {
     die('could not fork');
}
else if ($pid)
{
echo("Bye")  
}
else
{
     //Do Post Processing
}

This will NOT work as an apache module, you need to be using CGI.

LM
+1  A: 

I found this interesting link to do asynchronous processing(get request).

askapache

Furthermore you could do asynchronous processing by using a message queue like for instance beanstalkd.

Alfred
+1  A: 

Also consider fsockpen.

pbreitenbach
+2  A: 

This is how to make Marquis' answer work with both POST and GET requests:

  // $type must equal 'GET' or 'POST'
  function curl_request_async($url, $params, $type='POST')
  {
      foreach ($params as $key => &$val) {
        if (is_array($val)) $val = implode(',', $val);
        $post_params[] = $key.'='.urlencode($val);
      }
      $post_string = implode('&', $post_params);

      $parts=parse_url($url);

      $fp = fsockopen($parts['host'],
          isset($parts['port'])?$parts['port']:80,
          $errno, $errstr, 30);

      // Data goes in the path for a GET request
      if('GET' == $type) $parts['path'] .= '?'.$post_string;

      $out = "$type ".$parts['path']." HTTP/1.1\r\n";
      $out.= "Host: ".$parts['host']."\r\n";
      $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
      $out.= "Content-Length: ".strlen($post_string)."\r\n";
      $out.= "Connection: Close\r\n\r\n";
      // Data goes in the request body for a POST request
      if ('POST' == $type && isset($post_string)) $out.= $post_string;

      fwrite($fp, $out);
      fclose($fp);
  }
catgofire