ngx-export-tools-extra 0.3.0.0 → 0.3.1.0
raw patch · 3 files changed
+52/−25 lines, 3 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ NgxExport.Tools.Subrequest: instance GHC.Read.Read NgxExport.Tools.Subrequest.SubrequestConf
+ NgxExport.Tools.Subrequest: subrequestWithRead :: ByteString -> IO ByteString
Files
- Changelog.md +5/−0
- NgxExport/Tools/Subrequest.hs +46/−24
- ngx-export-tools-extra.cabal +1/−1
Changelog.md view
@@ -1,3 +1,8 @@+### 0.3.1.0++- Added function *subrequestWithRead* and an asynchronous variable handler of+ the same name.+ ### 0.3.0.0 - Added module *NgxExport.Tools.Subrequest* for making HTTP (sub)requests
NgxExport/Tools/Subrequest.hs view
@@ -21,17 +21,18 @@ -- * Making HTTP subrequests -- $makingHTTPSubrequests subrequest+ ,subrequestWithRead ) where import NgxExport import NgxExport.Tools import Network.HTTP.Client+import Network.HTTP.Types import Data.ByteString (ByteString)+import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as L-import qualified Data.Text as T import qualified Data.Text.Encoding as T-import Data.Text (Text) import Data.CaseInsensitive (mk) import Data.Aeson import Control.Arrow@@ -43,7 +44,8 @@ -- Using asynchronous variable handlers and services together with the HTTP -- client from "Network.HTTP.Client" allows making HTTP subrequests easily. -- This module provides such functionality by exporting asynchronous variable--- handler __/subrequest/__ and function 'subrequest' to build custom handlers.+-- handlers __/subrequest/__ and __/subrequestWithRead/__, and functions+-- 'subrequest' and 'subrequestWithRead' to build custom handlers. -- -- Below is a simple example. --@@ -106,7 +108,7 @@ -- \"headers\": [[\"Custom-Header\", \"$arg_a\"]]}\'; -- -- if ($hs_subrequest = \'\') {--- echo_status 500;+-- echo_status 404; -- echo \"Failed to perform subrequest\"; -- } --@@ -165,10 +167,10 @@ -- > In backend, Custom-Header is 'Value' -- -- Let's do a nasty thing. By injecting a comma into the argument /a/ we shall--- break parsing JSON.+-- break JSON parsing. -- -- > $ curl -D- 'http://localhost:8010/?a=Value"'--- > HTTP/1.1 500 Internal Server Error+-- > HTTP/1.1 404 Not Found -- > Server: nginx/1.17.9 -- > Date: Mon, 30 Mar 2020 14:42:42 GMT -- > Content-Type: application/octet-stream@@ -177,41 +179,38 @@ -- > -- > Failed to perform subrequest -type ReqHeaders = [(Text, Text)]- data SubrequestParseError = SubrequestParseError deriving Show+ instance Exception SubrequestParseError data SubrequestConf =- SubrequestConf { srMethod :: Text+ SubrequestConf { srMethod :: ByteString , srUri :: String- , srBody :: Text- , srHeaders :: ReqHeaders- }+ , srBody :: ByteString+ , srHeaders :: RequestHeaders+ } deriving Read+ instance FromJSON SubrequestConf where parseJSON = withObject "SubrequestConf" $ \o -> do- srMethod <- o .:? "method" .!= "GET"+ srMethod <- maybe "GET" T.encodeUtf8 <$> o .:? "method" srUri <- o .: "uri"- srBody <- o .:? "body" .!= ""- srHeaders <- o .:? "headers" .!= []+ srBody <- maybe "" T.encodeUtf8 <$> o .:? "body"+ srHeaders <- map (mk . T.encodeUtf8 *** T.encodeUtf8) <$>+ o .:? "headers" .!= [] return SubrequestConf {..} doSubrequest :: SubrequestConf -> IO L.ByteString doSubrequest SubrequestConf {..} = do req <- parseUrlThrow srUri- let req' = if T.null srMethod+ let req' = if B.null srMethod then req- else req { method = T.encodeUtf8 srMethod }- req'' = if T.null srBody+ else req { method = srMethod }+ req'' = if B.null srBody then req'- else req' { requestBody =- RequestBodyBS $ T.encodeUtf8 srBody }+ else req' { requestBody = RequestBodyBS srBody } req''' = if null srHeaders then req''- -- TODO: implement caching of frequent header values- else req'' { requestHeaders =- map (mk . T.encodeUtf8 *** T.encodeUtf8)- srHeaders }+ else req'' { requestHeaders = srHeaders } responseBody <$> httpLbs req''' httpManager httpManager :: Manager@@ -250,4 +249,27 @@ readFromByteStringAsJSON @SubrequestConf ngxExportAsyncIOYY 'subrequest++-- | Makes an HTTP request.+--+-- Behaves exactly as 'subrequest' except it parses Haskell terms representing+-- /SubrequestConf/ with 'read'.+--+-- An example of a subrequest configuration:+--+-- > SubrequestConf { srMethod = "GET"+-- > , srUri = "http://127.0.0.1/subreq"}+-- > , srBody = ""+-- > , srHeaders = [("Header1", "Value1"), ("Header2", "Value2")]+-- > }+--+-- Notice that unlike JSON parsing, fields of /SubrequestConf/ are not+-- omittable and must be listed in the order shown in the example.+subrequestWithRead+ :: ByteString -- ^ Subrequest configuration+ -> IO L.ByteString+subrequestWithRead = maybe (throwIO SubrequestParseError) doSubrequest .+ readFromByteString @SubrequestConf++ngxExportAsyncIOYY 'subrequestWithRead
ngx-export-tools-extra.cabal view
@@ -1,5 +1,5 @@ name: ngx-export-tools-extra-version: 0.3.0.0+version: 0.3.1.0 synopsis: More extra tools for Nginx haskell module description: More extra tools for <https://github.com/lyokha/nginx-haskell-module Nginx haskell module>.