1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

KtorでHTTPでのリクエストを弾く

Last updated at Posted at 2019-02-14

その名の通りに、KtorでHTTPでのリクエストを弾くFeatureをシンプルに実装します。

REST API とかだとHTTPへのリクエストをHTTPSにリダイレクトさせるよりはエラーを吐かせたほうが良い気がしました。

Featureとは

Ktorアプリケーションを構成する一連の機能の事で基本的にはリクエストとレスポンスのパイプラインに組み込まれるものです。
Webアプリを作る上で欠かせない主要な機能であるルーティングもそのFeatureの一つとして定義されています。

Featureの詳細(公式リファレンス)

Featureを定義するためには、そのFeatureを表すクラスと、それを組み立てるために必要な情報を詰めるクラス、ApplicationFeatureを継承したcompanion objectが必要です。(別にcompanion objectじゃなくても動くけど公式のFeature達に倣う)

今回はHTTPでのリクエストを弾いてしまうFeatureを作るのでHttpsOnlyって名前にしたいと思います。

HttpsOnlyのざっくりした機能

とにかくシンプルにHttpでのリクエストを拒否したいだけなので要件は2つだけです。

  • Httpでのリクエストを受け取った際にHttpStatusCode:403を返す。
  • Httpでのリクエストを受け取った際に、任意の型のレスポンスボディを返す。

コード

解説はコード内コメントで行います。

//Httpでのリクエストを拒否するためのFeature
class HttpsOnly(configuration: Configuration) {
    //Httpでのリクエストが有った際に返すレスポンスのボディ
    val response = configuration.responseObject

    //HttpsOnlyを組み立てるための設定
    class Configuration {
        //Httpでのリクエストが有った際に返すレスポンスのボディ
        var responseObject: Any = "https only"
    }

    companion object Feature : ApplicationFeature<ApplicationCallPipeline, Configuration, HttpsOnly> {
        //Featureを一意に表すキー
        override val key: AttributeKey<HttpsOnly> = AttributeKey("HttpsOnly")

        //Featureのインストールを行う関数
        override fun install(pipeline: ApplicationCallPipeline, configure: Configuration.() -> Unit): HttpsOnly {
            //configureを元にHttpsOnlyを組み立て
            val feature = HttpsOnly(Configuration().apply(configure))
            
            
            /*
             ApplicationCallPipelineに、リクエストがHttpではないかをチェックして
             そうだったときにHttpStatusCode 403とHttpsOnly#responseを返す処理を挟む
            */
            pipeline.intercept(ApplicationCallPipeline.Features) {
                if (call.request.origin.scheme != "http") return@intercept
                call.respond(HttpStatusCode.Forbidden, feature.response)
                finish()
            }
            return feature
        }
    }
}

実際に使う際には

fun Application.installHttpsOnly() = install(HttpsOnly) {
    responseObject = ErrorResponse(
        statusCode = HttpStatusCode.Forbidden.value,
        reason = "sslRequired",
        message = "SSL is required for requests to this server"
    )
}

のようにしてやればHttpでのリクエストを受け取った際にエラーレスポンスを任意のオブジェクトをレスポンスボディにして返してやることが出来ます。
ktor-jackson等と組み合わせればJSONを返すことも可能です。

間違ったことや、おかしな点があればご指摘して頂けれると嬉しいです。

参考

https://ktor.io/servers/features.html
https://ktor.io/advanced/pipeline.html
https://ktor.io/servers/lifecycle.html
https://github.com/ktorio/ktor/blob/43eef9ed31ba33137501820a1b292af946ede6f8/ktor-server/ktor-server-core/jvm/src/io/ktor/features/DefaultHeaders.kt

1
1
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
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?