User:Mage Whopper/ortho mod proxy

From OpenStreetMap Wiki
Jump to: navigation, search

PHPやperlで書いて簡単だったので調子に乗ってCで書き直してみました。

使い方

apache2.2の環境であれば、簡単です。

まず、[1]でmod_cgidso.c をダウンロード、テキストを保存します。適当なディレクトリにおいて共有ライブラリを生成、インストールします。

apxs -cia mod_cgidso.c

インストールするのでsuかsudoで行ってください。

下記プログラムをUTF-8で保存して、同じディレクトリにおきます。

apxs -c ortho.c

すると ortho.soというライブラリがそのディレクトリ直下の ./libs 内にできます。

ortho.soを公開ディレクトリ(httdocsなど)におき、JOSMでは

ortho.soをおいたパス?VERSION=1.3.0&REQUEST=GetMap&LAYERS=ORTHO&STYLES=&CRS=EPSG:4612&FORMAT=image/png&BGCOLOR=OxFFFFFF&

をサーバに指定します。

最後にhttpdconfに

<IfModule mod_cgidso.c>
  AddHandler dso-script .so
</IfModule>

と記述を追加して、apacheを再起動します。

これでapacheのmodでortho転送が動作します。mod_phpとの違いがいかほどかはよくわかりません。 やってみたかっただけです。

ソース

もとにしたのがapacheライセンスだったのでこちらはapacheライセンスでお願いします。

/*
* For OSM projects
* 国土画像情報(オルソ化空中写真) 国土交通省 WMS server 利用転送モジュール for apache2.2.x
* written by/ Mage Whopper
* 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* This product includes software developed by
 * The Apache Software Foundation (http://www.apache.org/).
 *
 * Portions of this software were developed at the National Center
 * for Supercomputing Applications (NCSA) at the University of
 * Illinois at Urbana-Champaign.
 */

/*
 * http_script: keeps all script-related ramblings together.
 *
 * Compliant to cgi/1.1 spec
 *
 * Adapted by rst from original NCSA code by Rob McCool
 *
 * Apache adds some new env vars; REDIRECT_URL and REDIRECT_QUERY_STRING for
 * custom error responses, and DOCUMENT_ROOT because we found it useful.
 * It also adds SERVER_ADMIN - useful for scripts to know who to mail when
 * they fail.
 */
#define APR_WANT_STRFUNC
#include "http_request.h"

#include <string.h>

#define JOSM_GETS_NUM 11
#define REQUEST_GETS_NUM JOSM_GETS_NUM

/* mod_cgidso からは dso_main() が呼び出される */
int dso_main(request_rec *r, int argc, char **argv)
{
	const char *get;
	struct getstrings_S{
		char *str;
		char *key;
		char *value;
	} getstrings[REQUEST_GETS_NUM];	/* 要求がくる数分だけ用意 */
	unsigned int len,ele;
	char gets[1024];	/* クエリストリングをコピーする */
	char newurl[1024]="";	/* クエリストリングをコピーする */
	unsigned int getParamnum;	/* GET要求したパラメータ数 */
	char *ortho_base="http://orthophoto.mlit.go.jp:8888/wms/service/wmsRasterTileMap?";
	char rbbox[64] = "";	/* bbox入れ替え後 */
	char *bbox_elements[4];
	char addquery[128]=""; /* 追加クエリ */

	/* クエリストリングを取得 */
	get = apr_table_get(r->subprocess_env, "QUERY_STRING");
	/* ?以降がないとき */
	strncpy(gets, get, 1024);

	/* &でsplit */
	getstrings[0].str = strtok(gets, "&");
	for (len=1; len < REQUEST_GETS_NUM; len++){
		if ((getstrings[len].str = strtok(NULL, "&")) == NULL){
			break;
		}
	}
	getParamnum = len;
	/* =で分割 */
	/* 二段階にしないと、=の右辺が空の時に対応できない */
	for(len=0;len<getParamnum;len++){
		if((getstrings[len].key = strtok(getstrings[len].str, "=")) == NULL){
			break;
		}
		if((getstrings[len].value = strtok(NULL, "\0")) == NULL){
			continue;	/* =&が\0\0になって終了するので引数の個数で最後を判定 */
		}

		switch(getstrings[len].key[0]){
		case 'V':
		case 'v':	/* version VERSION */
			if((strcmp(getstrings[len].key, "VERSION") == 0) || (strcmp(getstrings[len].key, "version") == 0)){
				getstrings[len].value ="1.3.0";	/* ORTHOのWMSが固定値を要求 */
			}
			break;
		case 'R': 
		case 'r': /* request REQUEST*/
			if((strcmp(getstrings[len].key, "REQUEST") == 0) || (strcmp(getstrings[len].key, "request") == 0)){
				/* GetMap */
				if((strcmp(getstrings[len].value, "GetMap") == 0)){
					/**/
					strcat(addquery,"CRS=EPSG:4612");
#if 0	/* クライアントで変更できるものは見ない */
				}else if(!(strcmp(getstrings[len].value,"GetCapabilities") == 0)){
					getstrings[len].value ="GetMap";
#endif
				}
			}
			break;
		case 'B': case 'b':
			/* key = bbox */
			if((strcmp(getstrings[len].key, "BBOX") == 0) || (strcmp(getstrings[len].key, "bbox") == 0)){
				/* bboxを分解 */
				if((bbox_elements[0] = strtok(getstrings[len].value, ",")) == NULL){
					/* error */
				}
				for(ele=1;ele<4;ele++){
					if((bbox_elements[ele] = strtok(NULL, ",")) == NULL){
						if(len != 3){
							/* error*/
						}
					}
				}
				/* bbox の値を入れ替え */
				strcat(rbbox, bbox_elements[1]);	/* minLon */
				strcat(rbbox,",");
				strcat(rbbox, bbox_elements[0]);	/* minLat */
				strcat(rbbox,",");
				strcat(rbbox, bbox_elements[3]);	/* minLon */
				strcat(rbbox,",");
				strcat(rbbox, bbox_elements[2]);	/* maxLat */
				getstrings[len].value = rbbox;
			}
			break;
		defult: break;
		}
	}

	strcat(newurl,ortho_base); /* base URL */
	strcat(newurl,addquery);	/* 追加string */
	for(len=0;len<getParamnum;len++){
		strcat(newurl,"&");
		strcat(newurl,getstrings[len].key);	/* key */
		strcat(newurl,"=");
		if(getstrings[len].value !=NULL){
			strcat(newurl,getstrings[len].value);	/* value */
		}
	}

    /* リダイレクト */
    apr_table_set(r->headers_out, "Location", newurl); 
    return HTTP_MOVED_TEMPORARILY;
}

ひとりごち

mod proxyって言うページ名にしてしまいましたがこれはproxyじゃないしapacheのmod_proxyと名前がかぶってるし、いまいち過ぎる。mod_phpと実測で速度の違いがあるのかどうかは定かではないですが、これなら300アクセス/secぐらいは余裕で耐えられると思います。(てきとう)

今回はじめてapacheのモジュールなんて作ってみましたが、簡単でいいですね。webでCがかけないので仕方なくphpやらrubyをいじってる口なのでしばらくこれで遊んでみようかと考え中です。しかしreturnが二つあってもエラーが出ないのはちょっとがっくり。lintは無いのでしょうか。

参照URL