Skip to content

Commit

Permalink
API: Serve static files (#45)
Browse files Browse the repository at this point in the history
* API: Serve static files

* Add api/v1 prefix to endpoints

* Small patch to correct the parser for static files (#48)

* Fix build, add test for schema

---------

Co-authored-by: Christian Hoener zu Siederdissen <[email protected]>
  • Loading branch information
j-mueller and choener authored Jan 7, 2025
1 parent 1b526b7 commit a7b81ce
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 17 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci-compiled-scripts.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ jobs:
# git diff --quiet implies --exit-code
run: |
cabal run export-smart-tokens
cabal run write-openapi-schema -- generated/openapi/schema.json
git diff --quiet
20 changes: 10 additions & 10 deletions generated/openapi/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@
},
"openapi": "3.0.0",
"paths": {
"/healthcheck": {
"/api/v1/healthcheck": {
"get": {
"description": "Is the server alive?",
"responses": {
Expand All @@ -226,7 +226,7 @@
}
}
},
"/query/address/{address}": {
"/api/v1/query/address/{address}": {
"get": {
"description": "The user's receiving address for programmable tokens",
"parameters": [
Expand Down Expand Up @@ -258,7 +258,7 @@
}
}
},
"/query/all-funds": {
"/api/v1/query/all-funds": {
"get": {
"description": "Total value of all programmable tokens",
"responses": {
Expand All @@ -275,7 +275,7 @@
}
}
},
"/query/blacklist/{address}": {
"/api/v1/query/blacklist/{address}": {
"get": {
"description": "The list of addresses that have been blacklisted",
"parameters": [
Expand Down Expand Up @@ -310,7 +310,7 @@
}
}
},
"/query/global-params": {
"/api/v1/query/global-params": {
"get": {
"description": "The UTxO with the global parameters",
"responses": {
Expand All @@ -327,7 +327,7 @@
}
}
},
"/query/user-funds/{address}": {
"/api/v1/query/user-funds/{address}": {
"get": {
"description": "Total value locked in programmable token outputs addressed to the user",
"parameters": [
Expand Down Expand Up @@ -359,7 +359,7 @@
}
}
},
"/tx/programmable-token/blacklist": {
"/api/v1/tx/programmable-token/blacklist": {
"post": {
"description": "Add a credential to the blacklist",
"requestBody": {
Expand Down Expand Up @@ -388,7 +388,7 @@
}
}
},
"/tx/programmable-token/issue": {
"/api/v1/tx/programmable-token/issue": {
"post": {
"description": "Create some programmable tokens",
"requestBody": {
Expand Down Expand Up @@ -417,7 +417,7 @@
}
}
},
"/tx/programmable-token/seize": {
"/api/v1/tx/programmable-token/seize": {
"post": {
"description": "Seize a user's funds",
"requestBody": {
Expand Down Expand Up @@ -446,7 +446,7 @@
}
}
},
"/tx/programmable-token/transfer": {
"/api/v1/tx/programmable-token/transfer": {
"post": {
"description": "Transfer programmable tokens from one address to another",
"requestBody": {
Expand Down
5 changes: 3 additions & 2 deletions src/lib/Wst/Cli.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import Control.Monad.IO.Class (MonadIO (..))
import Convex.Wallet.Operator (OperatorConfigSigning)
import Convex.Wallet.Operator qualified as Operator
import Data.Functor.Identity (Identity)
import Data.Maybe (fromMaybe)
import Data.Proxy (Proxy)
import Data.String (IsString (..))
import Options.Applicative (customExecParser, disambiguate, helper, idm, info,
Expand Down Expand Up @@ -55,6 +56,6 @@ deploy config = do
pure ()

startServer :: (MonadIO m, MonadLogger m) => Env.CombinedEnv Proxy Identity Proxy Identity w -> Server.ServerArgs -> m ()
startServer env' serverArgs@ServerArgs{saPort} = do
logInfo $ "starting server" :# ["port" .= saPort]
startServer env' serverArgs@ServerArgs{saPort, saStaticFiles} = do
logInfo $ "starting server" :# ["port" .= saPort, "static_files" .= fromMaybe "(no static files)" saStaticFiles]
liftIO (Server.runServer env' serverArgs)
3 changes: 2 additions & 1 deletion src/lib/Wst/Cli/Command.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import Options.Applicative (CommandFields, Mod, Parser, ReadM, argument, auto,
command, eitherReader, fullDesc, help, info, long,
metavar, option, optional, progDesc, short,
subparser, value)
import Options.Applicative.Builder (strOption)
import Text.Read (readMaybe)
import Wst.Server (ServerArgs (..))

Expand Down Expand Up @@ -64,7 +65,7 @@ parseServerArgs :: Parser ServerArgs
parseServerArgs =
ServerArgs
<$> option auto (help "The port" <> value 8080 <> long "port" <> short 'p')
<*> optional (option auto (help "Folder to serve static files from" <> long "static-files"))
<*> optional (strOption (help "Folder to serve static files from" <> long "static-files"))

parseTxIn :: Parser TxIn
parseTxIn =
Expand Down
16 changes: 13 additions & 3 deletions src/lib/Wst/Server.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
module Wst.Server(
runServer,
ServerArgs(..),
CombinedAPI,
defaultServerArgs
) where

Expand All @@ -19,8 +20,9 @@ import Data.Data (Proxy (..))
import Network.Wai.Handler.Warp qualified as Warp
import PlutusTx.Prelude qualified as P
import Servant (Server, ServerT)
import Servant.API (NoContent (..), (:<|>) (..))
import Servant.API (NoContent (..), Raw, (:<|>) (..))
import Servant.Server (hoistServer, serve)
import Servant.Server.StaticFiles (serveDirectoryWebApp)
import SmartTokens.Types.PTokenDirectory (blnKey)
import Wst.App (WstApp, runWstAppServant)
import Wst.AppError (AppError)
Expand All @@ -34,6 +36,12 @@ import Wst.Server.Types (APIInEra, AddToBlacklistArgs (..), BuildTxAPI,
TextEnvelopeJSON (..),
TransferProgrammableTokenArgs (..))

-- | Rest API combined with a Raw endpoint
-- for static files
type CombinedAPI =
APIInEra
:<|> Raw

data ServerArgs =
ServerArgs
{ saPort :: !Int
Expand All @@ -49,8 +57,10 @@ defaultServerArgs =
}

runServer :: (Env.HasRuntimeEnv env, Env.HasDirectoryEnv env) => env -> ServerArgs -> IO ()
runServer env ServerArgs{saPort} = do
let app = serve (Proxy @APIInEra) (server env)
runServer env ServerArgs{saPort, saStaticFiles} = do
let app = case saStaticFiles of
Nothing -> serve (Proxy @APIInEra) (server env)
Just fp -> serve (Proxy @CombinedAPI) (server env :<|> serveDirectoryWebApp fp)
port = saPort
Warp.run port app

Expand Down
2 changes: 1 addition & 1 deletion src/lib/Wst/Server/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ import SmartTokens.Types.ProtocolParams (ProgrammableLogicGlobalParams)
import Wst.JSON.Utils qualified as JSON
import Wst.Offchain.Query (UTxODat (..))

type APIInEra = API C.ConwayEra
type APIInEra = "api" :> "v1" :> API C.ConwayEra

newtype TextEnvelopeJSON a = TextEnvelopeJSON{ unTextEnvelopeJSON :: a }

Expand Down

0 comments on commit a7b81ce

Please sign in to comment.