tags:

views:

1093

answers:

7

In PHP, how can I replicate the expand/contract feature for Tinyurl's as on search.twitter.com?

+7  A: 

If you want to find out where a tinyurl is going, use fsockopen to get a connection to tinyurl.com on port 80, and send it an HTTP request like this

GET /dmsfm HTTP/1.0
Host: tinyurl.com

The response you get back will look like

HTTP/1.0 301 Moved Permanently
Connection: close
X-Powered-By: PHP/5.2.6
Location: http://en.wikipedia.org/wiki/TinyURL
Content-type: text/html
Content-Length: 0
Date: Mon, 15 Sep 2008 12:29:04 GMT
Server: TinyURL/1.6

example code...

<?php
$tinyurl="dmsfm";

$fp = fsockopen("tinyurl.com", 80, $errno, $errstr, 30);
if (!$fp) {
    echo "$errstr ($errno)<br />\n";
} else {
    $out = "GET /$tinyurl HTTP/1.0\r\n";
    $out .= "Host: tinyurl.com\r\n";
    $out .= "Connection: Close\r\n\r\n";

    $response="";

    fwrite($fp, $out);
    while (!feof($fp)) {
        $response.=fgets($fp, 128);
    }
    fclose($fp);

    //now parse the Location: header out of the response

}
?>
Paul Dixon
+4  A: 

And here is how to contract an arbitrary URL using the TinyURL API. The general call pattern goes like this, it's a simple HTTP request with parameters:

http://tinyurl.com/api-create.php?url=http://insertyourstuffhere.com

This will return the corresponding TinyURL for http://insertyourstuffhere.com. In PHP, you can wrap this in an fsockopen() call or, for convenience, just use the file() function to retrieve it:

function make_tinyurl($longurl)
{
  return(implode('', file(
    'http://tinyurl.com/api-create.php?url='.urlencode($longurl))));
}

// make an example call
print(make_tinyurl('http://www.joelonsoftware.com/items/2008/09/15.html'));
Udo
A: 

Another simple and easy way:

<?php
function getTinyUrl($url) {
return file_get_contents('http://tinyurl.com/api-create.php?url='.$url);
}
?>
barredo
+2  A: 

As people have answered programatically how to create and resolve tinyurl.com redirects, I'd like to (strongly) suggest something: caching.

In the twitter example, if every time you clicked the "expand" button, it did an XmlHTTPRequest to, say, /api/resolve_tinyurl/http://tinyurl.com/abcd, then the server created a HTTP connection to tinyurl.com, and inspected the header - it would destroy both twitter and tinyurl's servers..

An infinitely more sensible method would be to do something like this Python'y pseudo-code..

def resolve_tinyurl(url):
    key = md5( url.lower_case() )
    if cache.has_key(key)
        return cache[md5]
    else:
        resolved = query_tinyurl(url)
        cache[key] = resolved
        return resolved

Where cache's items magically get backed up into memory, and/or a file, and query_tinyurl() works as Paul Dixon's answer does.

dbr
A: 

If you just want the location, then do a HEAD request instead of GET.

$tinyurl  = 'http://tinyurl.com/3fvbx8';
$context  = stream_context_create(array('http' => array('method' => 'HEAD')));
$response = file_get_contents($tinyurl, null, $context);

$location = '';
foreach ($http_response_header as $header) {
    if (strpos($header, 'Location:') === 0) {
        $location = trim(strrchr($header, ' '));
        break;
    }
}
echo $location;
// http://www.pingdom.com/reports/vb1395a6sww3/check_overview/?name=twitter.com%2Fhome
GZipp
Whoops, neglected to look at the dates. Oh well, I still think it's a valid answer.
GZipp
A: 

Here is another way to decode short urls via CURL library:

function doShortURLDecode($url) {
    $ch = @curl_init($url);
    @curl_setopt($ch, CURLOPT_HEADER, TRUE);
    @curl_setopt($ch, CURLOPT_NOBODY, TRUE);
    @curl_setopt($ch, CURLOPT_FOLLOWLOCATION, FALSE);
    @curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
    $response = @curl_exec($ch);
    preg_match('/Location: (.*)\n/', $response, $a);
    if (!isset($a[1])) return $url;
    return $a[1];
}

It's described here.

Pons
A: 

In PHP there is also a get_headers function that can be used to decode tiny urls.

Pons