Merge pull request #105 from metosin/SmallFixes

Small fixes
This commit is contained in:
Tommi Reiman 2018-06-25 10:35:05 +03:00 committed by GitHub
commit e952afa8fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 142 additions and 66 deletions

View file

@ -1,8 +1,9 @@
## UNRELEASED
## 0.1.3-SNAPSHOT
## `reitit-core`
* `reitit.coercion/coerce!` coerced all parameters found in match, e.g. injecting in `:query-parameters` into `Match` with coerce those too if `:query` coercion is defined.
* if response coercion is not defined for a response status, response is still returned
* `spec-tools.data-spec/maybe` can be used in spec-coercion.
```clj
@ -37,6 +38,20 @@
; "/olipa/kerran?iso=p%C3%B6ril%C3%A4inen"
```
### `reitit-spec`
* `[metosin/spec-tools "0.7.1"]` with swagger generation enhancements, see the [CHANGELOG](https://github.com/metosin/spec-tools/blob/master/CHANGELOG.md)
* if response coercion is not defined for a response status, no `:schema` is not emitted.
* updated dependencies:
```clj
[metosin/spec-tools "0.7.1"] is available but we use "0.7.0"
```
### `reitit-schema`
* if response coercion is not defined for a response status, no `:schema` is not emitted.
## 0.1.2 (2018-6-6)
### `reitit-core`

View file

@ -81,3 +81,21 @@ There is also a exception throwing version:
(r/match-by-name! router ::user)
; ExceptionInfo missing path-params for route /api/user/:id: #{:id}
```
To turn a Match into a path, there is `reitit.core/match->path`:
```clj
(-> router
(r/match-by-name ::user {:id 1})
(r/match->path))
; "/api/user/1"
```
It can take an optional map of query-parameters too:
```clj
(-> router
(r/match-by-name ::user {:id 1})
(r/match->path {:iso "möly"}))
; "/api/user/1?iso=m%C3%B6ly"
```

View file

@ -79,4 +79,4 @@ With custom responses:
(app {:request-method :get, :uri "/pong"})
; {:status 406, :body "kosh"}
```
```

View file

@ -1,8 +1,8 @@
# Reverse routing with Ring
Both the `router` and the `match` are injected into Ring Request (as `::r/router` and `::r/match`) by the `reitit.ring/ring-handler` and with that, available to middleware and endpoints.
Both the `router` and the `match` are injected into Ring Request (as `::r/router` and `::r/match`) by the `reitit.ring/ring-handler` and with that, available to middleware and endpoints. To convert a `Match` into a path, one can use `r/match->path`, which optionally takes a map of query-parameters too.
Below is an example how to use the `router` to do reverse routing from a ring handler:
Below is an example how to do reverse routing from a ring handler:
```clj
(require '[reitit.core :as r])
@ -11,23 +11,28 @@ Below is an example how to use the `router` to do reverse routing from a ring ha
(def app
(ring/ring-handler
(ring/router
[["/users" {:get (fn [{:keys [::r/router]}]
{:status 200
:body (for [i (range 10)]
{:uri (:path (r/match-by-name router ::user {:id i}))})})}]
["/users/:id" {:name ::user
:get (constantly {:status 200, :body "user..."})}]])))
[["/users"
{:get (fn [{:keys [::r/router]}]
{:status 200
:body (for [i (range 10)]
{:uri (-> router
(r/match-by-name ::user {:id i})
;; with extra query-params
(r/match->path {:iso "möly"}))})})}]
["/users/:id"
{:name ::user
:get (constantly {:status 200, :body "user..."})}]])))
(app {:request-method :get, :uri "/users"})
;{:status 200,
; :body [{:uri "/users/0"}
; {:uri "/users/1"}
; {:uri "/users/2"}
; {:uri "/users/3"}
; {:uri "/users/4"}
; {:uri "/users/5"}
; {:uri "/users/6"}
; {:uri "/users/7"}
; {:uri "/users/8"}
; {:uri "/users/9"}]}
; {:status 200,
; :body ({:uri "/users/0?iso=m%C3%B6ly"}
; {:uri "/users/1?iso=m%C3%B6ly"}
; {:uri "/users/2?iso=m%C3%B6ly"}
; {:uri "/users/3?iso=m%C3%B6ly"}
; {:uri "/users/4?iso=m%C3%B6ly"}
; {:uri "/users/5?iso=m%C3%B6ly"}
; {:uri "/users/6?iso=m%C3%B6ly"}
; {:uri "/users/7?iso=m%C3%B6ly"}
; {:uri "/users/8?iso=m%C3%B6ly"}
; {:uri "/users/9?iso=m%C3%B6ly"})}
```

View file

@ -3,4 +3,4 @@
:dependencies [[org.clojure/clojure "1.9.0"]
[ring "1.6.3"]
[metosin/muuntaja "0.4.1"]
[metosin/reitit "0.1.2"]])
[metosin/reitit "0.1.3-SNAPSHOT"]])

View file

@ -3,4 +3,4 @@
:dependencies [[org.clojure/clojure "1.9.0"]
[ring "1.6.3"]
[metosin/muuntaja "0.4.1"]
[metosin/reitit "0.1.2"]])
[metosin/reitit "0.1.3-SNAPSHOT"]])

View file

@ -3,5 +3,5 @@
:dependencies [[org.clojure/clojure "1.9.0"]
[ring "1.6.3"]
[metosin/muuntaja "0.5.0"]
[metosin/reitit "0.1.2"]]
[metosin/reitit "0.1.3-SNAPSHOT"]]
:repl-options {:init-ns example.server})

View file

@ -1,4 +1,4 @@
(defproject metosin/reitit-core "0.1.2"
(defproject metosin/reitit-core "0.1.3-SNAPSHOT"
:description "Snappy data-driven router for Clojure(Script)"
:url "https://github.com/metosin/reitit"
:license {:name "Eclipse Public License"

View file

@ -116,7 +116,8 @@
(defn coerce-response [coercers request response]
(if response
(if-let [coercer (or (coercers (:status response)) (coercers :default))]
(impl/fast-assoc response :body (coercer request response)))))
(impl/fast-assoc response :body (coercer request response))
response)))
(defn request-coercers [coercion parameters opts]
(->> (for [[k v] parameters

View file

@ -1,4 +1,4 @@
(defproject metosin/reitit-ring "0.1.2"
(defproject metosin/reitit-ring "0.1.3-SNAPSHOT"
:description "Reitit: Ring routing"
:url "https://github.com/metosin/reitit"
:license {:name "Eclipse Public License"

View file

@ -1,4 +1,4 @@
(defproject metosin/reitit-schema "0.1.2"
(defproject metosin/reitit-schema "0.1.3-SNAPSHOT"
:description "Reitit: Plumatic Schema coercion"
:url "https://github.com/metosin/reitit"
:license {:name "Eclipse Public License"

View file

@ -61,9 +61,12 @@
{::swagger/responses
(into
(empty responses)
(for [[k response] responses
:let [response (set/rename-keys response {:body :schema})]]
[k (update response :schema #(coercion/-compile-model this % nil))]))})))
(for [[k response] responses]
[k (as-> response $
(set/rename-keys $ {:body :schema})
(if (:schema $)
(update $ :schema #(coercion/-compile-model this % nil))
$))]))})))
(throw
(ex-info
(str "Can't produce Schema apidocs for " spesification)

View file

@ -1,4 +1,4 @@
(defproject metosin/reitit-spec "0.1.2"
(defproject metosin/reitit-spec "0.1.3-SNAPSHOT"
:description "Reitit: clojure.spec coercion"
:url "https://github.com/metosin/reitit"
:license {:name "Eclipse Public License"

View file

@ -29,7 +29,11 @@
:default-encoder stt/any->any}))
(def no-op-transformer
st/no-op-transformer)
(reify
st/Transformer
(-name [_] ::no-op)
(-encoder [_ _ _])
(-decoder [_ _ _])))
(defprotocol IntoSpec
(into-spec [this name]))
@ -59,7 +63,10 @@
#?(:clj Object
:cljs default)
(into-spec [this _]
(st/create-spec {:spec this})))
(st/create-spec {:spec this}))
nil
(into-spec [this _]))
(defn stringify-pred [pred]
(str (if (seq? pred) (seq pred) pred)))
@ -93,9 +100,12 @@
{::swagger/responses
(into
(empty responses)
(for [[k response] responses
:let [response (set/rename-keys response {:body :schema})]]
[k (update response :schema #(coercion/-compile-model this % nil))]))})))
(for [[k response] responses]
[k (as-> response $
(set/rename-keys $ {:body :schema})
(if (:schema $)
(update $ :schema #(coercion/-compile-model this % nil))
$))]))})))
(throw
(ex-info
(str "Can't produce Spec apidocs for " spesification)

View file

@ -1,4 +1,4 @@
(defproject metosin/reitit-swagger-ui "0.1.2"
(defproject metosin/reitit-swagger-ui "0.1.3-SNAPSHOT"
:description "Reitit: Swagger-ui support"
:url "https://github.com/metosin/reitit"
:license {:name "Eclipse Public License"

View file

@ -1,4 +1,4 @@
(defproject metosin/reitit-swagger "0.1.2"
(defproject metosin/reitit-swagger "0.1.3-SNAPSHOT"
:description "Reitit: Swagger-support"
:url "https://github.com/metosin/reitit"
:license {:name "Eclipse Public License"

View file

@ -1,4 +1,4 @@
(defproject metosin/reitit "0.1.2"
(defproject metosin/reitit "0.1.3-SNAPSHOT"
:description "Snappy data-driven router for Clojure(Script)"
:url "https://github.com/metosin/reitit"
:license {:name "Eclipse Public License"

View file

@ -1,4 +1,4 @@
(defproject metosin/reitit-parent "0.1.2"
(defproject metosin/reitit-parent "0.1.3-SNAPSHOT"
:description "Snappy data-driven router for Clojure(Script)"
:url "https://github.com/metosin/reitit"
:license {:name "Eclipse Public License"
@ -9,17 +9,17 @@
:source-uri "https://github.com/metosin/reitit/{version}/{filepath}#L{line}"
:metadata {:doc/format :markdown}}
:managed-dependencies [[metosin/reitit "0.1.2"]
[metosin/reitit-core "0.1.2"]
[metosin/reitit-ring "0.1.2"]
[metosin/reitit-spec "0.1.2"]
[metosin/reitit-schema "0.1.2"]
[metosin/reitit-swagger "0.1.2"]
[metosin/reitit-swagger-ui "0.1.2"]
:managed-dependencies [[metosin/reitit "0.1.3-SNAPSHOT"]
[metosin/reitit-core "0.1.3-SNAPSHOT"]
[metosin/reitit-ring "0.1.3-SNAPSHOT"]
[metosin/reitit-spec "0.1.3-SNAPSHOT"]
[metosin/reitit-schema "0.1.3-SNAPSHOT"]
[metosin/reitit-swagger "0.1.3-SNAPSHOT"]
[metosin/reitit-swagger-ui "0.1.3-SNAPSHOT"]
[meta-merge "1.0.0"]
[ring/ring-core "1.6.3"]
[metosin/spec-tools "0.7.0"]
[metosin/spec-tools "0.7.1-SNAPSHOT"]
[metosin/schema-tools "0.10.3"]
[metosin/ring-swagger-ui "2.2.10"]
[metosin/jsonista "0.2.1"]]

View file

@ -5,9 +5,8 @@
[reitit.ring.coercion :as rrc]
[reitit.coercion.spec :as spec]
[reitit.coercion.schema :as schema]
#?@(:clj [
[muuntaja.middleware]
[jsonista.core :as j]]))
#?@(:clj [[muuntaja.middleware]
[jsonista.core :as j]]))
#?(:clj
(:import (clojure.lang ExceptionInfo)
(java.io ByteArrayInputStream))))
@ -17,8 +16,11 @@
{:keys [c]} :form
{:keys [d]} :header
{:keys [e]} :path} :parameters}]
{:status 200
:body {:total (+ a b c d e)}})
(if (= 666 a)
{:status 500
:body {:evil true}}
{:status 200
:body {:total (+ a b c d e)}}))
(def valid-request
{:uri "/api/plus/5"
@ -51,19 +53,23 @@
:form {:c int?}
:header {:d int?}
:path {:e int?}}
:responses {200 {:body {:total pos-int?}}}
:responses {200 {:body {:total pos-int?}}
500 {:description "fail"}}
:handler handler}}]]
{:data {:middleware middleware
:coercion spec/coercion}})))]
(testing "withut exception handling"
(testing "without exception handling"
(let [app (create [rrc/coerce-request-middleware
rrc/coerce-response-middleware])]
(testing "all good"
(is (= {:status 200
:body {:total 15}}
(app valid-request))))
(app valid-request)))
(is (= {:status 500
:body {:evil true}}
(app (assoc-in valid-request [:query-params "a"] "666")))))
(testing "invalid request"
(is (thrown-with-msg?
@ -106,7 +112,8 @@
:form {:c s/Int}
:header {:d s/Int}
:path {:e s/Int}}
:responses {200 {:body {:total (s/constrained s/Int pos? 'positive)}}}
:responses {200 {:body {:total (s/constrained s/Int pos? 'positive)}}
500 {:description "fail"}}
:handler handler}}]]
{:data {:middleware middleware
:coercion schema/coercion}})))]
@ -118,7 +125,10 @@
(testing "all good"
(is (= {:status 200
:body {:total 15}}
(app valid-request))))
(app valid-request)))
(is (= {:status 500
:body {:evil true}}
(app (assoc-in valid-request [:query-params "a"] "666")))))
(testing "invalid request"
(is (thrown-with-msg?

View file

@ -89,7 +89,9 @@
:form {:c string?}
:header {:d string?}
:path {:e string?}}
:responses {200 {:body {:total pos-int?}}}
:responses {200 {:body {:total pos-int?}}
400 {:description "fail"}
500 {}}
:handler identity}}]]
{:data {:middleware [rrc/coerce-exceptions-middleware
rrc/coerce-request-middleware

View file

@ -23,9 +23,12 @@
{:get {:summary "plus"
:parameters {:query {:x int?, :y int?}
:path {:z int?}}
:responses {200 {:body {:total int?}}}
:swagger {:responses {400 {:schema {:type "string"}
:description "kosh"}}}
:responses {200 {:body {:total int?}}
500 {:description "fail"}}
:handler (fn [{{{:keys [x y]} :query
{:keys [z]} :path} :parameters}]
{:keys [z]} :path} :parameters}]
{:status 200, :body {:total (+ x y z)}})}}]]
["/schema" {:coercion schema/coercion}
@ -33,9 +36,12 @@
{:get {:summary "plus"
:parameters {:query {:x Int, :y Int}
:path {:z Int}}
:responses {200 {:body {:total Int}}}
:swagger {:responses {400 {:schema {:type "string"}
:description "kosh"}}}
:responses {200 {:body {:total Int}}
500 {:description "fail"}}
:handler (fn [{{{:keys [x y]} :query
{:keys [z]} :path} :parameters}]
{:keys [z]} :path} :parameters}]
{:status 200, :body {:total (+ x y z)}})}}]]]
{:data {:middleware [swagger/swagger-feature
@ -87,7 +93,10 @@
:properties {"total" {:format "int32"
:type "integer"}}
:required ["total"]
:type "object"}}}
:type "object"}}
400 {:schema {:type "string"}
:description "kosh"}
500 {:description "fail"}}
:summary "plus"}}
"/api/spec/plus/{z}" {:get {:parameters [{:description ""
:format "int64"
@ -111,7 +120,10 @@
:schema {:properties {"total" {:format "int64"
:type "integer"}}
:required ["total"]
:type "object"}}}
:type "object"}}
400 {:schema {:type "string"}
:description "kosh"}
500 {:description "fail"}}
:summary "plus"}}}}
spec)))))