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

Commit 70edf77

Browse files
authored
Merge pull request #3727 from input-output-hk/paweljakubas/CO-417/fix-unsupported-media-type
[CO-417] Add more friendly 415 Unsupported Media Type error
2 parents 69cb520 + f71f0b4 commit 70edf77

10 files changed

+94
-14
lines changed

CHANGELOG.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@
2121

2222
- We can force an NTP-check when getting node-info via the API (`?force_ntp_check` query flag) (CO-325)
2323

24-
- The API provides an endpoint to retrieve basic statistics on the UTxO distribution of a wallet
24+
- The API provides an endpoint to retrieve basic statistics on the UTxO distribution of a wallet
2525
(`/api/v1/wallets/{walletId}/statistics`). (CO-325)
2626

27-
- cardano-sl exposes a new package `x509` with tooling for defining a PKI infrastructure from
27+
- cardano-sl exposes a new package `x509` with tooling for defining a PKI infrastructure from
2828
pure Haskell. This is basically an export of the internals of the tool `cardano-sl-x509-generate` (CO-387)
2929

3030

@@ -50,8 +50,8 @@
5050
- **[API BREAKING CHANGE]** The behavior of `/api/v1/addresses/{address}` has been adjusted to reflect more accurately
5151
the meaning of ownership regarding addresses.
5252
The previous version of this endpoint failed with an HTTP error when the given address was unknown to the wallet.
53-
This was misleading since an address that is unknown to the wallet may still belong to the wallet. To reflect this,
54-
the V1 endpoint does not fail anymore as it used to when an address is not recognised and returns instead a new field
53+
This was misleading since an address that is unknown to the wallet may still belong to the wallet. To reflect this,
54+
the V1 endpoint does not fail anymore as it used to when an address is not recognised and returns instead a new field
5555
'is-ours' which indicates either that an address is ours, or that it is 'not-recognised'. (CBR-401)
5656

5757
### Improvements
@@ -62,13 +62,15 @@
6262

6363
- Small refactor of wallet Errors implementation to be more maintainable (CBR-26)
6464

65-
- Content-Type parser is now more lenient and accepts `application/json`, `application/json;charset=utf-8` and
65+
- Content-Type parser is now more lenient and accepts `application/json`, `application/json;charset=utf-8` and
6666
no Content-Type at all (defaulting to `application/json`).
6767

6868
- The codebase now relies on the package `cryptonite` (instead of `ed25519`) for Ed25519 implementation (CO-325)
6969

7070
- **[API BREAKING CHANGE]** Improve diagnostic for `NotEnoughMoney` error (CBR-461)
7171

72+
- When Content-Type's main MIME-type cannot fall back to 'application/json' then UnsupportedMimeTypeError is returned
73+
7274
### Specifications
7375

7476
### Documentation

pkgs/default.nix

+2
Original file line numberDiff line numberDiff line change
@@ -18051,6 +18051,7 @@ license = stdenv.lib.licenses.mit;
1805118051
, beam-migrate
1805218052
, beam-sqlite
1805318053
, bifunctors
18054+
, binary
1805418055
, bytestring
1805518056
, cardano-crypto
1805618057
, cardano-sl
@@ -18176,6 +18177,7 @@ beam-core
1817618177
beam-migrate
1817718178
beam-sqlite
1817818179
bifunctors
18180+
binary
1817918181
bytestring
1818018182
cardano-crypto
1818118183
cardano-sl

wallet-new/cardano-sl-wallet-new.cabal

+1
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ library
167167
ghc-options: -Wall
168168

169169
build-depends: base
170+
, binary
170171
, acid-state
171172
, aeson
172173
, aeson-options

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

+35-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module Cardano.Wallet.API.Response (
77
, ResponseStatus(..)
88
, WalletResponse(..)
99
, JSONValidationError(..)
10+
, UnsupportedMimeTypeError(..)
1011
-- * Generating responses for collections
1112
, respondWith
1213
, fromSlice
@@ -34,7 +35,7 @@ import Formatting (bprint, build, (%))
3435
import qualified Formatting.Buildable
3536
import Generics.SOP.TH (deriveGeneric)
3637
import GHC.Generics (Generic)
37-
import Servant (err400)
38+
import Servant (err400, err415)
3839
import Servant.API.ContentTypes (Accept (..), JSON, MimeRender (..),
3940
MimeUnrender (..), OctetStream)
4041
import Test.QuickCheck
@@ -269,3 +270,36 @@ instance HasDiagnostic JSONValidationError where
269270
instance ToServantError JSONValidationError where
270271
declareServantError _ =
271272
err400
273+
274+
275+
newtype UnsupportedMimeTypeError
276+
= UnsupportedMimeTypePresent Text
277+
deriving (Eq, Show, Generic)
278+
279+
deriveGeneric ''UnsupportedMimeTypeError
280+
281+
instance ToJSON UnsupportedMimeTypeError where
282+
toJSON =
283+
jsendErrorGenericToJSON
284+
285+
instance FromJSON UnsupportedMimeTypeError where
286+
parseJSON =
287+
jsendErrorGenericParseJSON
288+
289+
instance Exception UnsupportedMimeTypeError
290+
291+
instance Arbitrary UnsupportedMimeTypeError where
292+
arbitrary =
293+
pure (UnsupportedMimeTypePresent "Delivered MIME-type is not supported.")
294+
295+
instance Buildable UnsupportedMimeTypeError where
296+
build (UnsupportedMimeTypePresent txt) =
297+
bprint build txt
298+
299+
instance HasDiagnostic UnsupportedMimeTypeError where
300+
getDiagnosticKey _ =
301+
"mimeContentTypeError"
302+
303+
instance ToServantError UnsupportedMimeTypeError where
304+
declareServantError _ =
305+
err415

wallet-new/src/Cardano/Wallet/API/V1/Swagger.hs

+5-2
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,9 @@ $errors
376376
-- 'JSONValidationError'
377377
, mkRow fmtErr $ JSONValidationFailed "Expected String, found Null."
378378

379+
-- 'UnsupportedMimeTypeError'
380+
, mkRow fmtErr $ UnsupportedMimeTypePresent "Expected Content-Type's main MIME-type to be 'application/json'."
381+
379382
-- TODO 'MnemonicError' ?
380383
]
381384
mkRow fmt err = T.intercalate "|" (fmt err)
@@ -860,8 +863,8 @@ curl -X POST \
860863
--cacert ./scripts/tls-files/ca.crt \
861864
--cert ./scripts/tls-files/client.pem \
862865
-d '{
863-
"walletId": "Ae2tdPwUPE...V3AVTnqGZ4",
864-
"accountIndex": 2147483648
866+
"walletId": "Ae2tdPwUPE...V3AVTnqGZ4",
867+
"accountIndex": 2147483648
865868
}'
866869
```
867870

wallet-new/src/Cardano/Wallet/Action.hs

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import Cardano.Wallet.Server.CLI (NewWalletBackendParams,
2929
getFullMigrationFlag, getWalletDbOptions, walletDbPath,
3030
walletRebuildDb)
3131
import Cardano.Wallet.Server.Middlewares (throttleMiddleware,
32-
withDefaultHeader)
32+
unsupportedMimeTypeMiddleware, withDefaultHeader)
3333
import qualified Cardano.Wallet.Server.Plugins as Plugins
3434
import Cardano.Wallet.WalletLayer (PassiveWalletLayer)
3535
import qualified Cardano.Wallet.WalletLayer.Kernel as WalletLayer.Kernel
@@ -88,6 +88,7 @@ actionWithWallet params genesisConfig walletConfig txpConfig ntpConfig nodeParam
8888
-- Throttle requests.
8989
[ throttleMiddleware (ccThrottle walletConfig)
9090
, withDefaultHeader Headers.applicationJson
91+
, unsupportedMimeTypeMiddleware
9192
])
9293

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

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

+27-3
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,25 @@ module Cardano.Wallet.Server.Middlewares
77
( withMiddlewares
88
, throttleMiddleware
99
, withDefaultHeader
10+
, unsupportedMimeTypeMiddleware
1011
) where
1112

12-
import Universum
13+
import Universum hiding (toStrict)
1314

1415
import Data.Aeson (encode)
16+
import Data.Binary.Builder (fromByteString)
17+
import Data.ByteString.Lazy (toStrict)
1518
import qualified Data.List as List
1619
import Network.HTTP.Types.Header (Header)
1720
import Network.HTTP.Types.Method (methodPatch, methodPost, methodPut)
18-
import Network.Wai (Application, Middleware, ifRequest,
19-
requestHeaders, requestMethod, responseLBS)
21+
import Network.HTTP.Types.Status (status415)
22+
import Network.Wai (Application, Middleware, Response, ifRequest,
23+
modifyResponse, requestHeaders, requestMethod,
24+
responseBuilder, responseLBS, responseStatus)
2025
import qualified Network.Wai.Middleware.Throttle as Throttle
2126

27+
28+
import Cardano.Wallet.API.Response (UnsupportedMimeTypeError (..))
2229
import Cardano.Wallet.API.V1.Headers (applicationJson)
2330
import qualified Cardano.Wallet.API.V1.Types as V1
2431

@@ -29,6 +36,23 @@ import Pos.Launcher.Configuration (ThrottleSettings (..))
2936
withMiddlewares :: [Middleware] -> Application -> Application
3037
withMiddlewares = flip $ foldr ($)
3138

39+
unsupportedMimeTypeMiddleware :: Middleware
40+
unsupportedMimeTypeMiddleware =
41+
modifyResponse responseModifier
42+
where
43+
responseModifier :: Response -> Response
44+
responseModifier r
45+
| responseStatus r == status415 =
46+
responseBuilder status415
47+
[ ("Content-Type", "application/json") ]
48+
( fromByteString .
49+
toStrict .
50+
encode $
51+
UnsupportedMimeTypePresent "The API expects the Content-Type's main MIME-type to be 'application/json'"
52+
)
53+
| otherwise = r
54+
55+
3256
-- | Only apply a @Middleware@ to request with bodies (we don't consider
3357
-- "DELETE" as one of them).
3458
ifRequestWithBody :: Middleware -> Middleware

wallet-new/test/MarshallingSpec.hs

+3-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ import Test.Pos.Core.Arbitrary ()
4040

4141
import Cardano.Wallet.API.Indices
4242
import Cardano.Wallet.API.Request.Pagination (Page, PerPage)
43-
import Cardano.Wallet.API.Response (JSONValidationError)
43+
import Cardano.Wallet.API.Response (JSONValidationError,
44+
UnsupportedMimeTypeError)
4445
import Cardano.Wallet.API.V1.Migration.Types (Migrate (..),
4546
MigrationError)
4647
import Cardano.Wallet.API.V1.Types
@@ -75,6 +76,7 @@ spec = parallel $ describe "Marshalling & Unmarshalling" $ do
7576
aesonRoundtripProp @TransactionStatus Proxy
7677
aesonRoundtripProp @WalletError Proxy
7778
aesonRoundtripProp @JSONValidationError Proxy
79+
aesonRoundtripProp @UnsupportedMimeTypeError Proxy
7880
aesonRoundtripProp @MigrationError Proxy
7981
aesonRoundtripProp @WalletId Proxy
8082
aesonRoundtripProp @Wallet Proxy

wallet-new/test/WalletNewJson.hs

+11-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ import Universum
66

77
import Hedgehog (Property)
88

9-
import Cardano.Wallet.API.Response (JSONValidationError (..))
9+
import Cardano.Wallet.API.Response (JSONValidationError (..),
10+
UnsupportedMimeTypeError (..))
1011
import Cardano.Wallet.API.V1.Migration.Types (MigrationError (..))
1112
import Cardano.Wallet.API.V1.Swagger.Example (genExample)
1213
import Cardano.Wallet.API.V1.Types (ErrNotEnoughMoney (..), V1 (..),
@@ -165,3 +166,12 @@ golden_JSONValidationError_JSONValidationFailed =
165166
goldenTestJSON
166167
(JSONValidationFailed "test")
167168
"test/golden/JSONValidationError_JSONValidationFailed"
169+
170+
-------------------------------------------------------------------------------
171+
-- UnsupportedMimeTypeError
172+
-------------------------------------------------------------------------------
173+
golden_UnsupportedMimeTypeError_UnsupportedMimeTypePresent :: Property
174+
golden_UnsupportedMimeTypeError_UnsupportedMimeTypePresent =
175+
goldenTestJSON
176+
(UnsupportedMimeTypePresent "test")
177+
"test/golden/UnsupportedMimeTypeError_UnsupportedMimeTypePresent"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"status":"error","diagnostic":{"mimeContentTypeError":"test"},"message":"UnsupportedMimeTypePresent"}

0 commit comments

Comments
 (0)