| Safe Haskell | None | 
|---|---|
| Language | Haskell2010 | 
Network.Wai.Middleware.Rewrite
Contents
Synopsis
- type PathsAndQueries = ([Text], Query)
- rewriteWithQueries :: (PathsAndQueries -> RequestHeaders -> IO PathsAndQueries) -> Middleware
- rewritePureWithQueries :: (PathsAndQueries -> RequestHeaders -> PathsAndQueries) -> Middleware
- rewriteRoot :: Text -> Middleware
- rewrite :: ([Text] -> RequestHeaders -> IO [Text]) -> Middleware
- rewritePure :: ([Text] -> RequestHeaders -> [Text]) -> Middleware
- rewriteRequest :: (PathsAndQueries -> RequestHeaders -> IO PathsAndQueries) -> Request -> IO Request
- rewriteRequestPure :: (PathsAndQueries -> RequestHeaders -> PathsAndQueries) -> Request -> Request
How to use this module
This module provides Middleware to rewrite URL paths. It also provides
 functions that will convert a Request to a modified Request.
 Both operations require a function that takes URL parameters and
 headers, and returns new URL parameters. Parameters are pieces of URL
 paths and query parameters.
If you are a new user of the library, use rewriteWithQueries or
 rewritePureWithQueries for middleware. For modifying Requests
 directly, use rewriteRequest or rewriteRequestPure.
A note on semantics
Versions of this library in wai-extra ≤ 3.0.16.1 exported only
 rewrite and rewritePure and both modified rawPathInfo of the
 underlying requests. Such modification has been proscribed. The
 semantics of these functions have not changed; instead the recommended
 approach is to use rewriteWithQueries and rewritePureWithQueries.
 The new functions are slightly different, as described in the section
 on upgrading; code for previous library versions can be upgraded with
 a single change, and as the type of the new function is different the
 compiler will indicate where this change must be made.
The rewriteRequest and rewriteRequestPure functions use the new
 semantics, too.
Paths and Queries
This library defines the type synonym PathsAndQueries to make code
 handling paths and queries easier to read.
e.g. /foo/bar would look like
["foo", "bar"] :: Text
?bar=baz would look like
[("bar", Just "baz")] :: QueryTextTogether,
/foo?bar=baz would look like
(["foo"],[("bar", Just "baz")]) :: PathsAndQueriestype PathsAndQueries = ([Text], Query) Source #
A tuple of the path sections as [Text] and query parameters as
 Query. This makes writing type signatures for the conversion
 function far more pleasant.
Note that this uses Query not QueryText to more accurately
 reflect the paramaters that can be supplied in URLs. It may be safe to
 treat parameters as text; use the queryToQueryText and
 queryTextToQuery functions to interconvert.
An example rewriting paths with queries
Let’s say we want to replace a website written in PHP with one written using WAI. We’ll use the http-reverse-proxy package to serve the old site from the new site, but there’s a problem. The old site uses pages like
index.php?page=page
whereas the new site would look like
index/page
In doing this, we want to separate the migration code from our new website. So we’d like to handle links internally using the path formulation, but externally have the old links still work.
Therefore, we will use middleware (rewritePureWithQueries) from this
 module to rewrite incoming requests from the query formulation to the
 paths formulation.
{-# LANGUAGE ViewPatterns #-}
rewritePathFromPhp :: Middleware
rewritePathFromPhp = rewritePureWithQueries pathFromPhp
pathFromPhp :: PathsAndQueries -> H.RequestHeaders -> PathsAndQueries
pathFromPhp (pieces, queries) _ = piecesConvert pieces queries
    where
        piecesConvert :: [Text] -> H.Query -> PathsAndQueries
        piecesConvert ["index.php"] qs@(join . lookup "page" -> Just page) =
            ( ["index", TE.decodeUtf8With TE.lenientDecode page]
            , delete ("page", pure page) qs
            )
        piecesConvert ps qs = (ps, qs)On the other side, we will use rewriteRequestPure to rewrite outgoing
 requests to the original website from the reverse proxy code (using the
 WPRModifiedRequest or
 WPRModifiedRequestSecure constructors. Note,
 these links will only work if the haddock documentation for
 http-reverse-proxy
 is installed).
rewritePhpFromPath :: Request -> Request
rewritePhpFromPath = rewriteRequestPure phpFromPath
phpFromPath :: PathsAndQueries -> H.RequestHeaders -> PathsAndQueries
phpFromPath (pieces, queries) _ = piecesConvert pieces queries
    where
        piecesConvert :: [Text] -> H.Query -> PathsAndQueries
        piecesConvert ["index", page] qs = ( ["index.php"], ("page", pure . TE.encodeUtf8 $ page) : qs )
        piecesConvert ps qs = (ps, qs)For the whole example, see https://gist.github.com/dbaynard/c844d0df124f68ec8b6da152c581ce6d.
Upgrading from wai-extra ≤ 3.0.16.1
It is quite simple to upgrade from rewrite and rewritePure, to
 rewriteWithQueries and rewritePureWithQueries.
 Insert first, which specialises to
first:: ([Text] -> [Text]) ->PathsAndQueries->PathsAndQueries
as the following example demonstrates.
Old versions of the library could only handle path pieces, not queries.
 This could have been supplied to rewritePure.
staticConvert' :: [Text] -> H.RequestHeaders -> [Text]
staticConvert' pieces _ = piecesConvert pieces
  where
   piecesConvert [] = ["static", "html", "pages.html"]
   piecesConvert route@("pages":_) = "static":"html":route
Instead, use this function, supplied to rewritePureWithQueries.
staticConvert ::PathsAndQueries-> H.RequestHeaders ->PathsAndQueriesstaticConvert pathsAndQueries _ =firstpiecesConvert pathsAndQueries where piecesConvert [] = ["static", "html", "pages.html"] piecesConvert route@("pages":_) = "static":"html":route
The former formulation is deprecated for two reasons:
- The original formulation of rewritemodifiedrawPathInfo, which is deprecated behaviour.
- The original formulation did not allow query parameters to influence the path.
Concerning the first point, take care with semantics of your program when
 upgrading as the upgraded functions no longer modify rawPathInfo.
Middleware
Recommended functions
rewriteWithQueries :: (PathsAndQueries -> RequestHeaders -> IO PathsAndQueries) -> Middleware Source #
Rewrite based on your own conversion function for paths and queries.
 This function is to be supplied by users of this library, and operates
 in IO.
rewritePureWithQueries :: (PathsAndQueries -> RequestHeaders -> PathsAndQueries) -> Middleware Source #
Rewrite based on pure conversion function for paths and queries. This function is to be supplied by users of this library.
rewriteRoot :: Text -> Middleware Source #
Rewrite root requests (/) to a specified path
Note that index.html in example below should already be a valid route.
rewriteRoot "index.html" :: Middleware
Since: 3.0.23.0
Deprecated
rewrite :: ([Text] -> RequestHeaders -> IO [Text]) -> Middleware Source #
Warning: This modifies the rawPathInfo field of a Request. This is not recommended behaviour; it is however how this function has worked in the past. Use rewriteWithQueries instead
Rewrite based on your own conversion function for paths only, to be
 supplied by users of this library (with the conversion operating in IO).
For new code, use rewriteWithQueries instead.
rewritePure :: ([Text] -> RequestHeaders -> [Text]) -> Middleware Source #
Warning: This modifies the rawPathInfo field of a Request. This is not recommended behaviour; it is however how this function has worked in the past. Use rewritePureWithQueries instead
Rewrite based on pure conversion function for paths only, to be supplied by users of this library.
For new code, use rewritePureWithQueries instead.
Operating on Requests
rewriteRequest :: (PathsAndQueries -> RequestHeaders -> IO PathsAndQueries) -> Request -> IO Request Source #
rewriteRequestPure :: (PathsAndQueries -> RequestHeaders -> PathsAndQueries) -> Request -> Request Source #
Modify a Request using the pure supplied function. This is suitable for
 the reverse proxy example.