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

Commit 7de5853

Browse files
authored
Merge branch 'develop' into matt/node-api-docs
2 parents 6952a94 + b860f2a commit 7de5853

File tree

10 files changed

+238
-10
lines changed

10 files changed

+238
-10
lines changed

cabal.project.freeze

+1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ constraints: Cabal ==2.2.0.1,
7777
http-client ==0.5.13.1,
7878
http-client-tls ==0.3.5.3,
7979
http-conduit ==2.3.2,
80+
http-media ==0.7.1.3,
8081
http-types ==0.12.2,
8182
insert-ordered-containers ==0.2.1.0,
8283
ip ==1.3.0,

cluster/cardano-sl-cluster.cabal

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ library
3232
, cardano-sl-core
3333
, cardano-sl-infra
3434
, cardano-sl-networking
35+
, cardano-sl-node
3536
, cardano-sl-util
3637
, cardano-sl-x509
3738
, cardano-wallet

cluster/src/Cardano/Cluster/Environment.hs

+2-2
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ import Cardano.Cluster.Util (getsModify, indexedForM, indexedForM_,
4747
ntwrkAddrToString, rotations, unsafeBoolFromString,
4848
unsafeElemIndex, unsafeNetworkAddressFromString,
4949
unsafeSeverityFromString, (|>))
50-
import Cardano.Wallet.Client.Http (WalletClient, mkHttpClient,
51-
mkHttpsManagerSettings, newManager)
50+
import Cardano.Node.Manager (mkHttpsManagerSettings, newManager)
51+
import Cardano.Wallet.Client.Http (WalletClient, mkHttpClient)
5252
import Cardano.X509.Configuration (CertConfiguration (..),
5353
CertDescription (..), DirConfiguration (..),
5454
ServerConfiguration (..), TLSConfiguration (..),

lib/src/Pos/Util/Jsend.hs

-2
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,6 @@ instance GDiagnosticToJSON U1 where
132132

133133
data ResponseStatus =
134134
SuccessStatus
135-
| FailStatus
136135
| ErrorStatus
137136
deriving (Show, Eq, Ord, Enum, Bounded)
138137

@@ -153,5 +152,4 @@ instance ToSchema ResponseStatus where
153152

154153
instance Buildable ResponseStatus where
155154
build SuccessStatus = "success"
156-
build FailStatus = "fail"
157155
build ErrorStatus = "error"

lib/src/Pos/Web/Types.hs

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ module Pos.Web.Types
88

99
import Universum
1010

11-
import Data.Aeson.TH (defaultOptions, deriveToJSON)
11+
import Data.Aeson.TH (defaultOptions, deriveJSON)
1212

1313
-- | Stages of SSC.
1414
-- Also called GodTossing algorithm.
@@ -23,7 +23,7 @@ data SscStage
2323
| SharesStage
2424
| OrdinaryStage
2525

26-
deriveToJSON defaultOptions ''SscStage
26+
deriveJSON defaultOptions ''SscStage
2727

2828
-- | TLS Transport Layer Security file paths.
2929
data TlsParams = TlsParams
@@ -36,4 +36,4 @@ data TlsParams = TlsParams
3636
newtype CConfirmedProposalState = CConfirmedProposalState Text
3737
deriving (Show, Generic, Buildable)
3838

39-
deriveToJSON defaultOptions ''CConfirmedProposalState
39+
deriveJSON defaultOptions ''CConfirmedProposalState

node/cardano-sl-node.cabal

+11
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ library
2020
, aeson
2121
, async
2222
, bytestring
23+
, connection
2324
, cardano-sl
2425
, cardano-sl-chain
2526
, cardano-sl-core
@@ -28,22 +29,32 @@ library
2829
, cardano-sl-infra
2930
, cardano-sl-networking
3031
, cardano-sl-util
32+
, cardano-sl-x509
3133
, data-default
34+
, http-client
35+
, http-client-tls
36+
, http-media
3237
, http-types
3338
, lens
39+
, servant-client
3440
, servant-server
3541
, servant-swagger
3642
, servant-swagger-ui
3743
, stm
3844
, swagger2
3945
, text
4046
, time-units
47+
, tls
4148
, universum
4249
, wai
4350
, warp
51+
, x509
52+
, x509-store
4453

4554
exposed-modules: Cardano.Node.API
4655
Cardano.Node.API.Swagger
56+
Cardano.Node.Client
57+
Cardano.Node.Manager
4758

4859
other-modules: Paths_cardano_sl_node
4960

node/src/Cardano/Node/API.hs

+3-3
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ import qualified Pos.Web as Legacy
5353
import Cardano.Node.API.Swagger (forkDocServer)
5454

5555
type NodeV1Api
56-
= "v1"
57-
:> ( Node.API
58-
:<|> Legacy.NodeApi
56+
= "api" :> "v1" :>
57+
( Node.API
58+
:<|> Legacy.NodeApi
5959
)
6060

6161
nodeV1Api :: Proxy NodeV1Api

node/src/Cardano/Node/Client.hs

+125
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
{-# LANGUAGE DeriveGeneric #-}
2+
{-# LANGUAGE LambdaCase #-}
3+
4+
module Cardano.Node.Client
5+
( -- Node Client
6+
NodeClient(..)
7+
, ClientError(..)
8+
, fromServantError
9+
10+
-- * HTTP instance
11+
, NodeHttpClient
12+
, mkHttpClient
13+
) where
14+
15+
import Universum
16+
17+
import Data.Aeson (FromJSON)
18+
import qualified Data.Aeson as Aeson
19+
import Network.HTTP.Client (Manager)
20+
import Network.HTTP.Media.MediaType (MediaType)
21+
import Servant ((:<|>) (..))
22+
import Servant.Client (BaseUrl (..), ClientEnv (..), ClientM,
23+
GenResponse (..), Response, ServantError, client,
24+
runClientM)
25+
import qualified Servant.Client as Servant
26+
27+
import Cardano.Node.API (nodeV1Api)
28+
import Pos.Chain.Txp (Utxo)
29+
import Pos.Node.API (ForceNtpCheck, NodeInfo, NodeSettings)
30+
import Pos.Util.Jsend (ResponseStatus (..))
31+
import Pos.Util.Servant (APIResponse (..))
32+
import Pos.Web.Types (CConfirmedProposalState)
33+
34+
35+
-- * Node Client
36+
37+
data NodeClient m
38+
= NodeClient
39+
{ getUtxo
40+
:: m Utxo
41+
42+
, getConfirmedProposals
43+
:: m [CConfirmedProposalState]
44+
45+
, getNodeSettings
46+
:: m NodeSettings
47+
48+
, getNodeInfo
49+
:: ForceNtpCheck
50+
-> m NodeInfo
51+
52+
, applyUpdate
53+
:: m ()
54+
55+
, postponeUpdate
56+
:: m ()
57+
} deriving (Generic)
58+
59+
60+
data ClientError a
61+
= KnownError a
62+
| DecodeFailure Text Response
63+
| UnsupportedContentType MediaType Response
64+
| InvalidContentTypeHeader Response
65+
| ConnectionError Text
66+
deriving (Show, Generic, Eq)
67+
instance Exception a => Exception (ClientError a)
68+
69+
fromServantError :: FromJSON a => ServantError -> ClientError a
70+
fromServantError = \case
71+
Servant.FailureResponse r@(Response _ _ _ body) ->
72+
case Aeson.decode body of
73+
Just (APIResponse a ErrorStatus _) ->
74+
KnownError a
75+
Just _ ->
76+
DecodeFailure "API failed with non-error response ?!?" r
77+
Nothing ->
78+
DecodeFailure "Invalid / Non-JSEnd API Error Response" r
79+
Servant.DecodeFailure t r ->
80+
DecodeFailure t r
81+
Servant.UnsupportedContentType m r ->
82+
UnsupportedContentType m r
83+
Servant.InvalidContentTypeHeader r ->
84+
InvalidContentTypeHeader r
85+
Servant.ConnectionError t ->
86+
ConnectionError t
87+
88+
89+
-- * HTTP Instance
90+
91+
type NodeHttpClient = NodeClient (ExceptT (ClientError ()) IO)
92+
93+
mkHttpClient
94+
:: BaseUrl
95+
-> Manager
96+
-> NodeHttpClient
97+
mkHttpClient baseUrl manager = NodeClient
98+
{ getUtxo =
99+
run getUtxoR
100+
, getConfirmedProposals =
101+
run getConfirmedProposalsR
102+
, getNodeSettings =
103+
fmap wrData $ run getNodeSettingsR
104+
, getNodeInfo =
105+
fmap wrData . run . getNodeInfoR
106+
, applyUpdate =
107+
void $ run applyUpdateR
108+
, postponeUpdate =
109+
void $ run postponeUpdateR
110+
}
111+
where
112+
run :: forall a. ClientM a -> ExceptT (ClientError ()) IO a
113+
run = ExceptT
114+
. fmap (first fromServantError)
115+
. flip runClientM (ClientEnv manager baseUrl noCookieJar)
116+
117+
noCookieJar = Nothing
118+
119+
( getNodeSettingsR
120+
:<|> getNodeInfoR
121+
:<|> applyUpdateR
122+
:<|> postponeUpdateR
123+
):<|>( getUtxoR
124+
:<|> getConfirmedProposalsR
125+
) = client nodeV1Api

node/src/Cardano/Node/Manager.hs

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
{-# LANGUAGE ScopedTypeVariables #-}
2+
3+
module Cardano.Node.Manager
4+
( -- * Smart-constructors
5+
mkHttpManagerSettings
6+
, mkHttpsManagerSettings
7+
8+
-- * Re-exports, helpers to load X509 certificates and private key
9+
, credentialLoadX509
10+
, readSignedObject
11+
, newManager
12+
, Manager
13+
) where
14+
15+
import Universum
16+
17+
import Data.ByteString (ByteString)
18+
import Data.Default (Default (..))
19+
import Data.X509 (CertificateChain, SignedCertificate)
20+
import Data.X509.CertificateStore (makeCertificateStore)
21+
import Data.X509.Extra (validateDefaultWithIP)
22+
import Data.X509.File (readSignedObject)
23+
import Network.Connection (TLSSettings (..))
24+
import Network.HTTP.Client (Manager, ManagerSettings,
25+
defaultManagerSettings, newManager)
26+
import Network.HTTP.Client.TLS (mkManagerSettings)
27+
import Network.TLS (ClientHooks (..), ClientParams (..),
28+
Credentials (..), HostName, PrivKey, Shared (..),
29+
Supported (..), credentialLoadX509, noSessionManager)
30+
import Network.TLS.Extra.Cipher (ciphersuite_default)
31+
32+
type Port = ByteString
33+
34+
35+
mkHttpManagerSettings :: ManagerSettings
36+
mkHttpManagerSettings =
37+
defaultManagerSettings
38+
39+
40+
mkHttpsManagerSettings
41+
:: (HostName, Port) -- ^ Target server hostname & port
42+
-> [SignedCertificate] -- ^ CA certificate chain
43+
-> (CertificateChain, PrivKey) -- ^ (Client certificate, Client key)
44+
-> ManagerSettings
45+
mkHttpsManagerSettings serverId caChain credentials =
46+
mkManagerSettings tlsSettings sockSettings
47+
where
48+
sockSettings = Nothing
49+
tlsSettings = TLSSettings clientParams
50+
clientParams = ClientParams
51+
{ clientUseMaxFragmentLength = Nothing
52+
, clientServerIdentification = serverId
53+
, clientUseServerNameIndication = True
54+
, clientWantSessionResume = Nothing
55+
, clientShared = clientShared
56+
, clientHooks = clientHooks
57+
, clientSupported = clientSupported
58+
, clientDebug = def
59+
}
60+
clientShared = Shared
61+
{ sharedCredentials = Credentials [credentials]
62+
, sharedCAStore = makeCertificateStore caChain
63+
, sharedSessionManager = noSessionManager
64+
, sharedValidationCache = def
65+
}
66+
clientHooks = def
67+
{ onCertificateRequest = const . return . Just $ credentials
68+
, onServerCertificate = validateDefaultWithIP
69+
}
70+
clientSupported = def
71+
{ supportedCiphers = ciphersuite_default
72+
}

pkgs/default.nix

+20
Original file line numberDiff line numberDiff line change
@@ -14480,6 +14480,7 @@ license = stdenv.lib.licenses.mit;
1448014480
, cardano-sl-core
1448114481
, cardano-sl-infra
1448214482
, cardano-sl-networking
14483+
, cardano-sl-node
1448314484
, cardano-sl-util
1448414485
, cardano-sl-x509
1448514486
, cardano-wallet
@@ -14527,6 +14528,7 @@ cardano-sl-chain
1452714528
cardano-sl-core
1452814529
cardano-sl-infra
1452914530
cardano-sl-networking
14531+
cardano-sl-node
1453014532
cardano-sl-util
1453114533
cardano-sl-x509
1453214534
cardano-wallet
@@ -16099,16 +16101,22 @@ license = stdenv.lib.licenses.mit;
1609916101
, cardano-sl-networking
1610016102
, cardano-sl-util
1610116103
, cardano-sl-utxo
16104+
, cardano-sl-x509
16105+
, connection
1610216106
, containers
1610316107
, cpphs
1610416108
, data-default
1610516109
, hashable
1610616110
, hspec
16111+
, http-client
16112+
, http-client-tls
16113+
, http-media
1610716114
, http-types
1610816115
, HUnit
1610916116
, lens
1611016117
, mtl
1611116118
, QuickCheck
16119+
, servant-client
1611216120
, servant-server
1611316121
, servant-swagger
1611416122
, servant-swagger-ui
@@ -16117,10 +16125,13 @@ license = stdenv.lib.licenses.mit;
1611716125
, swagger2
1611816126
, text
1611916127
, time-units
16128+
, tls
1612016129
, universum
1612116130
, validation
1612216131
, wai
1612316132
, warp
16133+
, x509
16134+
, x509-store
1612416135
}:
1612516136
mkDerivation {
1612616137

@@ -16148,19 +16159,28 @@ cardano-sl-db
1614816159
cardano-sl-infra
1614916160
cardano-sl-networking
1615016161
cardano-sl-util
16162+
cardano-sl-x509
16163+
connection
1615116164
data-default
16165+
http-client
16166+
http-client-tls
16167+
http-media
1615216168
http-types
1615316169
lens
16170+
servant-client
1615416171
servant-server
1615516172
servant-swagger
1615616173
servant-swagger-ui
1615716174
stm
1615816175
swagger2
1615916176
text
1616016177
time-units
16178+
tls
1616116179
universum
1616216180
wai
1616316181
warp
16182+
x509
16183+
x509-store
1616416184
];
1616516185
executableHaskellDepends = [
1616616186
base

0 commit comments

Comments
 (0)