短縮URLの展開

PHP短縮URL

短縮URLをクリックするときに少し躊躇することってありますよね?

短縮URLを展開してくれるサービスもすでにありますが、仕組みを知りたくなり自分で作ってみました。

仕組みや解説はいいから短縮URLの展開だけしたいという方は以下のページでどうぞ。

短縮URL展開の仕組み

短縮URLのヘッダ取得

まずは、短縮URLのヘッダーを取得してみる。

bit.lyでhttps://www.yahoo.co.jpを変換。

変換後URL→ https://bit.ly/1GV6cLV

このURLにアクセスしてヘッダ情報を取得します。

$url = "https://bit.ly/1GV6cLV";
$header_data = get_headers($url, 1);
print_r($header_data);

以下の情報が取得できました。

Array ( 
[0] => HTTP/1.1 301 Moved Permanently  
[Server] => Array ( [0] => nginx [1] => ATS )  
[Date] => Array ( [0] => Tue, 29 Jan 2019 14:22:03 GMT [1] => Tue, 29 Jan 2019 14:22:03 GMT )  
[Content-Type] => Array ( [0] => text/html; charset=utf-8 [1] => text/html; charset=UTF-8 )  
[Content-Length] => 111  
[Connection] => close  
[Cache-Control] => Array ( [0] => private, max-age=90 [1] => private, no-cache, no-store, must-revalidate )  
[Content-Security-Policy] => referrer always;  
[Location] => https://www.yahoo.co.jp/  
[Referrer-Policy] => unsafe-url  
[Set-Cookie] => Array ( [0] => _bit=j0tem3-830c2fe63a8569dd58-00K; Domain=bit.ly; Expires=Sun, 28 Jul 2019 14:22:03 GMT [1] => TLS=v=1.2&r=1; path=/; domain=.yahoo.co.jp; Secure ) 
[1] => HTTP/1.0 200 OK  
[P3P] => policyref="http://privacy.yahoo.co.jp/w3c/p3p_jp.xml", CP="CAO DSP COR CUR ADM DEV TAI PSA PSD IVAi IVDi CONi TELo OTPi OUR DELi SAMi OTRi UNRi PUBi IND PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA POL HEA PRE GOV"  
[X-Content-Type-Options] => nosniff  
[X-XSS-Protection] => 1; mode=block  
[X-Frame-Options] => SAMEORIGIN  
[Vary] => Accept-Encoding  
[Expires] => -1  
[Pragma] => no-cache  
[Age] => 0  
[Via] => http/1.1 edge1455.img.bbt.yahoo.co.jp (ApacheTrafficServer [c sSf ]) )

「HTTP/1.1 301 Moved Permanently 」とレスポンスがあります。

さらに[Location] にhttps://www.yahoo.co.jp/ と表示されています。

よって [Location] にリダイレクト先のURLが記載されていると理解。

複数回リダイレクトが発生している場合

念のため、リダイレクト先からさらにリダイレクトが発生している場合をチェック。

https://yahoo.co.jp → https://www.yahoo.co.jp にリダイレクトされているので、https://yahoo.co.jpの短縮URLを作成。

https://bit.ly/1it31yM → http://yahoo.co.jp → https://yahoo.co.jp

となる予定です。

結果、[Location]が以下のように配列になっていました。

[Location] => Array ( [0] => https://yahoo.co.jp/ [1] => https://www.yahoo.co.jp/ ) 

ということで、[Location]が配列の場合は1回以上のリダイレクトが発生していると理解しました。

リダイレクト先をチェックするスクリプト

今までの考察を踏まえて以下のスクリプトを考えてみました。

  • ヘッダから[Location]を取得
  • [Location]がなければ短縮URLではない
  • [Location]が配列の場合は複数のリダイレクトが発生している。そうでない場合はリダイレクトは1回のみ
  • 配列の場合はすべてのURLを表示する。

$url = "https://bit.ly/1it31yM"; //チェックするURL
$header_data = get_headers($url, 1); //ヘッダ情報取得

if(isset($header_data['Location'])) //ヘッダ情報に[Location]が含まれている場合
{
 $returned_url = $header_data['Location']; //[Location]を $returned_urlに格納
 
if (is_array( $returned_url)) { //$returned_urlが配列の場合

 foreach ($returned_url as $value) { 
  echo $value. "<br />"; //複数のURLを表示
  }
}
else { //$returned_urlが配列ではない場合
echo $returned_url; //URLを表示
}
}
else { //ヘッダ情報に[Location]が含まれていない場合
echo "短縮URLではありません。";
}

こんなところですね。

間違えている場合にはコメントで教えていただけましたら幸いです。

[追記]Twitter短縮URLの展開に不具合がありました。

Twitterの短縮URL https://t.co が短縮URLとして認識されない不具合がありました。

原因を確認したところ、https://t.coからget_headersで取得した配列のキーが[location]であることが原因でした。

[Location]と[location]。大文字小文字の違いですね。そのため、転送先が存在以内と判断され「短縮URLではありません」となっていました。

現状、t.co以外の短縮URLは展開できていたので、[location]も転送先として認識するように以下のように追記しました。

$url = "https://t.co/EwUaWzOEMQ"; //チェックするURL
$header_data = get_headers($url, 1); //ヘッダ情報取得

if(isset($header_data['Location']) OR isset($header_data['location'])) //ヘッダ情報に[Location]または[location]が含まれている場合
{
if(isset($header_data['Location'])) {
 $returned_url = $header_data['Location']; //[Location]を $returned_urlに格納
 }
 if(isset($header_data['location'])) {
 $returned_url = $header_data['location']; //[location]を $returned_urlに格納
 }
 
if (is_array( $returned_url)) { //$returned_urlが配列の場合

 foreach ($returned_url as $value) { 
  echo $value. "<br />"; //複数のURLを表示
  }
}
else { //$returned_urlが配列ではない場合
echo $returned_url; //URLを表示
}
}
else { //ヘッダ情報に[Location]が含まれていない場合
echo "短縮URLではありません。";
}

デモページも更新済みです。

PHP短縮URL