reitit/CHANGELOG.md

17 KiB

UNRELEASED

reitit-core

  • segment-router doesn't accept empty segments as path-parameters, fixes #181.

0.2.9 (2018-11-21)

reitit-spec

0.2.8 (2018-11-18)

reitit-core

  • Added support for composing middleware & interceptor transformations, fixes #167.

reitit-spec

  • Spec problems are exposed as-is into request & response coercion errors, enabling pretty-printers like expound to be used:
(require '[reitit.ring :as ring])
(require '[reitit.ring.middleware.exception :as exception])
(require '[reitit.ring.coercion :as coercion])
(require '[expound.alpha :as expound])

(defn coercion-error-handler [status]
  (let [printer (expound/custom-printer {:theme :figwheel-theme, :print-specs? false})
        handler (exception/create-coercion-handler status)]
    (fn [exception request]
      (printer (-> exception ex-data :problems))
      (handler exception request))))

(def app
  (ring/ring-handler
    (ring/router
      ["/plus"
       {:get
        {:parameters {:query {:x int?, :y int?}}
         :responses {200 {:body {:total pos-int?}}}
         :handler (fn [{{{:keys [x y]} :query} :parameters}]
                    {:status 200, :body {:total (+ x y)}})}}]
      {:data {:coercion reitit.coercion.spec/coercion
              :middleware [(exception/create-exception-middleware
                             (merge
                               exception/default-handlers
                               {:reitit.coercion/request-coercion (coercion-error-handler 400)
                                :reitit.coercion/response-coercion (coercion-error-handler 500)}))
                           coercion/coerce-request-middleware
                           coercion/coerce-response-middleware]}})))

(app
  {:uri "/plus"
   :request-method :get
   :query-params {"x" "1", "y" "fail"}})

(app
  {:uri "/plus"
   :request-method :get
   :query-params {"x" "1", "y" "-2"}})

reitit-swagger

0.2.7 (2018-11-11)

reitit-spec

[metosin/spec-tools "0.8.2"] is available but we use "0.8.1"

0.2.6 (2018-11-09)

reitit-core

  • Faster path-parameter decoding: doing less work when parameters don't need decoding. Wildcard-routing is now 10-15% faster in perf tests (opensensors & github api).
  • Fixed a ClojureScript compiler warning about private var usage. #169

reitit-ring

  • redirect-trailing-slash-handler can strip multiple slashes from end of the uri, by Hannu Hartikainen.

  • Fixed a ClojureScript compiler warning about satisfies? being a macro.

  • updated deps:

[ring "1.7.1"] is available but we use "1.7.0"

reitit-spec

  • updated deps:
[metosin/spec-tools "0.8.1"] is available but we use "0.8.0"

reitit-schema

  • updated deps:
[metosin/schema-tools "0.10.5"] is available but we use "0.10.4"

reitit-sieppari

  • updated deps:
[metosin/sieppari "0.0.0-alpha6"] is available but we use "0.0.0-alpha5"

0.2.5 (2018-10-30)

reitit-ring

  • router is injected into request also in the default branch
  • new reitit.ring/redirect-trailing-slash-handler to handle trailing slashes with style!
(require '[reitit.ring :as ring])

(def app
  (ring/ring-handler
    (ring/router
      [["/ping" (constantly {:status 200, :body ""})]
       ["/pong/" (constantly {:status 200, :body ""})]])
    (ring/redirect-trailing-slash-handler)))

(app {:uri "/ping/"})
; {:status 308, :headers {"Location" "/ping"}, :body ""}

(app {:uri "/pong"})
; {:status 308, :headers {"Location" "/pong/"}, :body ""}
  • updated deps:
[ring/ring-core "1.7.1"] is available but we use "1.7.0"

reitit-http

  • router is injected into request also in the default branch

0.2.4 (2018-10-21)

reitit-ring

  • New option :not-found-handler in reitit.ring/create-resource-handler to set how 404 is handled. Fixes #89, thanks to valerauko.

reitit-spec

  • Latest features from spec-tools

    • Swagger enchancements
    • Better spec coercion via st/coerce using spec walking & inference: many simple specs (core predicates, spec-tools.core/spec, s/and, s/or, s/coll-of, s/keys, s/map-of, s/nillable and s/every) can be transformed without needing spec to be wrapped. Fallbacks to old conformed based approach.
    • example app.
  • updated deps:

[metosin/spec-tools "0.8.0"] is available but we use "0.7.1"

0.2.3 (2018-09-24)

reitit-ring

  • ring-handler takes optionally a 3rd argument, an options map which can be used to se top-level middleware, applied before any routing is done:
(require '[reitit.ring :as ring])

(defn wrap [handler id]
  (fn [request]
    (handler (update request ::acc (fnil conj []) id))))

(defn handler [{:keys [::acc]}]
  {:status 200, :body (conj acc :handler)})

(def app
  (ring/ring-handler
    (ring/router
      ["/api" {:middleware [[mw :api]]}
       ["/get" {:get handler}]])
    (ring/create-default-handler)
    {:middleware [[mw :top]]}))

(app {:request-method :get, :uri "/api/get"})
; {:status 200, :body [:top :api :ok]}

(require '[reitit.core :as r])

(-> app (ring/get-router))
; #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

    • 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:

[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
    • 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:

[metosin/muuntaja "0.6.1"] is available but we use "0.6.0"

reitit-swagger-ui

  • updated deps:
[metosin/jsonista "0.2.2"] is available but we use "0.2.1"

0.2.2 (2018-09-09)

reitit-middleware

  • new middleware reitit.ring.middleware.parameters/parameters-middleware to wrap query & form params.

reitit-interceptors

  • new module like reitit-middleware but for interceptors. See the Docs.

0.2.1 (2018-09-04)

reitit-schema

  • updated deps:
[metosin/schema-tools "0.10.4"] is available but we use "0.10.3"

reitit-middleware

  • updated deps:
[metosin/muuntaja "0.6.0"] is available but we use "0.6.0-alpha5"

0.2.0 (2018-09-03)

Sample apps demonstraing the current status of reitit:

reitit-core

  • BREAKING: the router option key to extract body format has been renamed: :extract-request-format => :reitit.coercion/extract-request-format
    • should only concern you if you are not using Muuntaja.
  • the r/routes returns just the path + data tuples as documented, not the compiled route results. To get the compiled results, use r/compiled-routes instead.
  • new faster and more correct encoders and decoders for query & path params.
    • all path-parameters are now decoded correctly with reitit.impl/url-decode, thanks to Matthew Davidson!
    • query-parameters are encoded with reitit.impl/form-encode, so spaces are + instead of %20.
  • correctly read :header params from request :headers, not :header-params
  • welcome route name conflict resolution! If router has routes with same names, router can't be created. fix 'em.
  • sequential child routes are allowed, enabling this:
(-> ["/api"
     (for [i (range 4)]
       [(str "/" i)])]
    (r/router)
    (r/routes))
;[["/api/0" {}]
; ["/api/1" {}]
; ["/api/2" {}]
; ["/api/3" {}]]
  • A Guide to compose routers
  • Welcome Middleware and Intercetor Registries!
    • when Keywords are used in place of middleware / interceptor, a lookup is done into Router option ::middleware/registry (or ::interceptor/registry) with the key. Fails fast with missing registry entries.
    • fixes #32.
    • full documentation here.
(require '[reitit.ring :as ring])
(require '[reitit.middleware :as middleware])

(defn wrap-bonus [handler value]
 (fn [request]
   (handler (update request :bonus (fnil + 0) value))))

(def app
 (ring/ring-handler
   (ring/router
     ["/api" {:middleware [[:bonus 20]]}
      ["/bonus" {:middleware [:bonus10]
                :get (fn [{:keys [bonus]}]
                       {:status 200, :body {:bonus bonus}})}]]
     {::middleware/registry {:bonus wrap-bonus
                             :bonus10 [:bonus 10]}})))

(app {:request-method :get, :uri "/api/bonus"})
; {:status 200, :body {:bonus 30}}

reitit-swagger

  • In case of just one swagger api per router, the swagger api doesn't have to identified, so this works now:
(require '[reitit.ring :as ring])
(require '[reitit.swagger :as swagger])
(require '[reitit.swagger-ui :as swagger-ui])

(ring/ring-handler
  (ring/router
    [["/ping"
      {:get (fn [_] {:status 200, :body "pong"})}]
     ["/swagger.json"
      {:get {:no-doc true
             :handler (swagger/create-swagger-handler)}}]])
  (swagger-ui/create-swagger-ui-handler {:path "/"}))

reitit-middleware

  • A new module with common data-driven middleware: exception handling, content negotiation & multipart requests. See the docs.

reitit-swagger-ui

  • BREAKING: pass swagger-ui :config as-is (instead of mixed-casing keys) to swagger-ui, fixes #109:
    • see docs for available parameters.
(swagger-ui/create-swagger-ui-handler
  {:path "/"
   :url "/api/swagger.json"
   :config {:jsonEditor true
            :validatorUrl nil}})

reitit-frontend

  • new module for frontend-routing. See docs for details.

0.1.3 (2018-6-25)

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.
(def router
  (reitit.core/router
    ["/spec" {:coercion reitit.coercion.spec/coercion}
     ["/:number/:keyword" {:parameters {:path {:number int?
                                               :keyword keyword?}
                                        :query (ds/maybe {:int int?})}}]]
    {:compile reitit.coercion/compile-request-coercers}))

(-> (reitit.core/match-by-path router "/spec/10/kikka")
    (assoc :query-params {:int "10"})
    (reitit.coercion/coerce!))
; {:path {:number 10, :keyword :kikka}
;  :query {:int 10}}
  • reitit.core/match->path to create full paths from match, including the query parameters:
(require '[reitit.core :as r])

(-> (r/router ["/:a/:b" ::route])
    (r/match-by-name! ::route {:a "olipa", :b "kerran"})
    (r/match->path))
; "/olipa/kerran"

(-> (r/router ["/:a/:b" ::route])
    (r/match-by-name! ::route {:a "olipa", :b "kerran"})
    (r/match->path {:iso "pöriläinen"}))
; "/olipa/kerran?iso=p%C3%B6ril%C3%A4inen"

reitit-spec

  • [metosin/spec-tools "0.7.1"] with swagger generation enhancements, see the CHANGELOG
  • if response coercion is not defined for a response status, no :schema is not emitted.
  • updated dependencies:
[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

  • Better handling of nil in route syntax:
    • explicit nil after path string is always handled as nil route
    • nil as path string causes the whole route to be nil
    • nil as child route is stripped away
(testing "nil routes are stripped"
  (is (= [] (r/routes (r/router nil))))
  (is (= [] (r/routes (r/router [nil ["/ping"]]))))
  (is (= [] (r/routes (r/router [nil [nil] [[nil nil nil]]]))))
  (is (= [] (r/routes (r/router ["/ping" [nil "/pong"]])))))

reitit-ring

  • Use HTTP redirect (302) with index-files in reitit.ring/create-resource-handler.
  • reitit.ring/create-default-handler now conforms to RING Spec, Fixes #83

reitit-schema

  • updated dependencies:
[metosin/schema-tools "0.10.3"] is available but we use "0.10.2"

reitit-swagger

reitit-swagger-ui

  • Use HTTP redirect (302) with index-files in reitit.swagger-ui/create-swagger-ui-handler.

  • updated dependencies:

[metosin/jsonista "0.2.1"] is available but we use "0.2.0"

0.1.1 (2018-5-20)

reitit-core

  • linear-router now works with unnamed catch-all parameters, e.g. "/files/*"
  • match-by-path encodes parameters into strings using (internal) reitit.impl/IntoString protocol. Handles all of: strings, numbers, keywords, booleans, objects. Fixes #75.
(require '[reitit.core :as r])

(r/match-by-name
  (r/router
    ["/coffee/:type" ::coffee])
  ::coffee
  {:type :luwak})
;#Match{:template "/coffee/:type",
;       :data {:name :user/coffee},
;       :result nil,
;       :path-params {:type "luwak"},
;       :path "/coffee/luwak"}

reitit-ring

  • reitit.ring/default-handler now works correctly with async ring

  • new helper reitit.ring/router to compose routes outside of a router.

  • reitit.ring/create-resource-handler function to serve static routes. See docs.

  • new dependencies:

[ring/ring-core "1.6.3"]

reitit-swagger

  • New module to produce swagger-docs from routing tree, including Coercion definitions. Works with both middleware & interceptors and Schema & Spec. See docs and example project.

reitit-swagger-ui

New module to server pre-integrated Swagger-ui. See docs.

  • new dependencies:
[metosin/jsonista "0.2.0"]
[metosin/ring-swagger-ui "2.2.10"]

dependencies

[metosin/spec-tools "0.7.0"] is available but we use "0.6.1"
[metosin/schema-tools "0.10.2"] is available but we use "0.10.1"

0.1.0 (2018-2-19)

  • First release