restman 0.7.5.1 → 0.7.6.0
raw patch · 3 files changed
+164/−14 lines, 3 filesdep +aeson-prettydep +timenew-component:exe:restman-echo
Dependencies added: aeson-pretty, time
Files
- CHANGELOG.md +13/−0
- echo/Main.hs +108/−0
- restman.cabal +43/−14
CHANGELOG.md view
@@ -1,3 +1,16 @@+# v7.6.0 (2026-05-14)++## ✨ New Features+- [`0ff2462`](https://gitlab.com/krakrjak/restman/-/commit/0ff2462) ✨ Add Echo Server For Manual Testing ++## 🐛 Bug Fixes++## 🏗️ Architecture Changes++## 📝 Administrivia Changes+- [`46e1928`](https://gitlab.com/krakrjak/restman/-/commit/46e1928) 📝 Ensure Haddocks are uploaded to Hackage +- [`193918a`](https://gitlab.com/krakrjak/restman/-/commit/193918a) 📝 UseStack for Documentation Generation+ # v7.5.1 (2026-05-04) ## ✨ New Features
+ echo/Main.hs view
@@ -0,0 +1,108 @@+{-# language OverloadedStrings #-}+-- | Standalone diagnostic echo server for local restman testing.+--+-- Accepts any HTTP request and responds with a JSON object reflecting+-- the method, path, query string, request headers, and body — identical+-- schema to the in-process 'HTTP.EchoServer' used by the test suite.+--+-- Usage:+-- stack run restman-echo --flag restman:echo-server+-- PORT=9000 stack run restman-echo --flag restman:echo-server+--+-- Every incoming request is pretty-printed to stdout, including a UTC+-- timestamp, so both sides of a request/response cycle can evaluate+-- what actually arrived.+module Main (main) where++import Data.Aeson (encode, object, (.=))+import Data.Aeson.Encode.Pretty (encodePretty)+import qualified Data.ByteString.Lazy as BL+import qualified Data.ByteString.Lazy.Char8 as BLC8+import qualified Data.CaseInsensitive as CI+import Data.Map.Strict (Map)+import qualified Data.Map.Strict as Map+import qualified Data.Text as T+import qualified Data.Text.Encoding as TE+import Data.Time.Clock (getCurrentTime)+import Network.HTTP.Types (status200)+import Network.Wai+ ( Application+ , rawPathInfo+ , rawQueryString+ , requestHeaders+ , requestMethod+ , responseLBS+ , strictRequestBody+ )+import Network.Wai.Handler.Warp (Port, run)+import System.Environment (lookupEnv)+import System.IO (hFlush, stdout)++-- | Build the echo payload — identical schema to HTTP.EchoServer.+buildPayload+ :: T.Text -- ^ method+ -> T.Text -- ^ path+ -> T.Text -- ^ query string (including leading '?')+ -> Map T.Text T.Text -- ^ lowercased headers+ -> T.Text -- ^ body+ -> BL.ByteString+buildPayload method path query hdrs body =+ encode $ object+ [ "method" .= method+ , "path" .= path+ , "query" .= query+ , "headers" .= hdrs+ , "body" .= body+ ]++-- | Log a received request to stdout in pretty-printed JSON, with a+-- UTC timestamp in the log entry (timestamp is *not* included in the+-- HTTP response body so the schema stays compatible with EchoServer).+logRequest+ :: T.Text -- ^ method+ -> T.Text -- ^ path+ -> T.Text -- ^ query string+ -> Map T.Text T.Text -- ^ lowercased headers+ -> T.Text -- ^ body+ -> IO ()+logRequest method path query hdrs body = do+ ts <- getCurrentTime+ let logEntry = encodePretty $ object+ [ "timestamp" .= show ts+ , "method" .= method+ , "path" .= path+ , "query" .= query+ , "headers" .= hdrs+ , "body" .= body+ ]+ BLC8.putStrLn logEntry+ putStrLn "\x2192 200 OK"+ hFlush stdout++-- | WAI application: log the request then echo it back as compact JSON.+echoApp :: Application+echoApp req respond = do+ rawBody <- strictRequestBody req+ let method = TE.decodeUtf8 (requestMethod req)+ path = TE.decodeUtf8 (rawPathInfo req)+ query = TE.decodeUtf8 (rawQueryString req)+ hdrs = Map.fromList+ [ (TE.decodeUtf8 (CI.foldedCase k), TE.decodeUtf8 v)+ | (k, v) <- requestHeaders req+ ] :: Map T.Text T.Text+ bodyTxt = TE.decodeUtf8 (BL.toStrict rawBody)+ logRequest method path query hdrs bodyTxt+ let payload = buildPayload method path query hdrs bodyTxt+ respond $ responseLBS status200+ [("Content-Type", "application/json")]+ payload++-- | Read PORT from the environment (default 8080) and run the server.+main :: IO ()+main = do+ portStr <- lookupEnv "PORT"+ let port = maybe 8080 read portStr :: Port+ putStrLn $ "restman-echo listening on port " <> show port+ putStrLn "(press Ctrl-C to stop)\n"+ hFlush stdout+ run port echoApp
restman.cabal view
@@ -1,22 +1,22 @@-cabal-version: 1.12-name: restman-version: 0.7.5.1-license: BSD2-license-file: LICENSE-copyright: Zac Slade or Boyd Stephen Smith Jr, 2024-maintainer: krakrjak@gmail.com, boyd.stephen.smith.jr@gmail.com-author: Zac Slade-homepage: https://gitlab.com/krakrjak/restman#readme-bug-reports: https://gitlab.com/krakrjak/restman/issues-synopsis: Web request TUI program.+cabal-version: 3.0+name: restman+version: 0.7.6.0+license: BSD-2-Clause+license-file: LICENSE+copyright: Zac Slade or Boyd Stephen Smith Jr, 2024+maintainer: krakrjak@gmail.com, boyd.stephen.smith.jr@gmail.com+author: Zac Slade+homepage: https://gitlab.com/krakrjak/restman#readme+bug-reports: https://gitlab.com/krakrjak/restman/issues+synopsis: Web request TUI program. description: A Brick-based TUI HTTP client powered by wreq. restman lets you compose and send HTTP requests from the terminal, with support for custom methods, headers, and inline syntax-highlighted response rendering via Skylighting. -category: Web-build-type: Simple-extra-source-files:+category: Web+build-type: Simple+extra-doc-files: README.md CHANGELOG.md @@ -24,6 +24,11 @@ type: git location: https://gitlab.com/krakrjak/restman +flag echo-server+ description: Build the standalone restman-echo diagnostic server+ default: False+ manual: True+ library exposed-modules: HTTP.Client@@ -34,6 +39,7 @@ hs-source-dirs: src other-modules: Paths_restman+ autogen-modules: Paths_restman default-language: GHC2024 ghc-options: -Wall build-depends:@@ -66,6 +72,7 @@ TUI Paths_restman + autogen-modules: Paths_restman default-language: GHC2024 ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall build-depends:@@ -82,6 +89,27 @@ utf8-string >=1.0.2 && <1.1, wreq >=0.5.4.4 && <0.6 +executable restman-echo+ main-is: Main.hs+ hs-source-dirs: echo+ default-language: GHC2024+ ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall+ build-depends:+ base >=4.7 && <5,+ aeson >=2.2.4.1 && <2.3,+ aeson-pretty >=0.8.10 && <0.9,+ bytestring >=0.12.2.0 && <0.13,+ case-insensitive >=1.2.1.0 && <1.3,+ containers >=0.7 && <0.8,+ http-types >=0.12.4 && <0.13,+ text >=2.1.3 && <2.2,+ time >=1.12.2 && <1.13,+ wai >=3.2.4 && <3.3,+ warp >=3.4.9 && <3.5++ if !flag(echo-server)+ buildable: False+ test-suite restman-test type: exitcode-stdio-1.0 main-is: Spec.hs@@ -100,6 +128,7 @@ Props.TypesProps Paths_restman + autogen-modules: Paths_restman default-language: GHC2024 ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall build-depends: