mirror of
https://github.com/metosin/reitit.git
synced 2025-12-30 05:08:25 +00:00
Merge pull request #148 from metosin/Generate-Options-endpoints-by-Default
Generate options-endpoints for ring by default
This commit is contained in:
commit
84501e3b40
13 changed files with 296 additions and 53 deletions
28
CHANGELOG.md
28
CHANGELOG.md
|
|
@ -31,12 +31,40 @@
|
|||
; #object[reitit.core$single_static_path_router]
|
||||
```
|
||||
|
||||
* `:options` requests are served for all routes by default with 200 OK to better support things like [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)
|
||||
* the default handler is not documented in Swagger
|
||||
* new router option `:reitit.ring/default-options-handler` to change this behavior. Setting `nil` disables this.
|
||||
|
||||
* updated deps:
|
||||
|
||||
```clj
|
||||
[ring/ring-core "1.7.0"] is available but we use "1.6.3"
|
||||
```
|
||||
|
||||
## `reitit-http`
|
||||
|
||||
* `:options` requests are served for all routes by default with 200 OK to better support things like [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)
|
||||
* the default handler is not documented in Swagger
|
||||
* new router option `:reitit.http/default-options-handler` to change this behavior. Setting `nil` disables this.
|
||||
|
||||
## `reitit-middleware`
|
||||
|
||||
* fix `reitit.ring.middleware.parameters/parameters-middleware`
|
||||
|
||||
* updated deps:
|
||||
|
||||
```clj
|
||||
[metosin/muuntaja "0.6.1"] is available but we use "0.6.0"
|
||||
```
|
||||
|
||||
## `reitit-swagger-ui`
|
||||
|
||||
* updated deps:
|
||||
|
||||
```clj
|
||||
[metosin/jsonista "0.2.2"] is available but we use "0.2.1"
|
||||
```
|
||||
|
||||
## 0.2.2 (2018-09-09)
|
||||
|
||||
* better documentation for interceptors
|
||||
|
|
|
|||
109
doc/ring/ring.md
109
doc/ring/ring.md
|
|
@ -2,15 +2,25 @@
|
|||
|
||||
[Ring](https://github.com/ring-clojure/ring) is a Clojure web applications library inspired by Python's WSGI and Ruby's Rack. By abstracting the details of HTTP into a simple, unified API, Ring allows web applications to be constructed of modular components that can be shared among a variety of applications, web servers, and web frameworks.
|
||||
|
||||
Read more about the [Ring Concepts](https://github.com/ring-clojure/ring/wiki/Concepts).
|
||||
|
||||
```clj
|
||||
[metosin/reitit-ring "0.2.2"]
|
||||
```
|
||||
|
||||
Ring-router adds support for [handlers](https://github.com/ring-clojure/ring/wiki/Concepts#handlers), [middleware](https://github.com/ring-clojure/ring/wiki/Concepts#middleware) and routing based on `:request-method`. Ring-router is created with `reitit.ring/router` function. It uses a custom route compiler, creating a optimized data structure for handling route matches, with compiled middleware chain & handlers for all request methods. It also ensures that all routes have a `:handler` defined. `reitit.ring/ring-handler` is used to create a Ring handler out of ring-router.
|
||||
## `reitit.ring/ring-router`
|
||||
|
||||
### Example
|
||||
`ring-router` is a higher order router, which adds support for `:request-method` based routing, [handlers](https://github.com/ring-clojure/ring/wiki/Concepts#handlers) and [middleware](https://github.com/ring-clojure/ring/wiki/Concepts#middleware).
|
||||
|
||||
It accepts the following options:
|
||||
|
||||
Simple Ring app:
|
||||
| key | description |
|
||||
| ---------------------------------------|-------------|
|
||||
| `:reitit.middleware/transform` | Function of `[Middleware] => [Middleware]` to transform the expanded Middleware (default: identity).
|
||||
| `:reitit.middleware/registry` | Map of `keyword => IntoMiddleware` to replace keyword references into Middleware
|
||||
| `:reitit.ring/default-options-handler` | Default handler for `:options` method in endpoints (default: default-options-handler)
|
||||
|
||||
Example router:
|
||||
|
||||
```clj
|
||||
(require '[reitit.ring :as ring])
|
||||
|
|
@ -18,10 +28,37 @@ Simple Ring app:
|
|||
(defn handler [_]
|
||||
{:status 200, :body "ok"})
|
||||
|
||||
(def app
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/ping" handler])))
|
||||
(def router
|
||||
(ring/router
|
||||
["/ping" {:get handler}]))
|
||||
```
|
||||
|
||||
Match contains `:result` compiled by the `ring-router`:
|
||||
|
||||
```clj
|
||||
(require '[reitit.core :as r])
|
||||
|
||||
(r/match-by-path router "/ping")
|
||||
;#Match{:template "/ping"
|
||||
; :data {:get {:handler #object[...]}}
|
||||
; :result #Methods{:get #Endpoint{...}
|
||||
; :options #Endpoint{...}}
|
||||
; :path-params {}
|
||||
; :path "/ping"}
|
||||
```
|
||||
|
||||
## `reitit.ring/ring-handler`
|
||||
|
||||
Given a `ring-router`, optional default-handler & options, `ring-handler` function will return a valid ring handler supporting both synchronous and [asynchronous](https://www.booleanknot.com/blog/2016/07/15/asynchronous-ring.html) request handling. The following options are available:
|
||||
|
||||
| key | description |
|
||||
| --------------|-------------|
|
||||
| `:middleware` | Optional sequence of middleware that wrap the ring-handler"
|
||||
|
||||
Simple Ring app:
|
||||
|
||||
```clj
|
||||
(def app (ring/ring-handler router))
|
||||
```
|
||||
|
||||
Applying the handler:
|
||||
|
|
@ -36,31 +73,46 @@ Applying the handler:
|
|||
; {:status 200, :body "ok"}
|
||||
```
|
||||
|
||||
The expanded routes shows the compilation results:
|
||||
The router can be accessed via `get-router`:
|
||||
|
||||
```clj
|
||||
(-> app (ring/get-router) (reitit/routes))
|
||||
; [["/ping"
|
||||
; {:handler #object[...]}
|
||||
; #Methods{:any #Endpoint{:data {:handler #object[...]},
|
||||
; :handler #object[...],
|
||||
; :middleware []}}]]
|
||||
(-> app (ring/get-router) (r/compiled-routes))
|
||||
;[["/ping"
|
||||
; {:handler #object[...]}
|
||||
; #Methods{:get #Endpoint{:data {:handler #object[...]}
|
||||
; :handler #object[...]
|
||||
; :middleware []}
|
||||
; :options #Endpoint{:data {:handler #object[...]}
|
||||
; :handler #object[...]
|
||||
; :middleware []}}]]
|
||||
```
|
||||
|
||||
Note the compiled resuts as third element in the route vector.
|
||||
|
||||
# Request-method based routing
|
||||
|
||||
Handler are also looked under request-method keys: `:get`, `:head`, `:patch`, `:delete`, `:options`, `:post` or `:put`. Top-level handler is used if request-method based handler is not found.
|
||||
Handlers can be placed either to the top-level (all methods) or under a specific method (`:get`, `:head`, `:patch`, `:delete`, `:options`, `:post`, `:put` or `:trace`). Top-level handler is used if request-method based handler is not found.
|
||||
|
||||
By default, the `:options` route is generated for all paths - to enable thing like [CORS](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing).
|
||||
|
||||
```clj
|
||||
(def app
|
||||
(ring/ring-handler
|
||||
(ring/router
|
||||
["/ping" {:name ::ping
|
||||
:get handler
|
||||
:post handler}])))
|
||||
[["/all" handler]
|
||||
["/ping" {:name ::ping
|
||||
:get handler
|
||||
:post handler}]])))
|
||||
```
|
||||
|
||||
Top-level handler catches all methods:
|
||||
|
||||
```clj
|
||||
(app {:request-method :delete, :uri "/all"})
|
||||
; {:status 200, :body "ok"}
|
||||
```
|
||||
|
||||
Method-level handler catches only the method:
|
||||
|
||||
```clj
|
||||
(app {:request-method :get, :uri "/ping"})
|
||||
; {:status 200, :body "ok"}
|
||||
|
||||
|
|
@ -68,19 +120,26 @@ Handler are also looked under request-method keys: `:get`, `:head`, `:patch`, `:
|
|||
; nil
|
||||
```
|
||||
|
||||
By default, `:options` is also supported (see router options to change this):
|
||||
|
||||
```clj
|
||||
(app {:request-method :options, :uri "/ping"})
|
||||
; {:status 200, :body ""}
|
||||
```
|
||||
|
||||
Name-based reverse routing:
|
||||
|
||||
```clj
|
||||
(-> app
|
||||
(ring/get-router)
|
||||
(reitit/match-by-name ::ping)
|
||||
:path)
|
||||
(r/match-by-name ::ping)
|
||||
(r/match->path))
|
||||
; "/ping"
|
||||
```
|
||||
|
||||
# Middleware
|
||||
|
||||
Middleware can be added with a `:middleware` key, either to top-level or under `:request-method` submap. It's value should be a vector of any the following:
|
||||
Middleware can be mounted using a `:middleware` key - either to top-level or under request method submap. Its value should be a vector of `reitit.middleware/IntoMiddleware` values. These include:
|
||||
|
||||
1. normal ring middleware function `handler -> request -> response`
|
||||
2. vector of middleware function `[handler args*] -> request -> response` and it's arguments
|
||||
|
|
@ -141,7 +200,3 @@ Top-level middleware, applied before any routing is done:
|
|||
(app {:request-method :get, :uri "/api/get"})
|
||||
; {:status 200, :body [:top :api :ok]}
|
||||
```
|
||||
|
||||
# Async Ring
|
||||
|
||||
All built-in middleware provide both 2 and 3-arity and are compiled for both Clojure & ClojureScript, so they work with [Async Ring](https://www.booleanknot.com/blog/2016/07/15/asynchronous-ring.html) and [Node.js](https://nodejs.org) too.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
(defproject ring-example "0.1.0-SNAPSHOT"
|
||||
:description "Reitit Ring App with Swagger"
|
||||
:dependencies [[org.clojure/clojure "1.9.0"]
|
||||
[ring/ring-jetty-adapter "1.7.0-RC2"]
|
||||
[ring/ring-jetty-adapter "1.7.0"]
|
||||
[metosin/reitit "0.2.3-SNAPSHOT"]]
|
||||
:profiles {:dev {:dependencies [[ring/ring-mock "0.3.2"]]
|
||||
:repl-options {:init-ns example.server}}})
|
||||
:repl-options {:init-ns example.server})
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
(defproject ring-example "0.1.0-SNAPSHOT"
|
||||
:description "Reitit Ring App with Swagger"
|
||||
:dependencies [[org.clojure/clojure "1.9.0"]
|
||||
[ring/ring-jetty-adapter "1.7.0-RC2"]
|
||||
[metosin/reitit "0.2.2"]]
|
||||
[ring/ring-jetty-adapter "1.7.0"]
|
||||
[metosin/reitit "0.2.3-SNAPSHOT"]]
|
||||
:repl-options {:init-ns example.server})
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
(update acc method expand opts)
|
||||
acc)) data ring/http-methods)])
|
||||
|
||||
(defn compile-result [[path data] opts]
|
||||
(defn compile-result [[path data] {:keys [::default-options-handler] :as opts}]
|
||||
(let [[top childs] (ring/group-keys data)
|
||||
compile (fn [[path data] opts scope]
|
||||
(interceptor/compile-result [path data] opts scope))
|
||||
|
|
@ -29,7 +29,12 @@
|
|||
(fn [acc method]
|
||||
(cond-> acc
|
||||
any? (assoc method (->endpoint path data method nil))))
|
||||
(ring/map->Methods {})
|
||||
(ring/map->Methods
|
||||
{:options
|
||||
(if default-options-handler
|
||||
(->endpoint path (assoc data
|
||||
:handler default-options-handler
|
||||
:no-doc true) :options nil))})
|
||||
ring/http-methods))]
|
||||
(if-not (seq childs)
|
||||
(->methods true top)
|
||||
|
|
@ -45,6 +50,14 @@
|
|||
support for http-methods and Interceptors. See [docs](https://metosin.github.io/reitit/)
|
||||
for details.
|
||||
|
||||
Options:
|
||||
|
||||
| key | description |
|
||||
| ---------------------------------------|-------------|
|
||||
| `:reitit.interceptor/transform` | Function of `[Interceptor] => [Interceptor]` to transform the expanded Interceptors (default: identity).
|
||||
| `:reitit.interceptor/registry` | Map of `keyword => IntoInterceptor` to replace keyword references into Interceptors
|
||||
| `:reitit.http/default-options-handler` | Default handler for `:options` method in endpoints (default: reitit.ring/default-options-handler)
|
||||
|
||||
Example:
|
||||
|
||||
(router
|
||||
|
|
@ -58,7 +71,9 @@
|
|||
([data]
|
||||
(router data nil))
|
||||
([data opts]
|
||||
(let [opts (meta-merge {:coerce coerce-handler, :compile compile-result} opts)]
|
||||
(let [opts (merge {:coerce coerce-handler
|
||||
:compile compile-result
|
||||
::default-options-handler ring/default-options-handler} opts)]
|
||||
(r/router data opts))))
|
||||
|
||||
(defn routing-interceptor
|
||||
|
|
|
|||
|
|
@ -10,6 +10,4 @@
|
|||
:form-params - a map of parameters from the body
|
||||
:params - a merged map of all types of parameter"
|
||||
{:name ::parameters
|
||||
:enter (fn [ctx]
|
||||
(let [request (:request ctx)]
|
||||
(assoc ctx :request (params/params-request request))))})
|
||||
:wrap params/wrap-params})
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@
|
|||
[ring.util.response :as response]])
|
||||
[clojure.string :as str]))
|
||||
|
||||
(declare get-match)
|
||||
(declare get-router)
|
||||
|
||||
(def http-methods #{:get :head :post :put :delete :connect :options :trace :patch})
|
||||
(defrecord Methods [get head post put delete connect options trace patch])
|
||||
(defrecord Endpoint [data handler path method middleware])
|
||||
|
|
@ -25,7 +28,7 @@
|
|||
(update acc method expand opts)
|
||||
acc)) data http-methods)])
|
||||
|
||||
(defn compile-result [[path data] opts]
|
||||
(defn compile-result [[path data] {:keys [::default-options-handler] :as opts}]
|
||||
(let [[top childs] (group-keys data)
|
||||
->endpoint (fn [p d m s]
|
||||
(-> (middleware/compile-result [p d] opts s)
|
||||
|
|
@ -37,7 +40,12 @@
|
|||
(fn [acc method]
|
||||
(cond-> acc
|
||||
any? (assoc method (->endpoint path data method nil))))
|
||||
(map->Methods {})
|
||||
(map->Methods
|
||||
{:options
|
||||
(if default-options-handler
|
||||
(->endpoint path (assoc data
|
||||
:handler default-options-handler
|
||||
:no-doc true) :options nil))})
|
||||
http-methods))]
|
||||
(if-not (seq childs)
|
||||
(->methods true top)
|
||||
|
|
@ -48,6 +56,11 @@
|
|||
(->methods (:handler top) data)
|
||||
childs))))
|
||||
|
||||
(defn default-options-handler [request]
|
||||
(let [methods (->> request get-match :result (keep (fn [[k v]] (if v k))))
|
||||
allow (->> methods (map (comp str/upper-case name)) (str/join ","))]
|
||||
{:status 200, :body "", :headers {"Allow" allow}}))
|
||||
|
||||
;;
|
||||
;; public api
|
||||
;;
|
||||
|
|
@ -57,6 +70,14 @@
|
|||
support for http-methods and Middleware. See [docs](https://metosin.github.io/reitit/)
|
||||
for details.
|
||||
|
||||
Options:
|
||||
|
||||
| key | description |
|
||||
| ---------------------------------------|-------------|
|
||||
| `:reitit.middleware/transform` | Function of `[Middleware] => [Middleware]` to transform the expanded Middleware (default: identity).
|
||||
| `:reitit.middleware/registry` | Map of `keyword => IntoMiddleware` to replace keyword references into Middleware
|
||||
| `:reitit.ring/default-options-handler` | Default handler for `:options` method in endpoints (default: default-options-handler)
|
||||
|
||||
Example:
|
||||
|
||||
(router
|
||||
|
|
@ -64,13 +85,13 @@
|
|||
[\"/users\" {:get get-user
|
||||
:post update-user
|
||||
:delete {:middleware [wrap-delete]
|
||||
:handler delete-user}}]])
|
||||
|
||||
See router options from [[reitit.core/router]] and [[reitit.middleware/router]]."
|
||||
:handler delete-user}}]])"
|
||||
([data]
|
||||
(router data nil))
|
||||
([data opts]
|
||||
(let [opts (meta-merge {:coerce coerce-handler, :compile compile-result} opts)]
|
||||
(let [opts (merge {:coerce coerce-handler
|
||||
:compile compile-result
|
||||
::default-options-handler default-options-handler} opts)]
|
||||
(r/router data opts))))
|
||||
|
||||
(defn routes
|
||||
|
|
@ -182,7 +203,7 @@
|
|||
|
||||
| key | description |
|
||||
| --------------|-------------|
|
||||
| `:middleware` | Optional sequence of middleware that are wrap the [[ring-handler]]"
|
||||
| `:middleware` | Optional sequence of middleware that wrap the ring-handler"
|
||||
([router]
|
||||
(ring-handler router nil))
|
||||
([router default-handler]
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@
|
|||
[metosin/spec-tools "0.7.1"]
|
||||
[metosin/schema-tools "0.10.4"]
|
||||
[metosin/ring-swagger-ui "2.2.10"]
|
||||
[metosin/muuntaja "0.6.0"]
|
||||
[metosin/jsonista "0.2.1"]
|
||||
[metosin/muuntaja "0.6.1"]
|
||||
[metosin/jsonista "0.2.2"]
|
||||
[metosin/sieppari "0.0.0-alpha5"]]
|
||||
|
||||
:plugins [[jonase/eastwood "0.2.6"]
|
||||
|
|
@ -65,10 +65,10 @@
|
|||
|
||||
[ring "1.7.0"]
|
||||
[ikitommi/immutant-web "3.0.0-alpha1"]
|
||||
[metosin/muuntaja "0.6.0"]
|
||||
[metosin/muuntaja "0.6.1"]
|
||||
[metosin/ring-swagger-ui "2.2.10"]
|
||||
[metosin/sieppari "0.0.0-alpha5"]
|
||||
[metosin/jsonista "0.2.1"]
|
||||
[metosin/jsonista "0.2.2"]
|
||||
|
||||
[criterium "0.4.4"]
|
||||
[org.clojure/test.check "0.9.0"]
|
||||
|
|
|
|||
|
|
@ -1,3 +1,17 @@
|
|||
(ns reitit.http.interceptors.parameters-test)
|
||||
(ns reitit.http.interceptors.parameters-test
|
||||
(:require [clojure.test :refer [deftest testing is]]
|
||||
[reitit.http.interceptors.parameters :as parameters]
|
||||
[reitit.http :as http]
|
||||
[reitit.interceptor.sieppari :as sieppari]))
|
||||
|
||||
;; TODO
|
||||
(deftest parameters-test
|
||||
(let [app (http/ring-handler
|
||||
(http/router
|
||||
["/ping" {:get #(select-keys % [:params :query-params])}]
|
||||
{:data {:interceptors [(parameters/parameters-interceptor)]}})
|
||||
{:executor sieppari/executor})]
|
||||
(is (= {:query-params {"kikka" "kukka"}
|
||||
:params {"kikka" "kukka"}}
|
||||
(app {:request-method :get
|
||||
:uri "/ping"
|
||||
:query-string "kikka=kukka"})))))
|
||||
|
|
|
|||
|
|
@ -169,6 +169,50 @@
|
|||
(testing "handler rejects"
|
||||
(is (= -406 (:status (app {:request-method :get, :uri "/pong"}))))))))))
|
||||
|
||||
(deftest default-options-handler-test
|
||||
(let [response {:status 200, :body "ok"}]
|
||||
|
||||
(testing "with defaults"
|
||||
(let [app (http/ring-handler
|
||||
(http/router
|
||||
[["/get" {:get (constantly response)
|
||||
:post (constantly response)}]
|
||||
["/options" {:options (constantly response)}]
|
||||
["/any" (constantly response)]])
|
||||
{:executor sieppari/executor})]
|
||||
|
||||
(testing "endpoint with a non-options handler"
|
||||
(is (= response (app {:request-method :get, :uri "/get"})))
|
||||
(is (= {:status 200, :body "", :headers {"Allow" "GET,POST,OPTIONS"}}
|
||||
(app {:request-method :options, :uri "/get"}))))
|
||||
|
||||
(testing "endpoint with a options handler"
|
||||
(is (= response (app {:request-method :options, :uri "/options"}))))
|
||||
|
||||
(testing "endpoint with top-level handler"
|
||||
(is (= response (app {:request-method :get, :uri "/any"})))
|
||||
(is (= response (app {:request-method :options, :uri "/any"}))))))
|
||||
|
||||
(testing "disabled via options"
|
||||
(let [app (http/ring-handler
|
||||
(http/router
|
||||
[["/get" {:get (constantly response)}]
|
||||
["/options" {:options (constantly response)}]
|
||||
["/any" (constantly response)]]
|
||||
{::http/default-options-handler nil})
|
||||
{:executor sieppari/executor})]
|
||||
|
||||
(testing "endpoint with a non-options handler"
|
||||
(is (= response (app {:request-method :get, :uri "/get"})))
|
||||
(is (= nil (app {:request-method :options, :uri "/get"}))))
|
||||
|
||||
(testing "endpoint with a options handler"
|
||||
(is (= response (app {:request-method :options, :uri "/options"}))))
|
||||
|
||||
(testing "endpoint with top-level handler"
|
||||
(is (= response (app {:request-method :get, :uri "/any"})))
|
||||
(is (= response (app {:request-method :options, :uri "/any"}))))))))
|
||||
|
||||
(deftest async-http-test
|
||||
(let [promise #(let [value (atom ::nil)]
|
||||
(fn
|
||||
|
|
|
|||
|
|
@ -1,3 +1,15 @@
|
|||
(ns reitit.ring.middleware.parameters-test)
|
||||
(ns reitit.ring.middleware.parameters-test
|
||||
(:require [clojure.test :refer [deftest testing is]]
|
||||
[reitit.ring.middleware.parameters :as parameters]
|
||||
[reitit.ring :as ring]))
|
||||
|
||||
;; TODO
|
||||
(deftest parameters-test
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
["/ping" {:get #(select-keys % [:params :query-params])}]
|
||||
{:data {:middleware [parameters/parameters-middleware]}}))]
|
||||
(is (= {:query-params {"kikka" "kukka"}
|
||||
:params {"kikka" "kukka"}}
|
||||
(app {:request-method :get
|
||||
:uri "/ping"
|
||||
:query-string "kikka=kukka"})))))
|
||||
|
|
|
|||
|
|
@ -197,6 +197,48 @@
|
|||
(testing "handler rejects"
|
||||
(is (= -406 (:status (app {:request-method :get, :uri "/pong"}))))))))))
|
||||
|
||||
(deftest default-options-handler-test
|
||||
(let [response {:status 200, :body "ok"}]
|
||||
|
||||
(testing "with defaults"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
[["/get" {:get (constantly response)
|
||||
:post (constantly response)}]
|
||||
["/options" {:options (constantly response)}]
|
||||
["/any" (constantly response)]]))]
|
||||
|
||||
(testing "endpoint with a non-options handler"
|
||||
(is (= response (app {:request-method :get, :uri "/get"})))
|
||||
(is (= {:status 200, :body "", :headers {"Allow" "GET,POST,OPTIONS"}}
|
||||
(app {:request-method :options, :uri "/get"}))))
|
||||
|
||||
(testing "endpoint with a options handler"
|
||||
(is (= response (app {:request-method :options, :uri "/options"}))))
|
||||
|
||||
(testing "endpoint with top-level handler"
|
||||
(is (= response (app {:request-method :get, :uri "/any"})))
|
||||
(is (= response (app {:request-method :options, :uri "/any"}))))))
|
||||
|
||||
(testing "disabled via options"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
[["/get" {:get (constantly response)}]
|
||||
["/options" {:options (constantly response)}]
|
||||
["/any" (constantly response)]]
|
||||
{::ring/default-options-handler nil}))]
|
||||
|
||||
(testing "endpoint with a non-options handler"
|
||||
(is (= response (app {:request-method :get, :uri "/get"})))
|
||||
(is (= nil (app {:request-method :options, :uri "/get"}))))
|
||||
|
||||
(testing "endpoint with a options handler"
|
||||
(is (= response (app {:request-method :options, :uri "/options"}))))
|
||||
|
||||
(testing "endpoint with top-level handler"
|
||||
(is (= response (app {:request-method :get, :uri "/any"})))
|
||||
(is (= response (app {:request-method :options, :uri "/any"}))))))))
|
||||
|
||||
(deftest async-ring-test
|
||||
(let [promise #(let [value (atom ::nil)]
|
||||
(fn
|
||||
|
|
|
|||
|
|
@ -183,6 +183,21 @@
|
|||
(-> {:request-method :get :uri "/swagger.json"}
|
||||
(app) :body :x-id)))))
|
||||
|
||||
(deftest with-options-endpoint-test
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
[["/ping"
|
||||
{:options (constantly "options")}]
|
||||
["/pong"
|
||||
(constantly "options")]
|
||||
["/swagger.json"
|
||||
{:get {:no-doc true
|
||||
:handler (swagger/create-swagger-handler)}}]]))]
|
||||
(is (= ["/ping" "/pong"] (spec-paths app "/swagger.json")))
|
||||
(is (= #{::swagger/default}
|
||||
(-> {:request-method :get :uri "/swagger.json"}
|
||||
(app) :body :x-id)))))
|
||||
|
||||
(deftest all-parameter-types-test
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
|
|
|
|||
Loading…
Reference in a new issue