ITゲリラ戦士にアパッチはいらない Pt. 1 <rack で OpenLayers の TMS 対応サイトを作るまで>

OpenLayers.Layer.TMS を研究するために、rack で TMS 対応サイトを作りました。これから TMS サーバを作るつもりです。

rack を使った理由

アパッチを使うと、アパッチ依存の知識が前提になり、教育が難しくなります。Ruby と gems さえインストールされていればすぐに使えて、ログを標準出力で観察でき、必要な時だけサーバを立ち上げ、知識を得たらすぐに綺麗にサーバを撤収できる、rack を使うことにしました。
メインストリーム IT から離れた業務分野に浸透中で、かつ Web によって世界を良くする手法を開発したいとお考えのITエンジニアのみなさん(うまいこというと、ITゲリラ戦士の皆さん)に、この rack を使う手法をおすすめしたいと思ったりしています*1

前提知識

準備

sudo gem install rack

Windows なら sudo はいりません。

スクリプト

下のような ruby スクリプトを作りました。簡潔な記述をすることを優先しています。これを例えば server.ru という名前で保存します。

require 'stringio'

use Rack::CommonLogger

map '/' do
  run proc {|env|
    [200, {'Content-Type' => 'text/html'}, StringIO.new(<<-EOS
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<script src="http://openlayers.org/dev/OpenLayers.js"></script>
<script>
var map;

function osm_getTileURL(bounds) {
  var res = this.map.getResolution();
  var x = Math.round((bounds.left - this.maxExtent.left) / 
                     (res * this.tileSize.w));
  var y = Math.round((this.maxExtent.top - bounds.top) / 
                     (res * this.tileSize.h));
  var z = this.map.getZoom();
  var limit = Math.pow(2, z);

  if (y < 0 || y >= limit) {
    return OpenLayers.Util.getImagesLocation() + "404.png";
  } else {
    x = ((x % limit) + limit) % limit;
    return this.url + z + "/" + x + "/" + y + "." + this.type;
  }
}

function init() {
  map = new OpenLayers.Map('map', {
    controls:[
      new OpenLayers.Control.Navigation(),
      new OpenLayers.Control.PanZoomBar(),
      new OpenLayers.Control.LayerSwitcher(),
      new OpenLayers.Control.Permalink(),
      new OpenLayers.Control.MousePosition(),
      new OpenLayers.Control.Attribution()],
    maxExtent: 
      new OpenLayers.Bounds(-20037508.34,-20037508.34,20037508.34,20037508.34),
    numZoomLevels:18,
    maxResolution: 156543.0399,
    units: 'm',
    projection: new OpenLayers.Projection("EPSG:900913"),
    displayProjection: new OpenLayers.Projection("EPSG:4326")});
  var tah = new OpenLayers.Layer.TMS(
    'OSM Tiles@Home', 
    'http://tah.openstreetmap.org/Tiles/tile/',
    {type: 'png', getURL: osm_getTileURL,
     displayOutsideMaxExtent: true,
     attribution: 'map: OpenStreetMap Tiles@Home'});
  map.addLayers([tah]);
  if(!map.getCenter()) {
    map.setCenter(new OpenLayers.LonLat(9.69873, 52.38736).transform(
      new OpenLayers.Projection("EPSG:4326"),
      new OpenLayers.Projection("EPSG:900913")), 15);
  }
}
</script>
</head>
<body onload="init()">
<div id="map"></div>
</body>
</html>
    EOS
    )]
  }
end

実行

rackup server.ru

としておいて、ブラウザで http://localhost:9292/ にアクセスすると OpenStreetMap の Tiles@Home の地図が表示されるはずです*2

これから

ここまでだけであればふつうの HTML ファイルをアパッチに持たせる方が簡単です。これから、localhost に対する OpenLayers.Layer.TMS を作成し、rack の反応を見ながら TMS サーバを作り上げていきます。

また、ここまでだけであれば webrick のほうが一つ手が少ないのですが、いずれにしても TMS で rmagick みたいなものを使うつもりなので、gem を使っています。

*1:でも、この方法を使って失敗しても責任は持ちません :-)

*2:ドイツの OpenStreetMap ですが、すごいです。日本の OpenStreetMap ももちろん尊敬しますが、ドイツの OpenStreetMap の現時点の完成度には驚嘆すべきものがあると感じます。