LoginSignup
7
7

More than 5 years have passed since last update.

Vert.xでFlickrのクライアントとHTTPサーバーを実装する

Posted at

Instant Vert.xを読みながらサンプルコードを試してみる。

今回はHttpServerとHttpClient(Flickr)。

まずはクライアント側のコード


public class ClientVerticle extends Verticle {

  HttpClient client;

  public void start() {
    container.logger().info("ClientVerticle deployed.");
    client = vertx.createHttpClient();
    client.setHost("ycpi-api.flickr.com").setPort(80);
    vertx.eventBus().registerHandler("webclient_address", this::handleClientEvent);
  }

  void handleClientEvent(Message<String> msg) {
    container.logger().info(Rythm.render("Recieved tag:@tag", msg));
    client.getNow(
        Rythm.render("/services/feeds/photos_public.gne?tags=@message&format=json", msg.body()),
        (HttpClientResponse res) -> {
      container.logger().info(Rythm.render("Got response. status_code=[@status].", res.statusCode()));
      res.bodyHandler((Buffer body) -> {
        String json = body.toString();
        // かっこに囲まれた変なJSONを返すので削る。
        json = json.substring(json.indexOf('(') + 1, json.length() - 1);
        json = json.replaceAll("\\\\'", "'");
        msg.reply(json);
      });
    });
  }
}

EventBusの"webclient_address"というアドレスでイベントが着火するとイベントのメッセージに書かれたキーワードを使ってFlickrのAPIから画像を集めてきます。

FlickrのAPIは特別な認証が必要ないですが、JSONとしてパースするにはレスポンスをちょっと成形する必要があります。

続いてサーバー側のコード

public class ServerVerticle extends Verticle {

  public void start() {
    container.deployVerticle(ClientVerticle.class.getCanonicalName());
    HttpServer server = vertx.createHttpServer();
    RouteMatcher routeMatcher = new RouteMatcher();
    routeMatcher.get("/tag/:theTag", this::handleTag);
    routeMatcher.getWithRegEx(".*", this::handleOthers);
    server.requestHandler(routeMatcher).listen(8080);
  }

  private void handleTag(HttpServerRequest req) {
    String tag = req.params().get("theTag");
    container.logger().info(Rythm.render("Looking for:@searchWord", tag));
    vertx.eventBus().send("webclient_address", tag, (Message<String> result) -> {
      String json = result.body();
      JsonObject jsonObj = new JsonObject(json);
      String html = Rythm.render(PAGE_TEMPLATE, tag, jsonObj.getArray("items"));
      req.response().end(html);
    });
  }

  private void handleOthers(HttpServerRequest req) {
    req.response().end("ERROR: fill the tag.");
  }

  private static final String PAGE_TEMPLATE =
      "@import org.vertx.java.core.json.JsonArray\n"
      + "@import org.vertx.java.core.json.JsonObject\n"
      + "@args String searchWord, JsonArray items\n"
      + "<html><h1>Result for @searchWord </h1>\n"
      + "@for(items) {\n"
      + "@{ JsonObject item = (JsonObject)_; }\n"
      + "<h3>@item.getString(\"title\")</h3>\n"
      + "<a href=\"@item.getString(\"link\")\">"
      + "<img src=\"@item.getObject(\"media\").getString(\"m\")\" />"
      + "</a>\n"
      + "}\n" + "</html>";
}

start()ではクライアントのVerticleをデプロイした後、RouteMatcherを使ってHTTP Serverで受け取るリクエストののルーティングを行っています。

クライアント側で書いたコードをこちらのVerticleに書いても問題なく動作しますが、プログラムの関心事毎にVerticleを作る方がよかろうとのことです。(例えば、データベースへの接続、WEBサーバー、認証、キャッシュ、など)

サーバーがレスポンスとして返却するHTMLのレンダリングにはRythmというテンプレートエンジンを使っています。

Verticleを実行した後はブラウザからhttp://localhost:8080/tag/catにアクセスすると、ClientVerticleが猫の画像を集めてきて、ServerVerticleが集めた猫の画像を並べたHTMLをブラウザに返却します。

今回のソースコードはこちらにあります。

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7