2016-10-19 34 views
3

のリングCompojureを使用してClojure Web APIを開発しています。 APIは、指定されたルートに基づいてHTTPおよびHTTPS要求を受け入れる必要があります。例えばClojureとRingを使用したHTTPSリクエスト

アプリ-ルート考えてみましょう:

(defroutes app-routes    
      (POST "/route-one" {request :request} (processRequet request)) 
      (POST "/route-two" {request :request} (processRequet request))) 

私はルート-1ルート-2のみHTTPS要求を受け入れるための唯一のHTTPリクエストとを受け入れるようにしたいです。

これは可能ですか?

私は、次の設定で桟橋を実行してみました:

(jetty/run-jetty #'app {:join? false :ssl? true :ssl-port 8443 :keystore "./resources/keystore.jks" :key-password "12345678"}) 

HTTPS要求を受け入れるようにAPIを有効にし、それは同じルートにHTTP要求をブロックしませんでした。

また、私は運でHTTPプロトコルを無効にしてみました:

(jetty/run-jetty #'app {:port 5000 :join? false :ssl? true :ssl-port 8443 :keystore "./resources/keystore.jks" :key-password "12345678" :http? false}) 

私がオンライン読んだものから、リング HTTPS要求のための標準的な手順は、すべてのHTTPSリクエストを管理するために、リバースプロキシとしてnginxのを使用しています。

しかし、私はオンラインで実装が見つかりませんでした。

アイデア?

+0

まだhttp://pedestal.io/を見ましたか?それはあなたの状況に合ったと思う複数の "サーバ"を扱うための設定を持っています。 –

答えて

2
これを達成するための一つの簡単な方法は、例えば、あなたのルート内の着信要求のスキームをチェックすることです

:そうでも、

(defroutes app-routes 
    (POST "/route-one" request 
     (if (= (:scheme req) :http) 
      (process-requet request) 
      {:status 403 :body "https not supported"})) 
    (POST "/route-two" request 
     (if (= (:scheme req) :https) 
      (process-requet request) 
      {:status 403 :body "http not supported"}))) 

あなたはもちろん、別の関数やマクロにこの方式のチェックを抽出することができます多くのルートがある場合、これはあなたのコードにあまりにも多くのノイズがなければ実行可能なオプションになる可能性があります。

多くのルートがあり、追加のコールを追加したりそれぞれにチェックしたりしたくない場合、これを達成する別の方法はアプリケーションにミドルウェアを追加することです。ミドルウェアは、要求に含まれている:schemeを確認し、適合しない要求を拒否することができます。たとえば:

(defn wrap-https-only [handler] 
    (fn [req] 
    (if (= (:scheme req) :https) 
     (handler req) 
     {:status 403 :body "http not supported"}))) 

(defn wrap-http-only [handler] 
    (fn [req] 
    (if (= (:scheme req) :http) 
     (handler req) 
     {:status 403 :body "https not supported"}))) 

トリッキーな部分は、あなたが選択的に、いくつかのルートではなく他の人にこのミドルウェアを適用することで、Compojureはこれを実行するための簡単な方法を提供していません。あなたはミドルウェアが各サブセットに適用されていることをここで見ることができます

(def http-routes 
    (-> (routes (POST "/http-only/route-one" request 
        (process-requet request))) 
     wrap-http-only)) 

(def https-routes 
    (-> (routes (POST "/http-only/route-two" request 
        (process-requet request))) 
     wrap-https-only)) 


(defroutes app-routes 
    (ANY "/http-only/*" [] http-routes) 
    (ANY "/https-only/*" [] https-routes)) 

:あなたはいくつかの一般的なすべてのあなたのhttpルートでパス、および(グループにそれらをする)すべてのHTTPSのルートを持っているなら、あなたはこのようなパターンを使用することができます経路の最初の部分が一致する場合にのみ実行されます。これで、好きなだけ多くのルートを追加することができ、ミドルウェアはすべてのルートのスキームチェックを処理します。このアプローチでは、最初の 'app-routes'ルートで何らかの方法でルートのサブセットを識別できる必要があります。この場合はパスで識別しています。

スキームをチェックするときに注意すべきことは、SSLをロードバランサにオフロードすることを決定した場合、これは動作しないことに注意してください。その場合、アプリケーションは常にHTTP(HTTPSではなく)要求を受信します。普通は:schemeの値の代わりにX-Forwarded-Protoヘッダーをチェックするだけで同じ結果を得ることができます。

関連する問題