2016-10-19 8 views
3

Я разрабатываю веб-API Clojure, используя Кольцо и Compojure. API должен иметь возможность принимать запросы HTTP и HTTPS на основе указанного маршрута.Запросы HTTPS с Clojure и Ring

Например:

Рассмотрим следующие приложение-маршруты:

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

Я хочу маршрутный один принимать только запросы HTTP и маршрут-два принимать только HTTPS запросы ,

Возможно ли это?

Я попытался запустить причала со следующими параметрами:

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

Это позволило API принимать запросы HTTPS, но не блокирует HTTP-запросы к тем же маршрутам.

Я также попытался отключить протокол HTTP не повезло:

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

Из того, что я прочитал в Интернете, стандартная процедура для Ring запросов HTTPS использует Nginx в качестве обратного прокси-сервера для управления всеми запросами HTTPS ,

Но я не нашел никакой реализации в Интернете.

Любые идеи?

+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 не предлагает простой способ сделать это. Если у вас есть какой-то общий путь во всех ваших HTTP маршрутов, и все ваши Https маршруты (сгруппировать их), то вы можете использовать шаблон, как это:

(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)) 

Вы можете увидеть здесь, что промежуточное программное обеспечение применяется к каждому подмножеству маршрутов, и поэтому он будет выполняться только в том случае, если соответствует первая часть пути. Теперь вы можете добавить столько маршрутов, сколько хотите, а промежуточное ПО позаботится о проверке схемы для всех.Обратите внимание: этот подход требует, чтобы вы каким-то образом идентифицировали подмножества маршрутов на начальных маршрутах «маршруты приложения», в этом случае я идентифицировал их по пути.

При проверке схемы следует обратить внимание, что это не будет работать, если вы решите отключить SSL для балансировки нагрузки. В этом случае ваше приложение всегда будет получать запросы HTTP (не HTTPS). Обычно вы можете добиться того же, просто проверив заголовок X-Forwarded-Proto вместо значения :scheme.