diff --git a/advanced/composing_routers.html b/advanced/composing_routers.html
index 062b7416..77108cf0 100644
--- a/advanced/composing_routers.html
+++ b/advanced/composing_routers.html
@@ -1111,7 +1111,7 @@
diff --git a/advanced/configuring_routers.html b/advanced/configuring_routers.html
index cd8bc9d4..ae0a8cf1 100644
--- a/advanced/configuring_routers.html
+++ b/advanced/configuring_routers.html
@@ -817,7 +817,7 @@
diff --git a/advanced/dev_workflow.html b/advanced/dev_workflow.html
index 4b278adb..dffc2553 100644
--- a/advanced/dev_workflow.html
+++ b/advanced/dev_workflow.html
@@ -876,7 +876,7 @@
diff --git a/advanced/different_routers.html b/advanced/different_routers.html
index 61bccb89..b0888ccf 100644
--- a/advanced/different_routers.html
+++ b/advanced/different_routers.html
@@ -820,7 +820,7 @@
diff --git a/advanced/route_validation.html b/advanced/route_validation.html
index 868a5ce9..692db703 100644
--- a/advanced/route_validation.html
+++ b/advanced/route_validation.html
@@ -912,7 +912,7 @@
diff --git a/advanced/shared_routes.html b/advanced/shared_routes.html
index df72c518..58f40d30 100644
--- a/advanced/shared_routes.html
+++ b/advanced/shared_routes.html
@@ -832,7 +832,7 @@
diff --git a/basics/name_based_routing.html b/basics/name_based_routing.html
index 94f16190..217b3c91 100644
--- a/basics/name_based_routing.html
+++ b/basics/name_based_routing.html
@@ -835,7 +835,7 @@
diff --git a/basics/path_based_routing.html b/basics/path_based_routing.html
index 83bd9c55..38af98e6 100644
--- a/basics/path_based_routing.html
+++ b/basics/path_based_routing.html
@@ -793,7 +793,7 @@
diff --git a/basics/route_conflicts.html b/basics/route_conflicts.html
index 3fe932ac..2a17e2c5 100644
--- a/basics/route_conflicts.html
+++ b/basics/route_conflicts.html
@@ -836,7 +836,7 @@
diff --git a/basics/route_data.html b/basics/route_data.html
index 875f6333..73619393 100644
--- a/basics/route_data.html
+++ b/basics/route_data.html
@@ -834,7 +834,7 @@
diff --git a/basics/route_data_validation.html b/basics/route_data_validation.html
index 0998e388..e495a134 100644
--- a/basics/route_data_validation.html
+++ b/basics/route_data_validation.html
@@ -886,7 +886,7 @@
diff --git a/basics/route_syntax.html b/basics/route_syntax.html
index 13cb7048..48964dce 100644
--- a/basics/route_syntax.html
+++ b/basics/route_syntax.html
@@ -823,7 +823,7 @@ E.g., /foo bar should be /foo%20bar.
diff --git a/basics/router.html b/basics/router.html
index 4fa25198..ff951b1d 100644
--- a/basics/router.html
+++ b/basics/router.html
@@ -803,7 +803,7 @@
diff --git a/cljdoc.edn b/cljdoc.edn
index 50d5b8cf..6e4014dd 100644
--- a/cljdoc.edn
+++ b/cljdoc.edn
@@ -25,6 +25,7 @@
["Ring-router" {:file "doc/ring/ring.md"}]
["Reverse-routing" {:file "doc/ring/reverse_routing.md"}]
["Default handler" {:file "doc/ring/default_handler.md"}]
+ ["Slash handler" {:file "doc/ring/slash_handler.md"}]
["Static Resources" {:file "doc/ring/static.md"}]
["Dynamic Extensions" {:file "doc/ring/dynamic_extensions.md"}]
["Data-driven Middleware" {:file "doc/ring/data_driven_middleware.md"}]
diff --git a/coercion/clojure_spec_coercion.html b/coercion/clojure_spec_coercion.html
index c5ad92b8..5dec295a 100644
--- a/coercion/clojure_spec_coercion.html
+++ b/coercion/clojure_spec_coercion.html
@@ -810,7 +810,7 @@
diff --git a/coercion/coercion.html b/coercion/coercion.html
index 1c453597..6324ef84 100644
--- a/coercion/coercion.html
+++ b/coercion/coercion.html
@@ -900,7 +900,7 @@
diff --git a/coercion/data_spec_coercion.html b/coercion/data_spec_coercion.html
index 182b3840..5ced5f21 100644
--- a/coercion/data_spec_coercion.html
+++ b/coercion/data_spec_coercion.html
@@ -799,7 +799,7 @@
diff --git a/coercion/schema_coercion.html b/coercion/schema_coercion.html
index 35deb9b5..23cf3dff 100644
--- a/coercion/schema_coercion.html
+++ b/coercion/schema_coercion.html
@@ -800,7 +800,7 @@
diff --git a/development.html b/development.html
index 88995194..34fc74d8 100644
--- a/development.html
+++ b/development.html
@@ -790,7 +790,7 @@ lein test
diff --git a/faq.html b/faq.html
index 919bb348..c7189503 100644
--- a/faq.html
+++ b/faq.html
@@ -868,7 +868,7 @@
diff --git a/frontend/basics.html b/frontend/basics.html
index 3bca88d8..f30285d9 100644
--- a/frontend/basics.html
+++ b/frontend/basics.html
@@ -778,7 +778,7 @@ React breaking due to errors).
diff --git a/frontend/browser.html b/frontend/browser.html
index 9eed4ca2..01a2d630 100644
--- a/frontend/browser.html
+++ b/frontend/browser.html
@@ -782,7 +782,7 @@ router instance and passes the instance to all calls.
diff --git a/frontend/controllers.html b/frontend/controllers.html
index 58df86ec..88d1e406 100644
--- a/frontend/controllers.html
+++ b/frontend/controllers.html
@@ -795,7 +795,7 @@ missing resources.
diff --git a/http/default_interceptors.html b/http/default_interceptors.html
index a717b67e..aa711f2d 100644
--- a/http/default_interceptors.html
+++ b/http/default_interceptors.html
@@ -790,7 +790,7 @@
diff --git a/http/interceptors.html b/http/interceptors.html
index 75d442e2..394d53b1 100644
--- a/http/interceptors.html
+++ b/http/interceptors.html
@@ -782,7 +782,7 @@
diff --git a/http/pedestal.html b/http/pedestal.html
index 5661cc86..be45b3c7 100644
--- a/http/pedestal.html
+++ b/http/pedestal.html
@@ -790,7 +790,7 @@
diff --git a/http/sieppari.html b/http/sieppari.html
index 8e6b0ba9..50dd1406 100644
--- a/http/sieppari.html
+++ b/http/sieppari.html
@@ -830,7 +830,7 @@
diff --git a/index.html b/index.html
index 5dba9415..5b17299a 100644
--- a/index.html
+++ b/index.html
@@ -910,7 +910,7 @@
diff --git a/performance.html b/performance.html
index d5944355..d8e160e0 100644
--- a/performance.html
+++ b/performance.html
@@ -847,7 +847,7 @@
diff --git a/ring/coercion.html b/ring/coercion.html
index 41b8c2f6..cf5de1f8 100644
--- a/ring/coercion.html
+++ b/ring/coercion.html
@@ -901,7 +901,7 @@
diff --git a/ring/compiling_middleware.html b/ring/compiling_middleware.html
index 0b800596..a403f97b 100644
--- a/ring/compiling_middleware.html
+++ b/ring/compiling_middleware.html
@@ -828,7 +828,7 @@
diff --git a/ring/data_driven_middleware.html b/ring/data_driven_middleware.html
index 0b6aaa01..b3bcbed9 100644
--- a/ring/data_driven_middleware.html
+++ b/ring/data_driven_middleware.html
@@ -856,7 +856,7 @@
diff --git a/ring/default_handler.html b/ring/default_handler.html
index ff193cba..13a99cae 100644
--- a/ring/default_handler.html
+++ b/ring/default_handler.html
@@ -834,7 +834,7 @@
diff --git a/ring/default_middleware.html b/ring/default_middleware.html
index 86547ca3..9c79dddd 100644
--- a/ring/default_middleware.html
+++ b/ring/default_middleware.html
@@ -984,7 +984,7 @@ Server: Jetty(9.2.21.v20170120)
diff --git a/ring/dynamic_extensions.html b/ring/dynamic_extensions.html
index c002458b..cd4d66f2 100644
--- a/ring/dynamic_extensions.html
+++ b/ring/dynamic_extensions.html
@@ -803,7 +803,7 @@
diff --git a/ring/middleware_registry.html b/ring/middleware_registry.html
index 81d76e35..7856af0c 100644
--- a/ring/middleware_registry.html
+++ b/ring/middleware_registry.html
@@ -814,7 +814,7 @@
diff --git a/ring/reverse_routing.html b/ring/reverse_routing.html
index 5de9a576..4fc21056 100644
--- a/ring/reverse_routing.html
+++ b/ring/reverse_routing.html
@@ -799,7 +799,7 @@
diff --git a/ring/ring.html b/ring/ring.html
index 5ad69b76..5778a043 100644
--- a/ring/ring.html
+++ b/ring/ring.html
@@ -935,7 +935,7 @@
diff --git a/ring/route_data_validation.html b/ring/route_data_validation.html
index 49ecb361..fc79f8d8 100644
--- a/ring/route_data_validation.html
+++ b/ring/route_data_validation.html
@@ -1011,7 +1011,7 @@
diff --git a/ring/slash_handler.md b/ring/slash_handler.md
new file mode 100644
index 00000000..76c0ad49
--- /dev/null
+++ b/ring/slash_handler.md
@@ -0,0 +1,64 @@
+# Slash handler
+
+The router works with precise matches. If a route is defined without a trailing slash, for example, it won't match a request with a slash.
+
+```clj
+(require '[reitit.ring :as ring])
+
+(def app
+ (ring/ring-handler
+ (ring/router
+ ["/ping" (constantly {:status 200, :body ""})])))
+
+(app {:uri "/ping/"})
+; nil
+```
+
+Sometimes it is desirable that paths with and without a trailing slash are recognized as the same.
+
+Setting the `redirect-trailing-slash-handler` as a second argument to `ring-handler`:
+
+```clj
+(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 ""}
+```
+
+`redirect-trailing-slash-handler` accepts an optional `:method` parameter that allows configuring how (whether) to handle missing/extra slashes. The default is to handle both.
+
+```clj
+(def app
+ (ring/ring-handler
+ (ring/router
+ [["/ping" (constantly {:status 200, :body ""})]
+ ["/pong/" (constantly {:status 200, :body ""})]])
+ ; only handle extra trailing slash
+ (ring/redirect-trailing-slash-handler {:method :strip})))
+
+(app {:uri "/ping/"})
+; {:status 308, :headers {"Location" "/ping"}, :body ""}
+(app {:uri "/pong"})
+; nil
+```
+```clj
+(def app
+ (ring/ring-handler
+ (ring/router
+ [["/ping" (constantly {:status 200, :body ""})]
+ ["/pong/" (constantly {:status 200, :body ""})]])
+ ; only handle missing trailing slash
+ (ring/redirect-trailing-slash-handler {:method :add})))
+
+(app {:uri "/ping/"})
+; nil
+(app {:uri "/pong"})
+; {:status 308, :headers {"Location" "/pong/"}, :body ""}
+```
diff --git a/ring/static.html b/ring/static.html
index 220a4477..7f70c920 100644
--- a/ring/static.html
+++ b/ring/static.html
@@ -839,7 +839,7 @@
diff --git a/ring/swagger.html b/ring/swagger.html
index 188e6682..652bbf09 100644
--- a/ring/swagger.html
+++ b/ring/swagger.html
@@ -1044,7 +1044,7 @@
diff --git a/ring/transforming_middleware_chain.html b/ring/transforming_middleware_chain.html
index ddfc4341..3cb62736 100644
--- a/ring/transforming_middleware_chain.html
+++ b/ring/transforming_middleware_chain.html
@@ -791,7 +791,7 @@