mirror of
https://github.com/metosin/reitit.git
synced 2025-12-23 10:41:10 +00:00
commit
46fb851444
8 changed files with 328 additions and 230 deletions
56
CHANGELOG.md
56
CHANGELOG.md
|
|
@ -14,18 +14,68 @@ We use [Break Versioning][breakver]. The version numbers follow a `<major>.<mino
|
|||
|
||||
## Unreleased
|
||||
|
||||
* Updated deps:
|
||||
|
||||
```clj
|
||||
[metosin/sieppari "0.0.0-alpha9"] is available but we use "0.0.0-alpha8"
|
||||
[metosin/malli "0.0.1-20200404.091302-14"] is available but we use "0.0.1-20200305.102752-13"
|
||||
[metosin/ring-swagger-ui "3.25.0"] is available but we use "3.24.3"
|
||||
[metosin/spec-tools "0.10.2"] is available but we use "0.10.0"
|
||||
[metosin/schema-tools "0.12.2"] is available but we use "0.12.1"
|
||||
[metosin/muuntaja "0.6.7"] is available but we use "0.6.6"
|
||||
[metosin/jsonista "0.2.6"] is available but we use "0.2.5"
|
||||
[com.bhauman/spell-spec "0.1.2"] is available but we use "0.1.1"
|
||||
[fipp "0.6.23"] is available but we use "0.6.22"
|
||||
[ring/ring-core "1.8.1"] is available but we use "1.8.0"
|
||||
```
|
||||
|
||||
### `reitit-core`
|
||||
|
||||
* Route conflict resolution and thus, router creation is now an order of magnitude faster.
|
||||
* Forcing router to be `reitit.core/linear-router` and disabling route conflict resolution totally bypasses route conflict resolution. For cases when router creating speed matters over routing performance:
|
||||
|
||||
```clj
|
||||
(r/router ...zillions-of-routes... {:router r/linear-router, :conflicts nil})
|
||||
```
|
||||
|
||||
### `reitit-frontend`
|
||||
|
||||
* `reitit.frontend.easy` state is setup before user `on-navigate` callback
|
||||
is called the first time, so that `rfe/push-state` and such can be called
|
||||
([#315](https://github.com/metosin/reitit/issues/315))
|
||||
|
||||
### `reitit-malli`
|
||||
### `reitit-ring`
|
||||
|
||||
* Update malli to latest version:
|
||||
* `reitit.ring/routes` strips away `nil` routes, fixes [#394](https://github.com/metosin/reitit/issues/394)
|
||||
* `reitit.ring/create-file-handler` to serve files from filesystem, fixes [#395](https://github.com/metosin/reitit/issues/395)
|
||||
* **BREAKING**: router option `:reitit.ring/default-options-handler` is deprecated
|
||||
* fails with router creation time error
|
||||
* use `:reitit.ring/default-options-endpoint` instead, takes an expandable route data instead just of a handler.
|
||||
|
||||
### `reitit-http`
|
||||
|
||||
* **BREAKING**: router option `:reitit.http/default-options-handler` is deprecated
|
||||
* fails with router creation time error
|
||||
* use `:reitit.http/default-options-endpoint` instead, takes an expandable route data instead just of a handler.
|
||||
|
||||
### `reitit-spec`
|
||||
|
||||
* lots of bug fixes, see [spec-tools changelog](https://github.com/metosin/spec-tools/blob/master/CHANGELOG.md#0102-2020-05-05)
|
||||
|
||||
### `reitit-sieppari`
|
||||
|
||||
* changes from Sieppari:
|
||||
* fixed performance regression bugs, order of magnitude faster dispatching
|
||||
* **BREAKING**: Out-of-the-box support for `core.async` and `manifold` are dropped, to use them, one needs to explicitely require the following side-effecting namespaces:
|
||||
* `sieppari.async.core-async` for core.async
|
||||
* `sieppari.async.manifold` for manifold
|
||||
|
||||
### `reitit-swagger`
|
||||
|
||||
* default to the new swagger-ui (3.25.0), to get old back add a dependency to:
|
||||
|
||||
```clj
|
||||
[metosin/malli "0.0.1-20200404.091302-14"] is available but we use "0.0.1-20200305.102752-13"
|
||||
[metosin/ring-swagger-ui "2.2.10"]
|
||||
```
|
||||
|
||||
## 0.4.2 (2020-01-17)
|
||||
|
|
|
|||
|
|
@ -14,11 +14,11 @@ Read more about the [Ring Concepts](https://github.com/ring-clojure/ring/wiki/Co
|
|||
|
||||
It accepts the following 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)
|
||||
| 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-endpoint` | Default endpoint for `:options` method (default: default-options-endpoint)
|
||||
|
||||
Example router:
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
(ns reitit.http
|
||||
(:require [meta-merge.core :refer [meta-merge]]
|
||||
[reitit.interceptor :as interceptor]
|
||||
[reitit.exception :as ex]
|
||||
[reitit.ring :as ring]
|
||||
[reitit.core :as r]))
|
||||
|
||||
|
|
@ -13,11 +14,11 @@
|
|||
(update acc method expand opts)
|
||||
acc)) data ring/http-methods)])
|
||||
|
||||
(defn compile-result [[path data] {::keys [default-options-handler] :as opts}]
|
||||
(defn compile-result [[path data] {:keys [::default-options-endpoint expand] :as opts}]
|
||||
(let [[top childs] (ring/group-keys data)
|
||||
childs (cond-> childs
|
||||
(and (not (:options childs)) (not (:handler top)) default-options-handler)
|
||||
(assoc :options {:no-doc true, :handler default-options-handler}))
|
||||
(and (not (:options childs)) (not (:handler top)) default-options-endpoint)
|
||||
(assoc :options (expand default-options-endpoint opts)))
|
||||
compile (fn [[path data] opts scope]
|
||||
(interceptor/compile-result [path data] opts scope))
|
||||
->endpoint (fn [p d m s]
|
||||
|
|
@ -47,11 +48,11 @@
|
|||
support for http-methods and Interceptors. See documentation on [[reitit.core/router]]
|
||||
for available options. In addition, the following options are available:
|
||||
|
||||
| key | description
|
||||
| ---------------------------------------|-------------
|
||||
| `:reitit.interceptor/transform` | Function or vector of functions of type `[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)
|
||||
| key | description
|
||||
| ----------------------------------------|-------------
|
||||
| `:reitit.interceptor/transform` | Function or vector of functions of type `[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-endpoint` | Default endpoint for `:options` method in endpoints (default: reitit.ring/default-options-endpoint)
|
||||
|
||||
Example:
|
||||
|
||||
|
|
@ -66,7 +67,10 @@
|
|||
([data opts]
|
||||
(let [opts (merge {:coerce coerce-handler
|
||||
:compile compile-result
|
||||
::default-options-handler ring/default-options-handler} opts)]
|
||||
::default-options-endpoint ring/default-options-endpoint} opts)]
|
||||
(when (contains? opts ::default-options-handler)
|
||||
(ex/fail! (str "Option :reitit.http/default-options-handler is deprecated."
|
||||
" Use :reitit.http/default-options-endpoint instead.")))
|
||||
(r/router data opts))))
|
||||
|
||||
(defn routing-interceptor
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
(defn- arities [f]
|
||||
(->> (class f)
|
||||
.getDeclaredMethods
|
||||
(filter #(= "invoke" (.getName %)))
|
||||
(filter (fn [^Method m] (= "invoke" (.getName m))))
|
||||
(map #(alength (.getParameterTypes ^Method %)))
|
||||
(set)))
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
(ns reitit.ring
|
||||
(:require [meta-merge.core :refer [meta-merge]]
|
||||
[reitit.middleware :as middleware]
|
||||
[reitit.exception :as ex]
|
||||
[reitit.core :as r]
|
||||
[reitit.impl :as impl]
|
||||
#?@(:clj [[ring.util.mime-type :as mime-type]
|
||||
[ring.util.response :as response]])
|
||||
[clojure.string :as str]
|
||||
[reitit.exception :as ex]))
|
||||
[clojure.string :as str]))
|
||||
|
||||
(declare get-match)
|
||||
(declare get-router)
|
||||
|
|
@ -108,7 +108,7 @@
|
|||
(defn routes
|
||||
"Create a ring handler by combining several handlers into one."
|
||||
[& handlers]
|
||||
(let [single-arity (apply some-fn handlers)]
|
||||
(let [single-arity (apply some-fn (keep identity handlers))]
|
||||
(fn
|
||||
([request]
|
||||
(single-arity request))
|
||||
|
|
@ -189,6 +189,48 @@
|
|||
;; TODO: ring.middleware.not-modified/wrap-not-modified
|
||||
;; TODO: ring.middleware.head/wrap-head
|
||||
;; TODO: handle etags
|
||||
(defn -create-file-or-resource-handler
|
||||
[response-fn {:keys [parameter root path loader allow-symlinks? index-files paths not-found-handler]
|
||||
:or {parameter (keyword "")
|
||||
root "public"
|
||||
index-files ["index.html"]
|
||||
paths (constantly nil)
|
||||
not-found-handler (constantly {:status 404, :body "", :headers {}})}}]
|
||||
(let [options {:root root
|
||||
:loader loader
|
||||
:index-files? false
|
||||
:allow-symlinks? allow-symlinks?}
|
||||
path-size (count path)
|
||||
create (fn [handler]
|
||||
(fn
|
||||
([request] (handler request))
|
||||
([request respond _] (respond (handler request)))))
|
||||
join-paths (fn [& paths]
|
||||
(str/replace (str/replace (str/join "/" paths) #"([/]+)" "/") #"/$" ""))
|
||||
response (fn [path]
|
||||
(if-let [response (or (paths (join-paths "/" path))
|
||||
(response-fn path options))]
|
||||
(response/content-type response (mime-type/ext-mime-type path))))
|
||||
path-or-index-response (fn [path uri]
|
||||
(or (response path)
|
||||
(loop [[file & files] index-files]
|
||||
(if file
|
||||
(if (response (join-paths path file))
|
||||
(response/redirect (join-paths uri file))
|
||||
(recur files))))))
|
||||
handler (if path
|
||||
(fn [request]
|
||||
(let [uri (:uri request)]
|
||||
(if-let [path (if (>= (count uri) path-size) (subs uri path-size))]
|
||||
(path-or-index-response path uri))))
|
||||
(fn [request]
|
||||
(let [uri (:uri request)
|
||||
path (-> request :path-params parameter)]
|
||||
(or (path-or-index-response path uri)
|
||||
(not-found-handler request)))))]
|
||||
(create handler))))
|
||||
|
||||
#?(:clj
|
||||
(defn create-resource-handler
|
||||
"A ring handler for serving classpath resources, configured via options:
|
||||
|
||||
|
|
@ -202,42 +244,25 @@
|
|||
| :not-found-handler | optional handler function to use if the requested resource is missing (404 Not Found)"
|
||||
([]
|
||||
(create-resource-handler nil))
|
||||
([{:keys [parameter root path loader allow-symlinks? index-files paths not-found-handler]
|
||||
:or {parameter (keyword "")
|
||||
root "public"
|
||||
index-files ["index.html"]
|
||||
paths (constantly nil)
|
||||
not-found-handler (constantly {:status 404, :body "", :headers {}})}}]
|
||||
(let [options {:root root, :loader loader, :allow-symlinks? allow-symlinks?}
|
||||
path-size (count path)
|
||||
create (fn [handler]
|
||||
(fn
|
||||
([request] (handler request))
|
||||
([request respond _] (respond (handler request)))))
|
||||
join-paths (fn [& paths]
|
||||
(str/replace (str/replace (str/join "/" paths) #"([/]+)" "/") #"/$" ""))
|
||||
resource-response (fn [path]
|
||||
(if-let [response (or (paths (join-paths "/" path))
|
||||
(response/resource-response path options))]
|
||||
(response/content-type response (mime-type/ext-mime-type path))))
|
||||
path-or-index-response (fn [path uri]
|
||||
(or (resource-response path)
|
||||
(loop [[file & files] index-files]
|
||||
(if file
|
||||
(if (resource-response (join-paths path file))
|
||||
(response/redirect (join-paths uri file))
|
||||
(recur files))))))
|
||||
handler (if path
|
||||
(fn [request]
|
||||
(let [uri (:uri request)]
|
||||
(if-let [path (if (>= (count uri) path-size) (subs uri path-size))]
|
||||
(path-or-index-response path uri))))
|
||||
(fn [request]
|
||||
(let [uri (:uri request)
|
||||
path (-> request :path-params parameter)]
|
||||
(or (path-or-index-response path uri)
|
||||
(not-found-handler request)))))]
|
||||
(create handler)))))
|
||||
([opts]
|
||||
(-create-file-or-resource-handler response/resource-response opts))))
|
||||
|
||||
#?(:clj
|
||||
(defn create-file-handler
|
||||
"A ring handler for serving file resources, configured via options:
|
||||
|
||||
| key | description |
|
||||
| -------------------|-------------|
|
||||
| :parameter | optional name of the wildcard parameter, defaults to unnamed keyword `:`
|
||||
| :root | optional resource root, defaults to `\"public\"`
|
||||
| :path | optional path to mount the handler to. Works only if mounted outside of a router.
|
||||
| :loader | optional class loader to resolve the resources
|
||||
| :index-files | optional vector of index-files to look in a resource directory, defaults to `[\"index.html\"]`
|
||||
| :not-found-handler | optional handler function to use if the requested resource is missing (404 Not Found)"
|
||||
([]
|
||||
(create-file-handler nil))
|
||||
([opts]
|
||||
(-create-file-or-resource-handler response/file-response opts))))
|
||||
|
||||
(defn create-enrich-request [inject-match? inject-router?]
|
||||
(cond
|
||||
|
|
|
|||
64
project.clj
64
project.clj
|
|
@ -27,33 +27,33 @@
|
|||
[metosin/reitit-frontend "0.4.2"]
|
||||
[metosin/reitit-sieppari "0.4.2"]
|
||||
[metosin/reitit-pedestal "0.4.2"]
|
||||
[metosin/ring-swagger-ui "3.24.3"]
|
||||
[metosin/spec-tools "0.10.0"]
|
||||
[metosin/schema-tools "0.12.1"]
|
||||
[metosin/muuntaja "0.6.6"]
|
||||
[metosin/jsonista "0.2.5"]
|
||||
[metosin/sieppari "0.0.0-alpha8"]
|
||||
[metosin/ring-swagger-ui "3.25.0"]
|
||||
[metosin/spec-tools "0.10.2"]
|
||||
[metosin/schema-tools "0.12.2"]
|
||||
[metosin/muuntaja "0.6.7"]
|
||||
[metosin/jsonista "0.2.6"]
|
||||
[metosin/sieppari "0.0.0-alpha9"]
|
||||
[metosin/malli "0.0.1-20200404.091302-14"]
|
||||
|
||||
;; https://clojureverse.org/t/depending-on-the-right-versions-of-jackson-libraries/5111
|
||||
[com.fasterxml.jackson.core/jackson-core "2.10.0"]
|
||||
[com.fasterxml.jackson.core/jackson-core "2.11.0"]
|
||||
|
||||
[meta-merge "1.0.0"]
|
||||
[fipp "0.6.22" :exclusions [org.clojure/core.rrb-vector]]
|
||||
[fipp "0.6.23" :exclusions [org.clojure/core.rrb-vector]]
|
||||
[expound "0.8.4"]
|
||||
[lambdaisland/deep-diff "0.0-47"]
|
||||
[com.bhauman/spell-spec "0.1.1"]
|
||||
[ring/ring-core "1.8.0"]
|
||||
[com.bhauman/spell-spec "0.1.2"]
|
||||
[ring/ring-core "1.8.1"]
|
||||
|
||||
[io.pedestal/pedestal.service "0.5.7"]]
|
||||
|
||||
:plugins [[jonase/eastwood "0.3.6"]
|
||||
:plugins [[jonase/eastwood "0.3.11"]
|
||||
;[lein-virgil "0.1.7"]
|
||||
[lein-doo "0.1.11"]
|
||||
[lein-cljsbuild "1.1.7"]
|
||||
[lein-cljsbuild "1.1.8"]
|
||||
[lein-cloverage "1.1.2"]
|
||||
[lein-codox "0.10.7"]
|
||||
[metosin/bat-test "0.4.3"]]
|
||||
[metosin/bat-test "0.4.4"]]
|
||||
|
||||
:profiles {:dev {:jvm-opts ^:replace ["-server"]
|
||||
|
||||
|
|
@ -80,37 +80,37 @@
|
|||
[org.clojure/clojurescript "1.10.597"]
|
||||
|
||||
;; modules dependencies
|
||||
[metosin/schema-tools]
|
||||
[metosin/spec-tools]
|
||||
[metosin/muuntaja]
|
||||
[metosin/schema-tools "0.12.2"]
|
||||
[metosin/spec-tools "0.10.2"]
|
||||
[metosin/muuntaja "0.6.7"]
|
||||
[metosin/sieppari]
|
||||
[metosin/jsonista]
|
||||
[metosin/jsonista "0.2.6"]
|
||||
[metosin/malli]
|
||||
[lambdaisland/deep-diff]
|
||||
[meta-merge]
|
||||
[com.bhauman/spell-spec]
|
||||
[expound]
|
||||
[fipp]
|
||||
[lambdaisland/deep-diff "0.0-47"]
|
||||
[meta-merge "1.0.0"]
|
||||
[com.bhauman/spell-spec "0.1.1"]
|
||||
[expound "0.8.4"]
|
||||
[fipp "0.6.23"]
|
||||
|
||||
[orchestra "2019.02.06-1"]
|
||||
|
||||
[ring "1.8.0"]
|
||||
[ring "1.8.1"]
|
||||
[ikitommi/immutant-web "3.0.0-alpha1"]
|
||||
[metosin/ring-http-response "0.9.1"]
|
||||
[metosin/ring-swagger-ui "2.2.10"]
|
||||
[metosin/ring-swagger-ui "3.25.0"]
|
||||
|
||||
[criterium "0.4.5"]
|
||||
[org.clojure/test.check "0.10.0"]
|
||||
[org.clojure/tools.namespace "0.3.1"]
|
||||
[org.clojure/test.check "1.0.0"]
|
||||
[org.clojure/tools.namespace "1.0.0"]
|
||||
[com.gfredericks/test.chuck "0.2.10"]
|
||||
|
||||
[io.pedestal/pedestal.service "0.5.7"]
|
||||
|
||||
[org.clojure/core.async "0.6.532"]
|
||||
[org.clojure/core.async "1.1.587"]
|
||||
[manifold "0.1.8"]
|
||||
[funcool/promesa "4.0.2"]
|
||||
[funcool/promesa "5.1.0"]
|
||||
|
||||
[com.clojure-goes-fast/clj-async-profiler "0.4.0"]
|
||||
[com.clojure-goes-fast/clj-async-profiler "0.4.1"]
|
||||
[ring-cors "0.1.13"]
|
||||
|
||||
[com.bhauman/rebel-readline "0.1.4"]]}
|
||||
|
|
@ -125,16 +125,16 @@
|
|||
[io.pedestal/pedestal.service "0.5.7"]
|
||||
[io.pedestal/pedestal.jetty "0.5.7"]
|
||||
[calfpath "0.7.2"]
|
||||
[org.clojure/core.async "0.6.532"]
|
||||
[org.clojure/core.async "1.1.587"]
|
||||
[manifold "0.1.8"]
|
||||
[funcool/promesa "4.0.2"]
|
||||
[funcool/promesa "5.1.0"]
|
||||
[metosin/sieppari]
|
||||
[yada "1.2.16"]
|
||||
[aleph "0.4.6"]
|
||||
[ring/ring-defaults "0.3.2"]
|
||||
[ataraxy "0.4.2"]
|
||||
[bidi "2.1.6"]
|
||||
[janus "1.3.0"]]}
|
||||
[janus "1.3.2"]]}
|
||||
:analyze {:jvm-opts ^:replace ["-server"
|
||||
"-Dclojure.compiler.direct-linking=true"
|
||||
"-XX:+PrintCompilation"
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@
|
|||
[reitit.interceptor.sieppari :as sieppari]
|
||||
[reitit.http :as http]
|
||||
[reitit.ring :as ring]
|
||||
[reitit.core :as r]))
|
||||
[reitit.core :as r])
|
||||
(:import (clojure.lang ExceptionInfo)))
|
||||
|
||||
(defn interceptor [name]
|
||||
{:enter (fn [ctx] (update-in ctx [:request ::i] (fnil conj []) name))})
|
||||
|
|
@ -169,6 +170,10 @@
|
|||
(testing "handler rejects"
|
||||
(is (= -406 (:status (app {:request-method :get, :uri "/pong"}))))))))))
|
||||
|
||||
(deftest default-options-handler-test
|
||||
(testing "Assertion fails when using deprecated options-handler"
|
||||
(is (thrown? ExceptionInfo (ring/router [] {::ring/default-options-handler (fn [_])})))))
|
||||
|
||||
(deftest default-options-handler-test
|
||||
(let [response {:status 200, :body "ok"}]
|
||||
|
||||
|
|
@ -199,7 +204,7 @@
|
|||
[["/get" {:get (constantly response)}]
|
||||
["/options" {:options (constantly response)}]
|
||||
["/any" (constantly response)]]
|
||||
{::http/default-options-handler nil})
|
||||
{::http/default-options-endpoint nil})
|
||||
{:executor sieppari/executor})]
|
||||
|
||||
(testing "endpoint with a non-options handler"
|
||||
|
|
|
|||
|
|
@ -24,6 +24,15 @@
|
|||
([request respond _]
|
||||
(respond (handler request))))
|
||||
|
||||
(deftest routes-test
|
||||
(testing "nils are removed"
|
||||
(is (= 123
|
||||
((ring/routes
|
||||
(constantly nil)
|
||||
nil
|
||||
(constantly 123))
|
||||
::irrelevant)))))
|
||||
|
||||
(deftest ring-router-test
|
||||
|
||||
(testing "all paths should have a handler"
|
||||
|
|
@ -161,8 +170,8 @@
|
|||
(deftest default-handler-test
|
||||
(let [response {:status 200, :body "ok"}
|
||||
router (ring/router
|
||||
[["/ping" {:get (constantly response)}]
|
||||
["/pong" (constantly nil)]])
|
||||
[["/ping" {:get (constantly response)}]
|
||||
["/pong" (constantly nil)]])
|
||||
app (ring/ring-handler router)]
|
||||
|
||||
(testing "match"
|
||||
|
|
@ -188,9 +197,9 @@
|
|||
|
||||
(testing "with custom http responses"
|
||||
(let [app (ring/ring-handler router (ring/create-default-handler
|
||||
{:not-found (constantly {:status -404})
|
||||
:method-not-allowed (constantly {:status -405})
|
||||
:not-acceptable (constantly {:status -406})}))]
|
||||
{:not-found (constantly {:status -404})
|
||||
:method-not-allowed (constantly {:status -405})
|
||||
:not-acceptable (constantly {:status -406})}))]
|
||||
(testing "route doesn't match"
|
||||
(is (= -404 (:status (app {:request-method :get, :uri "/"})))))
|
||||
(testing "method doesn't match"
|
||||
|
|
@ -200,7 +209,7 @@
|
|||
|
||||
(testing "with some custom http responses"
|
||||
(let [app (ring/ring-handler router (ring/create-default-handler
|
||||
{:not-found (constantly {:status -404})}))]
|
||||
{:not-found (constantly {:status -404})}))]
|
||||
(testing "route doesn't match"
|
||||
(is (= 405 (:status (app {:request-method :post, :uri "/ping"}))))))))))
|
||||
|
||||
|
|
@ -445,158 +454,163 @@
|
|||
(app request)))))))
|
||||
|
||||
#?(:clj
|
||||
(deftest resource-handler-test
|
||||
(deftest file-resource-handler-test
|
||||
(let [redirect (fn [uri] {:status 302, :body "", :headers {"Location" uri}})
|
||||
request (fn [uri] {:uri uri, :request-method :get})]
|
||||
(testing "inside a router"
|
||||
|
||||
(testing "from root"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
["/*" (ring/create-resource-handler)])
|
||||
(ring/create-default-handler))]
|
||||
(testing test
|
||||
(testing "different file-types"
|
||||
(let [response (app (request "/hello.json"))]
|
||||
(is (= "application/json" (get-in response [:headers "Content-Type"])))
|
||||
(is (get-in response [:headers "Last-Modified"]))
|
||||
(is (= "{\"hello\": \"file\"}" (slurp (:body response)))))
|
||||
(let [response (app (request "/hello.xml"))]
|
||||
(is (= "text/xml" (get-in response [:headers "Content-Type"])))
|
||||
(is (get-in response [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body response))))))
|
||||
(doseq [[name create] [["resource-handler" ring/create-resource-handler]
|
||||
["file-handler" #(ring/create-file-handler (assoc % :root "dev-resources/public"))]]]
|
||||
|
||||
(testing "index-files"
|
||||
(let [response (app (request "/docs"))]
|
||||
(is (= (redirect "/docs/index.html") response)))
|
||||
(let [response (app (request "/docs/"))]
|
||||
(is (= (redirect "/docs/index.html") response))))
|
||||
(testing (str "for " name)
|
||||
(testing "inside a router"
|
||||
|
||||
(testing "not found"
|
||||
(let [response (app (request "/not-found"))]
|
||||
(is (= 404 (:status response)))))
|
||||
(testing "from root"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
["/*" (create nil)])
|
||||
(ring/create-default-handler))]
|
||||
(testing test
|
||||
(testing "different file-types"
|
||||
(let [response (app (request "/hello.json"))]
|
||||
(is (= "application/json" (get-in response [:headers "Content-Type"])))
|
||||
(is (get-in response [:headers "Last-Modified"]))
|
||||
(is (= "{\"hello\": \"file\"}" (slurp (:body response)))))
|
||||
(let [response (app (request "/hello.xml"))]
|
||||
(is (= "text/xml" (get-in response [:headers "Content-Type"])))
|
||||
(is (get-in response [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body response))))))
|
||||
|
||||
(testing "3-arity"
|
||||
(let [result (atom nil)
|
||||
respond (partial reset! result)
|
||||
raise ::not-called]
|
||||
(app (request "/hello.xml") respond raise)
|
||||
(is (= "text/xml" (get-in @result [:headers "Content-Type"])))
|
||||
(is (get-in @result [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body @result)))))))))
|
||||
(testing "index-files"
|
||||
(let [response (app (request "/docs"))]
|
||||
(is (= (redirect "/docs/index.html") response)))
|
||||
(let [response (app (request "/docs/"))]
|
||||
(is (= (redirect "/docs/index.html") response))))
|
||||
|
||||
(testing "from path"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
["/files/*" (ring/create-resource-handler)])
|
||||
(ring/create-default-handler))
|
||||
request #(request (str "/files" %))
|
||||
redirect #(redirect (str "/files" %))]
|
||||
(testing test
|
||||
(testing "different file-types"
|
||||
(let [response (app (request "/hello.json"))]
|
||||
(is (= "application/json" (get-in response [:headers "Content-Type"])))
|
||||
(is (get-in response [:headers "Last-Modified"]))
|
||||
(is (= "{\"hello\": \"file\"}" (slurp (:body response)))))
|
||||
(let [response (app (request "/hello.xml"))]
|
||||
(is (= "text/xml" (get-in response [:headers "Content-Type"])))
|
||||
(is (get-in response [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body response))))))
|
||||
(testing "not found"
|
||||
(let [response (app (request "/not-found"))]
|
||||
(is (= 404 (:status response)))))
|
||||
|
||||
(testing "index-files"
|
||||
(let [response (app (request "/docs"))]
|
||||
(is (= (redirect "/docs/index.html") response)))
|
||||
(let [response (app (request "/docs/"))]
|
||||
(is (= (redirect "/docs/index.html") response))))
|
||||
(testing "3-arity"
|
||||
(let [result (atom nil)
|
||||
respond (partial reset! result)
|
||||
raise ::not-called]
|
||||
(app (request "/hello.xml") respond raise)
|
||||
(is (= "text/xml" (get-in @result [:headers "Content-Type"])))
|
||||
(is (get-in @result [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body @result)))))))))
|
||||
|
||||
(testing "not found"
|
||||
(let [response (app (request "/not-found"))]
|
||||
(is (= 404 (:status response)))))
|
||||
(testing "from path"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router
|
||||
["/files/*" (create nil)])
|
||||
(ring/create-default-handler))
|
||||
request #(request (str "/files" %))
|
||||
redirect #(redirect (str "/files" %))]
|
||||
(testing test
|
||||
(testing "different file-types"
|
||||
(let [response (app (request "/hello.json"))]
|
||||
(is (= "application/json" (get-in response [:headers "Content-Type"])))
|
||||
(is (get-in response [:headers "Last-Modified"]))
|
||||
(is (= "{\"hello\": \"file\"}" (slurp (:body response)))))
|
||||
(let [response (app (request "/hello.xml"))]
|
||||
(is (= "text/xml" (get-in response [:headers "Content-Type"])))
|
||||
(is (get-in response [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body response))))))
|
||||
|
||||
(testing "3-arity"
|
||||
(let [result (atom nil)
|
||||
respond (partial reset! result)
|
||||
raise ::not-called]
|
||||
(app (request "/hello.xml") respond raise)
|
||||
(is (= "text/xml" (get-in @result [:headers "Content-Type"])))
|
||||
(is (get-in @result [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body @result))))))))))
|
||||
(testing "index-files"
|
||||
(let [response (app (request "/docs"))]
|
||||
(is (= (redirect "/docs/index.html") response)))
|
||||
(let [response (app (request "/docs/"))]
|
||||
(is (= (redirect "/docs/index.html") response))))
|
||||
|
||||
(testing "outside a router"
|
||||
(testing "not found"
|
||||
(let [response (app (request "/not-found"))]
|
||||
(is (= 404 (:status response)))))
|
||||
|
||||
(testing "from root"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router [])
|
||||
(ring/routes
|
||||
(ring/create-resource-handler {:path "/"})
|
||||
(ring/create-default-handler)))]
|
||||
(testing test
|
||||
(testing "different file-types"
|
||||
(let [response (app (request "/hello.json"))]
|
||||
(is (= "application/json" (get-in response [:headers "Content-Type"])))
|
||||
(is (get-in response [:headers "Last-Modified"]))
|
||||
(is (= "{\"hello\": \"file\"}" (slurp (:body response)))))
|
||||
(let [response (app (request "/hello.xml"))]
|
||||
(is (= "text/xml" (get-in response [:headers "Content-Type"])))
|
||||
(is (get-in response [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body response))))))
|
||||
(testing "3-arity"
|
||||
(let [result (atom nil)
|
||||
respond (partial reset! result)
|
||||
raise ::not-called]
|
||||
(app (request "/hello.xml") respond raise)
|
||||
(is (= "text/xml" (get-in @result [:headers "Content-Type"])))
|
||||
(is (get-in @result [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body @result))))))))))
|
||||
|
||||
(testing "index-files"
|
||||
(let [response (app (request "/docs"))]
|
||||
(is (= (redirect "/docs/index.html") response)))
|
||||
(let [response (app (request "/docs/"))]
|
||||
(is (= (redirect "/docs/index.html") response))))
|
||||
(testing "outside a router"
|
||||
|
||||
(testing "not found"
|
||||
(let [response (app (request "/not-found"))]
|
||||
(is (= 404 (:status response)))))
|
||||
(testing "from root"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router [])
|
||||
(ring/routes
|
||||
(create {:path "/"})
|
||||
(ring/create-default-handler)))]
|
||||
(testing test
|
||||
(testing "different file-types"
|
||||
(let [response (app (request "/hello.json"))]
|
||||
(is (= "application/json" (get-in response [:headers "Content-Type"])))
|
||||
(is (get-in response [:headers "Last-Modified"]))
|
||||
(is (= "{\"hello\": \"file\"}" (slurp (:body response)))))
|
||||
(let [response (app (request "/hello.xml"))]
|
||||
(is (= "text/xml" (get-in response [:headers "Content-Type"])))
|
||||
(is (get-in response [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body response))))))
|
||||
|
||||
(testing "3-arity"
|
||||
(let [result (atom nil)
|
||||
respond (partial reset! result)
|
||||
raise ::not-called]
|
||||
(app (request "/hello.xml") respond raise)
|
||||
(is (= "text/xml" (get-in @result [:headers "Content-Type"])))
|
||||
(is (get-in @result [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body @result)))))))))
|
||||
(testing "index-files"
|
||||
(let [response (app (request "/docs"))]
|
||||
(is (= (redirect "/docs/index.html") response)))
|
||||
(let [response (app (request "/docs/"))]
|
||||
(is (= (redirect "/docs/index.html") response))))
|
||||
|
||||
(testing "from path"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router [])
|
||||
(ring/routes
|
||||
(ring/create-resource-handler {:path "/files"})
|
||||
(ring/create-default-handler)))
|
||||
request #(request (str "/files" %))
|
||||
redirect #(redirect (str "/files" %))]
|
||||
(testing test
|
||||
(testing "different file-types"
|
||||
(let [response (app (request "/hello.json"))]
|
||||
(is (= "application/json" (get-in response [:headers "Content-Type"])))
|
||||
(is (get-in response [:headers "Last-Modified"]))
|
||||
(is (= "{\"hello\": \"file\"}" (slurp (:body response)))))
|
||||
(let [response (app (request "/hello.xml"))]
|
||||
(is (= "text/xml" (get-in response [:headers "Content-Type"])))
|
||||
(is (get-in response [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body response))))))
|
||||
(testing "not found"
|
||||
(let [response (app (request "/not-found"))]
|
||||
(is (= 404 (:status response)))))
|
||||
|
||||
(testing "index-files"
|
||||
(let [response (app (request "/docs"))]
|
||||
(is (= (redirect "/docs/index.html") response)))
|
||||
(let [response (app (request "/docs/"))]
|
||||
(is (= (redirect "/docs/index.html") response))))
|
||||
(testing "3-arity"
|
||||
(let [result (atom nil)
|
||||
respond (partial reset! result)
|
||||
raise ::not-called]
|
||||
(app (request "/hello.xml") respond raise)
|
||||
(is (= "text/xml" (get-in @result [:headers "Content-Type"])))
|
||||
(is (get-in @result [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body @result)))))))))
|
||||
|
||||
(testing "not found"
|
||||
(let [response (app (request "/not-found"))]
|
||||
(is (= 404 (:status response)))))
|
||||
(testing "from path"
|
||||
(let [app (ring/ring-handler
|
||||
(ring/router [])
|
||||
(ring/routes
|
||||
(create {:path "/files"})
|
||||
(ring/create-default-handler)))
|
||||
request #(request (str "/files" %))
|
||||
redirect #(redirect (str "/files" %))]
|
||||
(testing test
|
||||
(testing "different file-types"
|
||||
(let [response (app (request "/hello.json"))]
|
||||
(is (= "application/json" (get-in response [:headers "Content-Type"])))
|
||||
(is (get-in response [:headers "Last-Modified"]))
|
||||
(is (= "{\"hello\": \"file\"}" (slurp (:body response)))))
|
||||
(let [response (app (request "/hello.xml"))]
|
||||
(is (= "text/xml" (get-in response [:headers "Content-Type"])))
|
||||
(is (get-in response [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body response))))))
|
||||
|
||||
(testing "3-arity"
|
||||
(let [result (atom nil)
|
||||
respond (partial reset! result)
|
||||
raise ::not-called]
|
||||
(app (request "/hello.xml") respond raise)
|
||||
(is (= "text/xml" (get-in @result [:headers "Content-Type"])))
|
||||
(is (get-in @result [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body @result)))))))))))))
|
||||
(testing "index-files"
|
||||
(let [response (app (request "/docs"))]
|
||||
(is (= (redirect "/docs/index.html") response)))
|
||||
(let [response (app (request "/docs/"))]
|
||||
(is (= (redirect "/docs/index.html") response))))
|
||||
|
||||
(testing "not found"
|
||||
(let [response (app (request "/not-found"))]
|
||||
(is (= 404 (:status response)))))
|
||||
|
||||
(testing "3-arity"
|
||||
(let [result (atom nil)
|
||||
respond (partial reset! result)
|
||||
raise ::not-called]
|
||||
(app (request "/hello.xml") respond raise)
|
||||
(is (= "text/xml" (get-in @result [:headers "Content-Type"])))
|
||||
(is (get-in @result [:headers "Last-Modified"]))
|
||||
(is (= "<xml><hello>file</hello></xml>\n" (slurp (:body @result)))))))))))))))
|
||||
|
||||
(deftest router-available-in-default-branch
|
||||
(testing "1-arity"
|
||||
|
|
|
|||
Loading…
Reference in a new issue