Skip to content
This repository was archived by the owner on Aug 18, 2020. It is now read-only.

Commit 74cc084

Browse files
committed
[CO-370] Make Content-Type parsing more lenient
We have had a lot of trouble where people will send no content-type or simply 'application/json' and request would fail with 415 Unsupported Media Type. Without knowing where to look, the error looks quite unexpected and could give a lot of headache. This commit does two changes: - It slightly modifies the 'Accept' instance to use 'contentTypes' instead of 'contentType'. The latter is defined from the former by simply taking the head of the list returned by 'contentTypes', which in our case is 'application/json;charset=utf-8' - It provides a default content-type 'application/json' when no content-type is provided
1 parent ea99d47 commit 74cc084

File tree

3 files changed

+34
-3
lines changed

3 files changed

+34
-3
lines changed

wallet-new/server/Main.hs

+5-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import Pos.Wallet.Web.Tracking.Sync (syncWallet)
3939

4040
import qualified Cardano.Wallet.Kernel.Mode as Kernel.Mode
4141

42+
import qualified Cardano.Wallet.API.V1.Headers as Headers
4243
import Cardano.Wallet.Kernel (PassiveWallet)
4344
import qualified Cardano.Wallet.Kernel as Kernel
4445
import qualified Cardano.Wallet.Kernel.Internal as Kernel.Internal
@@ -50,7 +51,8 @@ import Cardano.Wallet.Server.CLI (ChooseWalletBackend (..),
5051
getWalletNodeOptions, walletDbPath, walletFlushDb,
5152
walletRebuildDb)
5253
import qualified Cardano.Wallet.Server.LegacyPlugins as LegacyPlugins
53-
import Cardano.Wallet.Server.Middlewares (throttleMiddleware)
54+
import Cardano.Wallet.Server.Middlewares (throttleMiddleware,
55+
withDefaultHeader)
5456
import qualified Cardano.Wallet.Server.Plugins as Plugins
5557
import Cardano.Wallet.WalletLayer (PassiveWalletLayer)
5658
import qualified Cardano.Wallet.WalletLayer.Kernel as WalletLayer.Kernel
@@ -109,6 +111,7 @@ actionWithLegacyWallet genesisConfig walletConfig txpConfig sscParams nodeParams
109111
mconcat [ LegacyPlugins.conversation wArgs
110112
, LegacyPlugins.legacyWalletBackend genesisConfig walletConfig txpConfig wArgs ntpStatus
111113
[ LegacyPlugins.throttleMiddleware (ccThrottle walletConfig)
114+
, withDefaultHeader (Headers.applicationJson)
112115
]
113116
, LegacyPlugins.walletDocumentation wArgs
114117
, LegacyPlugins.acidCleanupWorker wArgs
@@ -177,6 +180,7 @@ actionWithWallet genesisConfig walletConfig txpConfig sscParams nodeParams ntpCo
177180
[ Plugins.apiServer pm params w
178181
-- Throttle requests.
179182
[ throttleMiddleware (ccThrottle walletConfig)
183+
, withDefaultHeader (Headers.applicationJson)
180184
]
181185

182186
-- The corresponding wallet documention, served as a different

wallet-new/src/Cardano/Wallet/API/Response.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ instance FromJSON a => MimeUnrender ValidJSON a where
229229
Right v -> return v
230230

231231
instance Accept ValidJSON where
232-
contentType _ = contentType (Proxy @ JSON)
232+
contentTypes _ = contentTypes (Proxy @ JSON)
233233

234234
instance ToJSON a => MimeRender ValidJSON a where
235235
mimeRender _ = mimeRender (Proxy @ JSON)

wallet-new/src/Cardano/Wallet/Server/Middlewares.hs

+28-1
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,35 @@
66
module Cardano.Wallet.Server.Middlewares
77
( withMiddlewares
88
, throttleMiddleware
9+
, withDefaultHeader
910
) where
1011

1112
import Universum
1213

1314
import Data.Aeson (encode)
14-
import Network.Wai (Application, Middleware, responseLBS)
15+
import qualified Data.List as List
16+
import Network.HTTP.Types.Header (Header)
17+
import Network.HTTP.Types.Method (methodPatch, methodPost, methodPut)
18+
import Network.Wai (Application, Middleware, ifRequest,
19+
requestHeaders, requestMethod, responseLBS)
1520
import qualified Network.Wai.Middleware.Throttle as Throttle
1621

1722
import Cardano.Wallet.API.V1.Headers (applicationJson)
1823
import qualified Cardano.Wallet.API.V1.Types as V1
1924

2025
import Pos.Launcher.Configuration (ThrottleSettings (..))
2126

27+
2228
-- | "Attaches" the middlewares to this 'Application'.
2329
withMiddlewares :: [Middleware] -> Application -> Application
2430
withMiddlewares = flip $ foldr ($)
2531

32+
-- | Only apply a @Middleware@ to request with bodies (we don't consider
33+
-- "DELETE" as one of them).
34+
ifRequestWithBody :: Middleware -> Middleware
35+
ifRequestWithBody =
36+
ifRequest ((`List.elem` [methodPost, methodPut, methodPatch]) . requestMethod)
37+
2638
-- | A @Middleware@ to throttle requests.
2739
throttleMiddleware :: Maybe ThrottleSettings -> Middleware
2840
throttleMiddleware Nothing app = app
@@ -40,3 +52,18 @@ throttleMiddleware (Just ts) app = \req respond -> do
4052
, Throttle.throttlePeriod = fromIntegral $ tsPeriod ts
4153
, Throttle.throttleBurst = fromIntegral $ tsBurst ts
4254
}
55+
56+
-- | A @Middleware@ to default a specific Header when not provided
57+
withDefaultHeader :: Header -> Middleware
58+
withDefaultHeader header = ifRequestWithBody $ \app req send ->
59+
let
60+
headers =
61+
requestHeaders req
62+
63+
req' =
64+
if any (on (==) fst header) headers then
65+
req
66+
else
67+
req { requestHeaders = header : headers }
68+
in
69+
app req' send

0 commit comments

Comments
 (0)