SHOJI's Code
 仕事や趣味で書いた各種言語のプログラミングコード(エクセルVBA,PHP,C/C++/C#,JavaScript等)、その他雑記。
2019.06<<12345678910111213141516171819202122232425262728293031>>2019.08
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

最近作ったコード。他のサイトへリダイレクトするPHPスクリプト。
http://(サイト)/gateway.php/path/to/access にアクセスすると、 http://xxx.xxx.xxx.xxx/path/to/access からの応答を返すものである。

gateway.php
<?php
//////////////////////////////////////////////////////////////////
// 準備
ini_set("max_execution_time", 0); // スクリプトの実行時間を無制限にする
set_time_limit(0);
ignore_user_abort(true); // クライアントから切断されても継続する

//////////////////////////////////////////////////////////////////
// 接続先情報取得
$host = "xxx.xxx.xxx.xxx";
$port = 80;
$path = $_SERVER["PATH_INFO"]; // アクセスするパス
if( $path=="" ) $path="/"; // パスが空の場合は "/"(ルート)に
if( ($q=$_SERVER["QUERY_STRING"])!="" ) $path.="?$q"; // クエリ文字列がある場合にはパスにクエリ文字列を付加

//////////////////////////////////////////////////////////////////
// リクエストの作成
$method = $_SERVER["REQUEST_METHOD"]; // メソッド (GET POST HEADなど)
$protocol = $_SERVER["SERVER_PROTOCOL"]; // プロトコル (HTTP/1.0 または HTTP/1.1)
$request = "$method $path $protocol\r\n"; // リクエスト行

// リクエストヘッダをコピーする
foreach(getallheaders() as $name=>$value)
{
// 一部のヘッダは書き換える
switch( $name )
{
case "Host": // Hostヘッダ
$request.="$name: $host\r\n"; // 接続先ホストに変更する
break;

case "Connection": // Connectionヘッダ
$request.="$name: close\r\n"; // 最終的にソケットはクローズするため、"close"と指定する
break;

default: // その他
$request.="$name: $value\r\n"; // そのままコピー
break;
}
}
$request .= "\r\n"; // ヘッダの終端

//////////////////////////////////////////////////////////////////
// ホストに接続し、リクエストを送信する
$fp = fsockopen($host, $port); // 接続
fputs($fp, $request); // 送信

//////////////////////////////////////////////////////////////////
// ヘッダのクリア
$header = array(); // ヘッダー(生)
$info = array(); // ヘッダ情報

//////////////////////////////////////////////////////////////////
// レスポンス受信
$response = $header[] = fgets($fp); // レスポンス行の受信
list($p, $status) = split(" ", $response); // プロトコルとステータスコードに分ける

//////////////////////////////////////////////////////////////////
// ヘッダを受信する
while( ($h = fgets($fp))!==false )
{
if( eregi("^\r?\n$", $h) ) break;

$header[] = $h;

list($name, $value) = split(": ?", $h);
$info[$name] = eregi_replace("\r?\n$", "", $value);
}

//////////////////////////////////////////////////////////////////
// クライアントにヘッダを送信
foreach($header as $h) header($h);

//////////////////////////////////////////////////////////////////
// 本体を受信し、クライアントへ送信する (メソッドがHEAD)
if( strtoupper($method) == "HEAD" )
;

//////////////////////////////////////////////////////////////////
// 本体を受信し、クライアントへ送信する (ステータスが100番台もしくは204,304)
else if( ereg("1[0-9][0-9])|204|304", $status) )
;

//////////////////////////////////////////////////////////////////
// 本体を受信し、クライアントへ送信する (チャンクエンコーディングの場合)
else if( $info["Transfer-Encoding"]=="chunked" )
{
// 本体受信
while( ($c = fgets($fp))!==false )
{
// クライアントとの接続が切れていれば、処理を終了する
if( connection_status()!=CONNECTION_NORMAL ) goto close_socket;

// クライアントへデータ長を送信
echo $c;

// 終了の確認
list($s, $ext) = split("; ?|\r\n", $c); // データ長を抽出
if( $s=="0" ) break; // "0"なら抜ける

// 本体部分の受信
$data = "";
while( !feof($fp) && strlen($data)<$size )
{
if( connection_status()!=CONNECTION_NORMAL ) goto close_socket;
$data.=fread($fp, $size - strlen($data));
}
$data .= fread($fp,2); // エンドマークのCR/LFを受信

// クライアントへデータ本体を送信
echo $data;
}

// 追加ヘッダ受信
while( ($h = fgets($fp))!==false )
{
// クライアントとの接続が切れていれば、処理を終了する
if( connection_status()!=CONNECTION_NORMAL ) goto close_socket;

// クライアントへ追加ヘッダを送信
echo $h;

// 終了の確認
if( eregi("^\r?\n$", $h) ) break; // 空行なら抜ける
}
}

//////////////////////////////////////////////////////////////////
// 本体を受信し、クライアントへ送信する (Content-lengthヘッダによる長さ指定)
else if( isset($info["Content-Length"]) )
{
// 受信バイト数
$bytes = $info["Content-Length"] - 0;

// 受信
$data = "";
while( !feof($fp) && strlen($data)<$bytes )
{
if( connection_status()!=CONNECTION_NORMAL ) goto close_socket;
$data.=fread($fp, $size - strlen($data));
}

// クライアントへ出力
echo $data;
}

//////////////////////////////////////////////////////////////////
// 本体を受信し、クライアントへ送信する (EOFまで受信)
else
{
while( !feof($fp) )
{
// クライアントとの接続が切れていれば、処理を終了する
if( connection_status()!=CONNECTION_NORMAL ) goto close_socket;

echo fread($fp, 8192);
}
}

// 接続を閉じる
close_socket:
fclose($fp);
?>


そんな面倒くさいことしなくても、header("Location: http://xxx.xxx.xxx.xxx"); で終わりじゃん。と思うのだろうが、スクリプトを通すことによって、間に処理を入れることが可能になる。実際のJOBではリダイレクト先に別のフォームで入力したユーザー名/パスワードを使ってAuthorizationヘッダを挿入したりした。
Apacheの設定を以下のようにしてやれば、単純にプロキシされているのと見た目区別がつかない。
ProxyPass /dir /gateway.php

スポンサーサイト

テーマ:PHP - ジャンル:コンピュータ
copyright © 2004-2006 SHOJI, Powered By FC2ブログ all rights reserved.
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。