ngx-export-tools-extra 0.6.0.1 → 0.6.1.0
raw patch · 3 files changed
+91/−71 lines, 3 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- NgxExport.Tools.Subrequest: extractRequestStatusFromFullResponse :: ByteString -> ByteString
+ NgxExport.Tools.Subrequest: extractExceptionFromFullResponse :: ByteString -> ByteString
- NgxExport.Tools.Subrequest: contentFromFullResponse :: HashSet HeaderName -> Bool -> ByteString -> ContentHandlerResult
+ NgxExport.Tools.Subrequest: contentFromFullResponse :: HashSet HeaderName -> Bool -> (ByteString -> ByteString -> ByteString) -> ByteString -> ContentHandlerResult
Files
- Changelog.md +6/−0
- NgxExport/Tools/Subrequest.hs +84/−70
- ngx-export-tools-extra.cabal +1/−1
Changelog.md view
@@ -1,3 +1,9 @@+### 0.6.1.0++- Handler *extractRequestStatusFromFullResponse* was replaced with handler+ *extractExceptionFromFullResponse*. The new handler contains the error message+ if the subrequest was terminated by an exception.+ ### 0.6.0.0 - Build EDE module with *prettyprinter* automatically.
NgxExport/Tools/Subrequest.hs view
@@ -29,10 +29,10 @@ -- $gettingFullResponse ,makeSubrequestFull ,makeSubrequestFullWithRead- ,extractRequestStatusFromFullResponse ,extractStatusFromFullResponse ,extractHeaderFromFullResponse ,extractBodyFromFullResponse+ ,extractExceptionFromFullResponse -- * Forwarding full response data to the client -- $forwardingFullResponse ,notForwardableResponseHeaders@@ -60,7 +60,6 @@ import Data.CaseInsensitive hiding (map) import Data.Aeson import Data.Maybe-import Data.Word import Control.Arrow import Control.Exception import System.IO.Unsafe@@ -272,26 +271,28 @@ subrequestBody :: SubrequestConf -> IO L.ByteString subrequestBody = subrequest parseUrlThrow responseBody -type FullResponse = (Word8, Int, [(ByteString, ByteString)], L.ByteString)+type FullResponse = (Int, [(ByteString, ByteString)], L.ByteString, ByteString) subrequestFull :: SubrequestConf -> IO L.ByteString subrequestFull = handleAll . subrequest parseRequest buildResponse- where handleAll = handle $ \e -> return $ Binary.encode @FullResponse $- case fromException e of- Just (HttpExceptionRequest _ c) ->- case c of- Network.HTTP.Client.ResponseTimeout -> response502- ConnectionTimeout -> response502- ConnectionFailure _ -> response502- _ -> response500- _ -> response500- response500 = (2, 500, [], "")- response502 = (1, 502, [], "")+ where handleAll = handle $ \e -> do+ let msg = C8.pack $ show e+ response500 = (500, [], "", msg)+ response502 = (502, [], "", msg)+ return $ Binary.encode @FullResponse $+ case fromException e of+ Just (HttpExceptionRequest _ c) ->+ case c of+ Network.HTTP.Client.ResponseTimeout -> response502+ ConnectionTimeout -> response502+ ConnectionFailure _ -> response502+ _ -> response500+ _ -> response500 buildResponse r = let status = statusCode $ responseStatus r headers = map (first original) $ responseHeaders r body = responseBody r- in Binary.encode @FullResponse (0, status, headers, body)+ in Binary.encode @FullResponse (status, headers, body, "") httpManager :: Manager httpManager = unsafePerformIO $ newManager defaultManagerSettings@@ -456,11 +457,10 @@ -- status, headers and the body must be extracted using handlers -- __/extractStatusFromFullResponse/__, __/extractHeaderFromFullResponse/__, -- and __/extractBodyFromFullResponse/__ which are based on functions of the--- same name. Handler __/extractRequestStatusFromFullResponse/__ and the--- corresponding function can be used to extract the request status: /0/ means--- that the request was completed without technical errors, /1/ means that the--- request failed due to connection errors including timeouts, and /2/ means--- that the request failed due to other errors.+-- same name. Handler __/extractExceptionFromFullResponse/__ and the+-- corresponding function can be used to extract the error message if an+-- exception has happened while making the subrequest: the value is empty if+-- there was no exception. -- -- Let's extend our example with these handlers. --@@ -583,17 +583,18 @@ -- -- The same as 'makeSubrequest' except it returns a binary encoded response data -- whose parts must be extracted by handlers made of--- 'extractRequestStatusFromFullResponse', 'extractStatusFromFullResponse',--- 'extractHeaderFromFullResponse', and 'extractBodyFromFullResponse'. It also--- does not throw errors when HTTP status of the response is not /2xx/.--- Exported on the Nginx level by handler /makeSubrequestFull/.+-- 'extractStatusFromFullResponse', 'extractHeaderFromFullResponse',+-- 'extractBodyFromFullResponse', and 'extractExceptionFromFullResponse'. It+-- does not throw any exceptions outside. Exported on the Nginx level by handler+-- /makeSubrequestFull/. makeSubrequestFull :: ByteString -- ^ Subrequest configuration -> IO L.ByteString makeSubrequestFull =- maybe (return $ Binary.encode @FullResponse (2, 400, [], ""))- subrequestFull .- readFromByteStringAsJSON @SubrequestConf+ maybe (return $+ Binary.encode @FullResponse+ (400, [], "", "Unreadable subrequest data")+ ) subrequestFull . readFromByteStringAsJSON @SubrequestConf ngxExportAsyncIOYY 'makeSubrequestFull @@ -601,39 +602,21 @@ -- -- The same as 'makeSubrequestWithRead' except it returns a binary encoded -- response data whose parts must be extracted by handlers made of--- 'extractRequestStatusFromFullResponse', 'extractStatusFromFullResponse',--- 'extractHeaderFromFullResponse', and 'extractBodyFromFullResponse'. It also--- does not throw errors when HTTP status of the response is not /2xx/.--- Exported on the Nginx level by handler /makeSubrequestFullWithRead/.+-- 'extractStatusFromFullResponse', 'extractHeaderFromFullResponse',+-- 'extractBodyFromFullResponse', and 'extractExceptionFromFullResponse'. It+-- does not throw any exceptions outside. Exported on the Nginx level by handler+-- /makeSubrequestFullWithRead/. makeSubrequestFullWithRead :: ByteString -- ^ Subrequest configuration -> IO L.ByteString makeSubrequestFullWithRead =- maybe (return $ Binary.encode @FullResponse (2, 400, [], ""))- subrequestFull .- readFromByteString @SubrequestConf+ maybe (return $+ Binary.encode @FullResponse+ (400, [], "", "Unreadable subrequest data")+ ) subrequestFull . readFromByteString @SubrequestConf ngxExportAsyncIOYY 'makeSubrequestFullWithRead --- | Extracts the request status from an encoded response.------ Must be used to extract response data encoded by 'makeSubrequestFull' or--- 'makeSubrequestFullWithRead'. Exported on the Nginx level by handler--- /extractRequestStatusFromFullResponse/.------ The request status may be one of the following values:------ - /0/ — the request was completed without technical errors,--- - /1/ — the request failed due to connection errors including timeouts,--- - /2/ — the request failed due to other errors.-extractRequestStatusFromFullResponse- :: ByteString -- ^ Encoded HTTP response- -> L.ByteString-extractRequestStatusFromFullResponse = C8L.pack . show .- (\(a, _, _, _) -> a) . (Binary.decode @FullResponse) . L.fromStrict--ngxExportYY 'extractRequestStatusFromFullResponse- -- | Extracts the HTTP status from an encoded response. -- -- Must be used to extract response data encoded by 'makeSubrequestFull' or@@ -643,7 +626,7 @@ :: ByteString -- ^ Encoded HTTP response -> L.ByteString extractStatusFromFullResponse = C8L.pack . show .- (\(_, a, _, _) -> a) . (Binary.decode @FullResponse) . L.fromStrict+ (\(a, _, _, _) -> a) . Binary.decode @FullResponse . L.fromStrict ngxExportYY 'extractStatusFromFullResponse @@ -662,7 +645,7 @@ -> L.ByteString extractHeaderFromFullResponse v = let (h, b) = mk *** C8.tail $ C8.break ('|' ==) v- (_, _, hs, _) = Binary.decode @FullResponse $ L.fromStrict b+ (_, hs, _, _) = Binary.decode @FullResponse $ L.fromStrict b in maybe "" L.fromStrict $ lookup h $ map (first mk) hs ngxExportYY 'extractHeaderFromFullResponse@@ -676,20 +659,37 @@ :: ByteString -- ^ Encoded HTTP response -> L.ByteString extractBodyFromFullResponse =- (\(_, _, _, a) -> a) . (Binary.decode @FullResponse) . L.fromStrict+ (\(_, _, a, _) -> a) . Binary.decode @FullResponse . L.fromStrict ngxExportYY 'extractBodyFromFullResponse +-- | Extracts the exception from an encoded response.+--+-- Must be used to extract response data encoded by 'makeSubrequestFull' or+-- 'makeSubrequestFullWithRead'. Exported on the Nginx level by handler+-- /extractExceptionFromFullResponse/.+--+-- The empty value implies that there was no exception while making the+-- subrequest. Non-/2xx/ responses are not regarded as exceptions as well.+extractExceptionFromFullResponse+ :: ByteString -- ^ Encoded HTTP response+ -> L.ByteString+extractExceptionFromFullResponse = L.fromStrict .+ (\(_, _, _, a) -> a) . Binary.decode @FullResponse . L.fromStrict++ngxExportYY 'extractExceptionFromFullResponse+ -- $forwardingFullResponse -- -- Data encoded in the full response can be translated to 'ContentHandlerResult' -- and forwarded downstream to the client in directive /haskell_content/.--- Handler __/fromFullResponse/__ performs such a translation. Not all response--- headers are allowed being forwarded downstream, and thus the handler deletes--- response headers with names listed in set 'notForwardableResponseHeaders' as--- well as all headers with names starting with /X-Accel-/ before sending the--- response to the client. The set of not forwardable response headers can be--- customized in function 'contentFromFullResponse'.+-- Handlers __/fromFullResponse/__ and __/fromFullResponseWithException/__+-- perform such a translation. Not all response headers are allowed being+-- forwarded downstream, and thus the handler deletes response headers with+-- names listed in set 'notForwardableResponseHeaders' as well as all headers+-- with names starting with /X-Accel-/ before sending the response to the+-- client. The set of not forwardable response headers can be customized in+-- function 'contentFromFullResponse'. -- -- Let's forward responses in location /\/full/ when argument /proxy/ in the -- client request's URI is equal to /yes/.@@ -740,17 +740,22 @@ -- | Translates encoded response to 'ContentHandlerResult'. -- -- The translated data can be forwarded to the client by a simple handler based--- on this function in directive /haskell_content/. Handler /fromFullResponse/--- forwards the response to the client after deleting headers listed in set--- 'notForwardableResponseHeaders' and headers with names starting with--- /X-Accel-/.+-- on this function in directive /haskell_content/. Handlers /fromFullResponse/+-- and /fromFullResponseWithException/ forward the response to the client after+-- deleting headers listed in set 'notForwardableResponseHeaders' and headers+-- with names starting with /X-Accel-/. The two handlers differ in the response+-- composing function: the former always returns the response body of the+-- subrequest while the latter returns the error message in the response body if+-- an exception has happened during the subrequest. contentFromFullResponse :: HashSet HeaderName -- ^ Set of not forwardable response headers -> Bool -- ^ Do not forward /X-Accel-.../ response headers+ -> (L.ByteString -> ByteString -> L.ByteString)+ -- ^ Function to compose response body and exception -> ByteString -- ^ Encoded HTTP response -> ContentHandlerResult-contentFromFullResponse headersToDelete deleteXAccel v =- let (_, st, hs, b) = Binary.decode @FullResponse $ L.fromStrict v+contentFromFullResponse headersToDelete deleteXAccel f v =+ let (st, hs, b, e) = Binary.decode @FullResponse $ L.fromStrict v hs' = map (first mk) hs ct = fromMaybe "" $ lookup (mk "Content-Type") hs' hs'' = filter@@ -759,10 +764,19 @@ deleteXAccel && foldCase "X-Accel-" `B.isPrefixOf` foldedCase n ) hs'- in (b, ct, st, map (first original) hs'')+ in (f b e, ct, st, map (first original) hs'') fromFullResponse :: ByteString -> ContentHandlerResult-fromFullResponse = contentFromFullResponse notForwardableResponseHeaders True+fromFullResponse =+ contentFromFullResponse notForwardableResponseHeaders True const ngxExportHandler 'fromFullResponse++fromFullResponseWithException :: ByteString -> ContentHandlerResult+fromFullResponseWithException =+ contentFromFullResponse notForwardableResponseHeaders True f+ where f "" = L.fromStrict+ f b = const b++ngxExportHandler 'fromFullResponseWithException
ngx-export-tools-extra.cabal view
@@ -1,5 +1,5 @@ name: ngx-export-tools-extra-version: 0.6.0.1+version: 0.6.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>.