python 3.X系です
レンタルサーバを使っていて、ローカルのプログラムからレンタルサーバ上のDBにアクセスしたいな~
なんてことはあんまりないかもしれませんが、ローカルからDBサーバのアドレス、ポートに
直接アクセスは出来ないのが普通だと思います
今回はWebAPIをphpで用意してやって、jsonでローカルとサーバのやりとりをすることで、
DBサーバと間接的にやりとりするプログラムを作る機会があったので私がやった方法をメモしておきます
仕組みの概要
仕組みはざっと↓な感じです
① SQL文作成(python)
pythonのプログラム上で、DBサーバで実行するためのSQLを記述します
② SQL文をjsonにしてPOSTリクエスト投げる(python)
SQL文をjson形式に変換して、httpのPOSTリクエストをレンタルサーバ上のphpに投げます
③ json受け取り(php)
php側でリクエストを受けたら、jsonを受け取って、SQL文を変数に格納します
④ SQL発行(php)
SQL文を普通にMySQLに投げます
⑤ 結果受け取って、jsonにして返す(php)
DBから結果が返ってきたら、またjsonにしてローカル側に返します
⑥ 結果をjsonで受け取って、配列に格納(python)
httpレスポンスを受けて、またまたjsonを取り出して、プログラムコード中で使いたいように配列にぶち込みます
では、サンプルコードを交えつつ、解説していきます
python側のサンプルコード
まずpython(ローカル)側です、
ちなみに私が使用しているレンタルサーバではhttpのbasic認証でパスワードをかけていたので、認証前提のコードになっています
import urllib.request import json # basic認証用の関数 def setup_basic_auth(base_uri, user, password): password_mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm() password_mgr.add_password( realm=None, uri=base_uri, user=user, passwd=password) auth_handler = urllib.request.HTTPBasicAuthHandler(password_mgr) opener = urllib.request.build_opener(auth_handler) urllib.request.install_opener(opener) if __name__ == '__main__': # 認証の定義 url = 'phpのURL' user = 'ユーザ' passwd = 'パスワード' # httpをPOSTで投げる method = 'POST' # jsonを送るのでMIME設定 headers = {"Content-Type": "application/json"} # 実行したいsqlを変数に格納 sql_txt = "SELCT * FROM `test_table`" # jsonのオブジェクトを作ってutf-8にする obj = {"query": sql_txt} json_data = json.dumps(obj).encode("utf-8") # basic認証を通す setup_basic_auth(url, user, passwd) # phpにPOSTリクエスト投げる req = urllib.request.Request(url=url, data=json_data, method=method, headers=headers) # レスポンスを受け取って、jsonを変換しつつ配列に突っ込む response = urllib.request.urlopen(req) json_str = response.read().decode('utf-8') db_result = json.loads(json_str)
こんな感じです、
jsonを送るので、MIMEタイプを教えてあげるのと、
受け取る時に、json.loads()を使って、リスト(or 辞書)に変換してやるところがポイントでしょうか
では続いて、php側のサンプルコードです
php側のサンプルコード
MySQLにクエリ投げるところは今回のポイントじゃないので、省略しちゃいます
//jsonデータの受け取り、jsonをデコードしてオブジェクトに格納 $json_string = file_get_contents('php://input'); $obj = json_decode($json_string); //エラーが発生したとき用の配列とフラグ $return_msg_abnormal = array(); $error_flg = ""; //jsonが受け取れなかったら、エラーフラグと、エラーメッセージを入れる if(!isset($obj)){ $return_msg_abnormal[]["error"] = "GET NG"; $error_flg = "ABNORMAL"; } //オブジェクトからSQLを取り出す //python側ではSQL文のテキストをqueryというキーで送っていたので //以下の通りように取り出します $sql = $obj->query; /* * DB接続うんぬんかんぬんは省略します */ //エラーフラグが設定されてなかったらSQL実行 $select_result = array(); if(empty($error_flg)){ $result = mysql_query($sql); if (!$result) { $return_msg_abnormal[]["error"] = "check sql!"; $error_flg = "ABNORMAL"; } else { while ($row = mysql_fetch_assoc($result)) { $select_result[] = $row; } } } //jsonで返すのでヘッダーにMIMEタイプの定義 header('Content-Type: application/json'); //エラーが発生してなかったらSQLの実行結果を返す、エラーだったらメッセージを返す if(!empty($error_flg)){ echo json_encode($return_msg_abnormal, JSON_PRETTY_PRINT); }else{ echo json_encode($select_result, JSON_PRETTY_PRINT); }
いかがでしょうか
わりと雑な感じで申し訳ないですが、こんな感じでWebAPIを通せば、レンタルサーバでもhttp経由でDBサーバとやりとりできるので、もしそういう要件があれば参考にしていただければと思います!
なんとすばらしい☆*:.。. o(≧▽≦)o .。.:*☆
ありがとうございます!以前の職場でも要件がありましたが、顧客が自分のDBのデータを好きなように取って加工したい、みたいな要望がありました。これであれば、DMZなんかで内部ネットワークにアクセスさせないようにしていても、http経由で実現できますね。データ量とかが絡んでくると色々考慮しなければいけませんが・・