WebサービスからJSONを取得してフロントPerlCGIで整形
フロントのWebサーバはPerl,PHP,Rubyくらいしか使えない環境で、アプリ本体はそれ以外で実装したい。
プロキシサーバも使えないので、どうしたものかと思っていたら、Webサービス方式にすれば良かったことに気づいたので、ちょっと試してみました。
データ形式はXMLでも良さそうですが、最近はやっぱりJSONが便利みたいなので、JSONでやります。
今回やること
- 検索結果をJSONで返せるようにする(簡易Webサービス化)
- PerlCGIから上のWebサービスにアクセスし、結果のJSONを元にHTMLを生成
簡易Webサービス
もちろん、これは何で作ってもかまいません。
サンプルとして、Play(scala)で作ったものを載せておきます。
元々は、searchメソッドの結果をHTMLテンプレートに渡すようになっていたのを、JSONでレスポンスを返せるようにしました。
そして、これはちょうど1年前にやった「HerokuでPlay2.0+PostgreSQL」のものなので、Herokuにアップして試しました。
- controllers/Application.scala
package controllers import play.api._ import play.api.mvc._ import play.api.libs.json._ import play.api.libs.json.Json.toJson object Application extends Controller { case class Person(name: String, age: Int) def index(q: String) = Action { implicit object PersonFormat extends Format[Person] { def writes(o: Person): JsValue = Json.toJson(Map("name" -> toJson(o.name), "age" -> toJson(o.age))) def reads(json: JsValue): Person = Person( (json \ "name").as[String], (json \ "age").as[Int]) } val records: Seq[Person] = search(q) Ok(toJson(Map("records" -> records))) } private def search(q: String): Seq[Person] = Seq() // 検索結果を返す }
返されるJSONはこんな感じです。
{"records": [ { "name" : "Suzuki Jiro", "age": 34 }, { "name" : "Matsui Hiroyuki", "age": 56 } ]}
フロントのPerlCGI
URLはダミーです。
特に難しいことはやっていません。
use strict; use warnings; use utf8; use Encode; use CGI; use URI::Escape; use LWP::UserAgent; use JSON; my $cgi = new CGI; my $q = $cgi->param("q"); # parameter my $url = "http://example.com/search?query=" . uri_escape(encode('utf-8', $q)); my $ua = LWP::UserAgent->new; my $req = HTTP::Request->new("GET", $url); my $res = $ua->request($req); # HTML print "Content-Type: text/html; charset=utf-8\n\n"; print "<html><body>"; if ($res->is_success) { my $json = JSON->new->utf8(0)->decode(decode_utf8($res->content)); my $i = 0; my $records = $json->{records}; # Array Ref print "<h1>List</h1><p>Q=[$q]</p><ul>"; for my $r (@{$records}) { printf "<li>No.%04d: name=%s, age=%s</li>", ++$i, $r->{name}, $r->{age}; } print "</ul>"; } else { print "<p>ERROR</p>"; } print "</body></html>";
まとめ
実際にやってみるまでは、いろいろ制限があってつまずくかな、と思いきや、あまりに普通に出来たので拍子抜けしてしまいました。PerlのJSONモジュールくらいですね。
でもそれは、グーグル先生とJSONさんがあればこそですね。サマサマです。
ミッションクリティカルなどのシビアな性能が求められるシステムには向かないでしょうが、そうでなければ分散が簡単に実現できるのが良いかなと思います。