diff --git a/Web/Route/Invertible/Internal.hs b/Web/Route/Invertible/Internal.hs
--- a/Web/Route/Invertible/Internal.hs
+++ b/Web/Route/Invertible/Internal.hs
@@ -29,6 +29,7 @@
   , blankRequest
   , RoutePredicate(..)
   , Route(..)
+  , requestRoutePredicate
   , normRoute
   , foldRoute
   , requestRoute'
diff --git a/Web/Route/Invertible/Map/Route.hs b/Web/Route/Invertible/Map/Route.hs
--- a/Web/Route/Invertible/Map/Route.hs
+++ b/Web/Route/Invertible/Map/Route.hs
@@ -70,22 +70,22 @@
   RouteMapCustom   a <> RouteMapCustom   b = RouteMapCustom   (a <> b)
   RouteMapPriority a <> RouteMapPriority b = RouteMapPriority (a <> b)
   RouteMapExactly  a <> RouteMapExactly  b = RouteMapExactly  (a <> b)
-  a@     (RouteMapHost     _) <> b = a <> RouteMapHost (defaultingValue b)
-  a <> b@(RouteMapHost     _)      =      RouteMapHost (defaultingValue a) <> b
-  a@     (RouteMapSecure   _) <> b = a <> RouteMapSecure (singletonBool Nothing b)
-  a <> b@(RouteMapSecure   _)      =      RouteMapSecure (singletonBool Nothing a) <> b
-  a@     (RouteMapPath     _) <> b = a <> RouteMapPath   (defaultingValue b)
-  a <> b@(RouteMapPath     _)      =      RouteMapPath   (defaultingValue a) <> b
-  a@     (RouteMapMethod   _) <> b = a <> RouteMapMethod (defaultingValue b)
-  a <> b@(RouteMapMethod   _)      =      RouteMapMethod (defaultingValue a) <> b
-  a@     (RouteMapQuery    _) <> b = a <> RouteMapQuery  (defaultQueryMap b)
-  a <> b@(RouteMapQuery    _)      =      RouteMapQuery  (defaultQueryMap a) <> b
-  a@     (RouteMapAccept   _) <> b = a <> RouteMapAccept (defaultingValue b)
-  a <> b@(RouteMapAccept   _)      =      RouteMapAccept (defaultingValue a) <> b
-  a@     (RouteMapCustom   _) <> b = a <> RouteMapCustom (constantValue b)
-  a <> b@(RouteMapCustom   _)      =      RouteMapCustom (constantValue a) <> b
-  a@     (RouteMapPriority _) <> b = a <> RouteMapPriority (Prioritized 0 b)
-  a <> b@(RouteMapPriority _)      =      RouteMapPriority (Prioritized 0 a) <> b
+  a@(RouteMapHost     _) <> b = a <> RouteMapHost (defaultingValue b)
+  a <> b@(RouteMapHost     _) =      RouteMapHost (defaultingValue a) <> b
+  a@(RouteMapSecure   _) <> b = a <> RouteMapSecure (singletonBool Nothing b)
+  a <> b@(RouteMapSecure   _) =      RouteMapSecure (singletonBool Nothing a) <> b
+  a@(RouteMapPath     _) <> b = a <> RouteMapPath   (defaultingValue b)
+  a <> b@(RouteMapPath     _) =      RouteMapPath   (defaultingValue a) <> b
+  a@(RouteMapMethod   _) <> b = a <> RouteMapMethod (defaultingValue b)
+  a <> b@(RouteMapMethod   _) =      RouteMapMethod (defaultingValue a) <> b
+  a@(RouteMapQuery    _) <> b = a <> RouteMapQuery  (defaultQueryMap b)
+  a <> b@(RouteMapQuery    _) =      RouteMapQuery  (defaultQueryMap a) <> b
+  a@(RouteMapAccept   _) <> b = a <> RouteMapAccept (defaultingValue b)
+  a <> b@(RouteMapAccept   _) =      RouteMapAccept (defaultingValue a) <> b
+  a@(RouteMapCustom   _) <> b = a <> RouteMapCustom (constantValue b)
+  a <> b@(RouteMapCustom   _) =      RouteMapCustom (constantValue a) <> b
+  a@(RouteMapPriority _) <> b = a <> RouteMapPriority (Prioritized 0 b)
+  a <> b@(RouteMapPriority _) =      RouteMapPriority (Prioritized 0 a) <> b
 
 instance Monoid (RouteMapT m a) where
   mempty = RouteMapExactly Blank
diff --git a/Web/Route/Invertible/Request.hs b/Web/Route/Invertible/Request.hs
--- a/Web/Route/Invertible/Request.hs
+++ b/Web/Route/Invertible/Request.hs
@@ -32,3 +32,20 @@
   , requestQuery = mempty
   , requestContentType = mempty
   }
+
+-- |Merge two requests, where non-blank values in the second argument take precedence.
+instance Semigroup Request where
+  a <> b = Request
+    { requestSecure = m requestSecure
+    , requestHost = m requestHost
+    , requestMethod = m requestMethod
+    , requestPath = m requestPath
+    , requestQuery = m requestQuery
+    , requestContentType = m requestContentType
+    } where
+    m f
+      | f b == f blankRequest = f a
+      | otherwise = f b
+
+instance Monoid Request where
+  mempty = blankRequest
diff --git a/Web/Route/Invertible/Route.hs b/Web/Route/Invertible/Route.hs
--- a/Web/Route/Invertible/Route.hs
+++ b/Web/Route/Invertible/Route.hs
@@ -17,6 +17,7 @@
   , routePriority
   , normRoute
   , foldRoute
+  , requestRoutePredicate
   , requestRoute'
   , requestRoute
   , BoundRoute(..)
diff --git a/web-inv-route.cabal b/web-inv-route.cabal
--- a/web-inv-route.cabal
+++ b/web-inv-route.cabal
@@ -1,5 +1,5 @@
 name:                web-inv-route
-version:             0.1.3.1
+version:             0.1.3.2
 synopsis:            Composable, reversible, efficient web routing using invertible invariants and bijections
 description:
   Utilities to route HTTP requests, mainly focused on path components.  Routes are specified using bijections and invariant functors, allowing run-time composition (routes can be distributed across modules), reverse and forward routing derived from the same specification, and O(log n) lookups.
