packages feed

ngx-export-tools-extra 0.5.8.0 → 0.5.9.0

raw patch · 4 files changed

+115/−10 lines, 4 filesdep +networkdep ~http-clientPVP ok

version bump matches the API change (PVP)

Dependencies added: network

Dependency ranges changed: http-client

API changes (from Hackage documentation)

+ NgxExport.Tools.Subrequest: instance GHC.Exception.Type.Exception NgxExport.Tools.Subrequest.UDSNotConfiguredError
+ NgxExport.Tools.Subrequest: instance GHC.Read.Read NgxExport.Tools.Subrequest.UDSConf
+ NgxExport.Tools.Subrequest: instance GHC.Show.Show NgxExport.Tools.Subrequest.UDSNotConfiguredError

Files

Changelog.md view
@@ -1,3 +1,7 @@+### 0.5.9.0++- Allow Unix domain sockets in configurations of internal HTTP subrequests.+ ### 0.5.8.0  - Using *Data.HashSet* for *pcGauges* and *pcScale1000* in Prometheus metrics.
NgxExport/Tools/Prometheus.hs view
@@ -435,7 +435,7 @@  prometheusConf :: PrometheusConf -> Bool -> IO L.ByteString prometheusConf = ignitionService $ \a -> do-    atomicWriteIORef conf $ Just a+    writeIORef conf $ Just a     return ""  ngxExportSimpleServiceTyped
NgxExport/Tools/Subrequest.hs view
@@ -22,6 +22,9 @@     -- $makingHTTPSubrequests                                    makeSubrequest                                   ,makeSubrequestWithRead+    -- * Internal HTTP subrequests via Unix domain sockets+    -- $internalHTTPSubrequests+     -- * Getting full response data from HTTP subrequests     -- $gettingFullResponse                                   ,makeSubrequestFull@@ -42,11 +45,14 @@ import           Network.HTTP.Client hiding (ResponseTimeout) import qualified Network.HTTP.Client (HttpExceptionContent (ResponseTimeout)) import           Network.HTTP.Types+import qualified Network.Socket as S+import qualified Network.Socket.ByteString as S import           Data.ByteString (ByteString) import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as C8 import qualified Data.ByteString.Lazy as L import qualified Data.ByteString.Lazy.Char8 as C8L+import           Data.IORef import qualified Data.Text.Encoding as T import qualified Data.Binary as Binary import           Data.HashSet (HashSet)@@ -123,8 +129,9 @@ -- --         location \/ { --             haskell_run_async __/makeSubrequest/__ $hs_subrequest---                     \'{\"uri\": \"http:\/\/127.0.0.1:8010\/proxy\",---                       \"headers\": [[\"Custom-Header\", \"$arg_a\"]]}\';+--                     \'{\"uri\": \"http:\/\/127.0.0.1:8010\/proxy\"+--                      ,\"headers\": [[\"Custom-Header\", \"$arg_a\"]]+--                      }\'; -- --             if ($hs_subrequest = \'\') { --                 echo_status 404;@@ -204,6 +211,10 @@  instance Exception SubrequestParseError +data UDSNotConfiguredError = UDSNotConfiguredError deriving Show++instance Exception UDSNotConfiguredError+ data ResponseTimeout = ResponseTimeoutDefault                      | ResponseTimeout TimeInterval deriving (Eq, Read) @@ -213,6 +224,7 @@                    , srBody            :: ByteString                    , srHeaders         :: RequestHeaders                    , srResponseTimeout :: ResponseTimeout+                   , srUseUDS          :: Bool                    } deriving Read  instance FromJSON SubrequestConf where@@ -224,6 +236,7 @@             o .:? "headers" .!= []         srResponseTimeout <- maybe ResponseTimeoutDefault ResponseTimeout <$>             o .:? "timeout"+        srUseUDS <- fromMaybe False <$> o .:? "useUDS"         return SubrequestConf {..}         where maybeEmpty = fmap $ maybe "" T.encodeUtf8 @@ -231,6 +244,10 @@     (Response L.ByteString -> L.ByteString) -> SubrequestConf ->     IO L.ByteString subrequest parseRequestF buildResponseF SubrequestConf {..} = do+    man <- if srUseUDS+               then fromMaybe (throw UDSNotConfiguredError) <$>+                        readIORef httpUDSManager+               else return httpManager     req <- parseRequestF srUri     let req' = if B.null srMethod                    then req@@ -245,7 +262,7 @@                       then req'''                       else req''' { responseTimeout =                                         setTimeout srResponseTimeout }-    buildResponseF <$> httpLbs req'''' httpManager+    buildResponseF <$> httpLbs req'''' man     where setTimeout (ResponseTimeout v)               | t == 0 = responseTimeoutNone               | otherwise = responseTimeoutMicro $ t * 1e6@@ -280,6 +297,10 @@ httpManager = unsafePerformIO $ newManager defaultManagerSettings {-# NOINLINE httpManager #-} +httpUDSManager :: IORef (Maybe Manager)+httpUDSManager = unsafePerformIO $ newIORef Nothing+{-# NOINLINE httpUDSManager #-}+ -- | Makes an HTTP request. -- -- This is the core function of the /makeSubrequest/ handler. From perspective@@ -301,8 +322,9 @@ -- -- > {"uri": "http://127.0.0.1/subreq", "method": "POST", "body": "some value"} ----- > {"uri": "http://127.0.0.1/subreq",--- >     "headers": [["Header1", "Value1"], ["Header2", "Value2"]]}+-- > {"uri": "http://127.0.0.1/subreq"+-- > ,"headers": [["Header1", "Value1"], ["Header2", "Value2"]]+-- > } -- -- Returns the response body if HTTP status of the response is /2xx/, otherwise -- throws an error. To avoid leakage of error messages into variable handlers,@@ -330,6 +352,7 @@ -- >                , srBody = "" -- >                , srHeaders = [("Header1", "Value1"), ("Header2", "Value2")] -- >                , srResponseTimeout = ResponseTimeout (Sec 10)+-- >                , srUseUDS = False -- >                } -- -- Notice that unlike JSON parsing, fields of /SubrequestConf/ are not@@ -344,6 +367,82 @@  ngxExportAsyncIOYY 'makeSubrequestWithRead +newtype UDSConf = UDSConf { udsPath :: FilePath } deriving Read++configureUDS :: UDSConf -> Bool -> IO L.ByteString+configureUDS = ignitionService $ \UDSConf {..} -> do+    man <- newManager defaultManagerSettings+               { managerRawConnection = return $ openUDS udsPath }+    writeIORef httpUDSManager $ Just man+    return ""+    where openUDS path _ _ _  = do+              s <- S.socket S.AF_UNIX S.Stream S.defaultProtocol+              S.connect s (S.SockAddrUnix path)+              makeConnection (S.recv s 4096) (S.sendAll s) (S.close s)++ngxExportSimpleServiceTyped 'configureUDS ''UDSConf SingleShotService++-- $internalHTTPSubrequests+--+-- Making HTTP subrequests to the own Nginx service via the loopback interface+-- (e.g. via /127.0.0.1/) has disadvantages of being neither very fast (if+-- compared with various types of local data communication channels) nor very+-- secure. Unix domain sockets is a better alternative in this sense. This+-- module has support for them by providing configuration service+-- __/simpleService_configureUDS/__ where path to the socket can be set, and an+-- extra field /srUseUDS/ in data /SubrequestConf/.+--+-- To extend the previous example for using with Unix domain sockets, the+-- following declarations should be added.+--+-- ==== File /nginx.conf/: configuring the Unix domain socket+-- @+--     haskell_run_service __/simpleService_configureUDS/__ $hs_service_uds+--             \'__/UDSConf/__ {__/udsPath/__ = \"\/tmp\/backend.sock\"}\';+-- @+--+-- /UDSConf/ is an opaque type containing only one field /udsPath/ with the path+-- to the socket.+--+-- ==== File /nginx.conf/: new location /\/uds/ in server /main/+-- @+--         location \/uds {+--             haskell_run_async __/makeSubrequest/__ $hs_subrequest+--                     \'{\"uri\": \"http:\/\/backend_proxy\/\"+--                      ,\"headers\": [[\"Custom-Header\", \"$arg_a\"]]+--                      ,\"__/useUDS/__\": __/true/__+--                      }\';+--+--             if ($hs_subrequest = \'\') {+--                 echo_status 404;+--                 echo \"Failed to perform subrequest\";+--                 break;+--             }+--+--             echo -n $hs_subrequest;+--         }+-- @+--+-- ==== File /nginx.conf/: new virtual server /backend_proxy/+-- @+--     server {+--         listen       unix:\/tmp\/backend.sock;+--         server_name  backend_proxy;+--+--         location \/ {+--             proxy_pass http:\/\/backend;+--         }+--     }+-- @+--+-- The server listens on the Unix domain socket with the path configured in+-- service /simpleService_configureUDS/.+--+-- ==== A simple test+--+-- > $ curl 'http://localhost:8010/uds?a=Value'+-- > In backend, Custom-Header is 'Value'+ -- $gettingFullResponse -- -- Handlers /makeSubrequest/ and /makeSubrequestWithRead/ return response body@@ -372,8 +471,9 @@ -- @ --         location \/full { --             haskell_run_async __/makeSubrequestFull/__ $hs_subrequest---                     \'{\"uri\": \"http:\/\/127.0.0.1:$arg_p\/proxy\",---                       \"headers\": [[\"Custom-Header\", \"$arg_a\"]]}\';+--                     \'{\"uri\": \"http:\/\/127.0.0.1:$arg_p\/proxy\"+--                      ,\"headers\": [[\"Custom-Header\", \"$arg_a\"]]+--                      }\'; -- --             haskell_run __/extractStatusFromFullResponse/__ $hs_subrequest_status --                     $hs_subrequest;
ngx-export-tools-extra.cabal view
@@ -1,5 +1,5 @@ name:                       ngx-export-tools-extra-version:                    0.5.8.0+version:                    0.5.9.0 synopsis:                   More extra tools for Nginx haskell module description:                More extra tools for         <https://github.com/lyokha/nginx-haskell-module Nginx haskell module>.@@ -38,7 +38,8 @@                           , ngx-export-tools >= 0.4.8.0                           , aeson >= 1.0.0.0                           , http-types >= 0.7.0-                          , http-client >= 0.5.0+                          , http-client >= 0.5.3+                          , network >= 2.4.0.0                           , binary                           , case-insensitive                           , containers