-
Notifications
You must be signed in to change notification settings - Fork 332
Introduce VersionNumber newtype. #3075
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c9b99ed
31c9889
86c4b1f
53758c3
a8d8ed7
d2e52a1
ccd4650
5d05349
e599619
ecf5249
6780480
4aa8e48
7a2bdde
5ecadff
7e60211
416abf1
8b64085
81d062f
aad079e
262ccb4
d09820d
a11e0da
7589b2d
f02ae72
d3b4f24
d4d6ae4
c21c33a
d2a2c39
45f30a1
030f805
0bbbdd8
5d7b5f5
5cae797
5199887
5213043
33aefc6
759750f
1fdee85
c454df8
e94dd83
1360860
18382ab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| Introduce VersionNumber newtype (see `/libs/wire-api/src/Wire/API/Routes/Version.hs` for explanation) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -17,36 +17,50 @@ | |
|
|
||
| module Wire.API.Routes.Version.Wai where | ||
|
|
||
| import Control.Monad.Except (throwError) | ||
| import Data.ByteString.Conversion | ||
| import qualified Data.Text.Lazy as LText | ||
| import Data.EitherR (fmapL) | ||
| import Data.String.Conversions (cs) | ||
| import qualified Data.Text as T | ||
| import Imports | ||
| import qualified Network.HTTP.Types as HTTP | ||
| import Network.Wai | ||
| import Network.Wai.Middleware.Rewrite | ||
| import Network.Wai.Utilities.Error | ||
| import Network.Wai.Utilities.Response | ||
| import Web.HttpApiData (parseUrlPiece, toUrlPiece) | ||
| import Wire.API.Routes.Version | ||
|
|
||
| -- | Strip off version prefix. Return 404 if the version is not supported. | ||
| versionMiddleware :: Set Version -> Middleware | ||
| versionMiddleware disabledAPIVersions app req k = case parseVersion (removeVersionHeader req) of | ||
| Nothing -> app req k | ||
| Just (req', n) -> case mkVersion n of | ||
| Just v | v `notElem` disabledAPIVersions -> app (addVersionHeader v req') k | ||
| _ -> | ||
| k $ | ||
| errorRs' $ | ||
| mkError HTTP.status404 "unsupported-version" $ | ||
| "Version " <> LText.pack (show n) <> " is not supported" | ||
|
|
||
| parseVersion :: Request -> Maybe (Request, Integer) | ||
| Right (req', v) -> | ||
| if v `elem` disabledAPIVersions | ||
| then err (toUrlPiece v) | ||
| else app (addVersionHeader v req') k | ||
| Left (BadVersion v) -> err v | ||
| Left NoVersion -> app req k | ||
| where | ||
| err :: Text -> IO ResponseReceived | ||
| err v = | ||
| k . errorRs' . mkError HTTP.status404 "unsupported-version" $ | ||
| "Version " <> cs v <> " is not supported" | ||
|
|
||
| data ParseVersionError = NoVersion | BadVersion Text | ||
|
|
||
| parseVersion :: Request -> Either ParseVersionError (Request, Version) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm wondering if this function cannot be generalized regarding its Monad: Shouldn't a constraint (This is nitpicking as far as nitpicking can get ... 😉 )
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yes, that would be sufficient, but i intentionally decided against it. i like both the abstract interpretation and the precise type that offers exactly what's needed, and not more. always happy to nit-pick, though! :) |
||
| parseVersion req = do | ||
| (version, pinfo) <- case pathInfo req of | ||
| [] -> Nothing | ||
| [] -> throwError NoVersion | ||
| (x : xs) -> pure (x, xs) | ||
| n <- readVersionNumber version | ||
| unless (looksLikeVersion version) $ | ||
| throwError NoVersion | ||
| n <- fmapL (const $ BadVersion version) $ parseUrlPiece version | ||
| pure (rewriteRequestPure (\(_, q) _ -> (pinfo, q)) req, n) | ||
|
|
||
| looksLikeVersion :: Text -> Bool | ||
| looksLikeVersion version = case T.splitAt 1 version of (h, t) -> h == "v" && T.all isDigit t | ||
|
|
||
| removeVersionHeader :: Request -> Request | ||
| removeVersionHeader req = | ||
| req | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here: Could be implemented with
fromEnum.