Slim3でhttpメソッドとControllerをマッピングする

前回、Slim3における拡張子付きURIのマッピングを試した。
今度は、同じURLへのリクエストについて、httpメソッドがGETならGetController、DELETEメソッドならDeleteControllerが呼ばれるみたいな感じで、httpメソッドとControllerを一対一にしたら、RESTfulなコードを書くときにController#isGet()とかを使うよりすっきりするんじゃないかと思い、試した。

まず、addRoutingは以下のようにする。Controller名にひもづく部分は適当に"httpmethod"とかにする。置換用文字列。

	public AppRouter() {
		addRouting("/user/{id}", "/user/httpmethod?id={id}");
        }

Controllerに処理が移る前に、requestのメソッドを取得する必要がある。RouterImpl#route()の引数がrequestなので、これをAppRouter内でオーバーライドして、マッピングのtoをrequestから取得したhttpメソッドの文字列で書き換える。

	@Override
	public String route(HttpServletRequest request, String path) {
		String to = super.route(request, path);
		if(to != null) {
			return to.replace("httpmethod", request.getMethod().toLowerCase());
		}
		
		return null;
		
	}

ここではControllerのクラス名をGet〜とかPost〜にした。よって"GET"とか"POST"だとマッピングされないので、toLowerCase()で小文字にする。

上記AppRouterを記述した上で、実際に試してみる。フォームからpostメソッドでURLにリクエストを投げるHTMLを用意。

<form action="./user/12345" method="POST">
<input type="submit" />
</form>

マッピングされるController。

public class PostController extends Controller {

	@Override
	protected Navigation run() throws Exception {
		response.getWriter().println("postcontroller");
		response.flushBuffer();
		return null;
	}

}

これでプロジェクトをRunして、HTMLでSubmit。

マッピング成功。「/user/12345」というURLにPOSTメソッドで、root.controller.user.PostControllerが呼び出せた。

しかし、AppRouter#route()をオーバーライドしてるので、予期しない動作がありそうで怖い。あくまでも実験なので実用に耐えるかは未検証です。