packages feed

ngx-export-tools-extra 0.6.2.0 → 0.7.0.0

raw patch · 5 files changed

+202/−9 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

Changelog.md view
@@ -1,3 +1,8 @@+### 0.7.0.0++- Added module *NgxExport.Tools.ServiceHookAdaptor* to maintain custom global+  data in all the worker processes in run-time.+ ### 0.6.2.0  - Added Cabal flag *Aggregate* to build module *NgxExport.Tools.Aggregate*
NgxExport/Tools/EDE.hs view
@@ -173,10 +173,10 @@ -- * __/uenc/__ encodes a JSON object using /URL encoding/ rules -- -- So, basically, we used /renderEDETemplate/ to decompose POSTed JSON objects--- and then /rewrite/ requests to other locations where extracted fields were--- encoded inside the location's URL path. Handler--- /renderEDETemplateFromFreeValue/ in /location \/cookie/ does the same but--- reads JSON objects from HTTP cookie /user/.+-- and then /rewrite/ requests to other locations where the URL path after+-- substitution of the extracted and then encoded into variable /$hs_user/+-- fields points to. Handler /renderEDETemplateFromFreeValue/ in location+-- /\/cookie/ does the same but reads JSON objects from HTTP cookie /user/. -- -- ==== A simple test --
+ NgxExport/Tools/ServiceHookAdaptor.hs view
@@ -0,0 +1,187 @@+{-# LANGUAGE TemplateHaskell #-}++-----------------------------------------------------------------------------+-- |+-- Module      :  NgxExport.Tools.ServiceHookAdaptor+-- Copyright   :  (c) Alexey Radkov 2021+-- License     :  BSD-style+--+-- Maintainer  :  alexey.radkov@gmail.com+-- Stability   :  experimental+-- Portability :  non-portable (requires Template Haskell)+--+-- A service hook adaptor from the more extra tools collection for+-- <http://github.com/lyokha/nginx-haskell-module nginx-haskell-module>.+--+-----------------------------------------------------------------------------+++module NgxExport.Tools.ServiceHookAdaptor (+    -- * Maintaining custom global data in run-time+    -- $maintainingCustomGlobalData+                                          ) where++import           NgxExport.Tools++import           Data.ByteString (ByteString)+import qualified Data.ByteString.Lazy as L+import           Control.Monad++-- $maintainingCustomGlobalData+--+-- This module exports a /simple service/ (in terms of module "NgxExport.Tools")+-- __/simpleService_hookAdaptor/__ which sleeps forever. Its sole purpose is to+-- serve /service hooks/ for changing global data in all the worker processes in+-- run-time. A single service hook adaptor can serve any number of service hooks+-- with any type of global data.+--+-- Below is a simple example.+--+-- ==== File /test_tools_extra_servicehookadaptor.hs/+-- @+-- {-\# LANGUAGE TemplateHaskell, OverloadedStrings \#-}+--+-- module TestToolsExtraServiceHookAdaptor where+--+-- import           NgxExport+-- import           NgxExport.Tools.ServiceHookAdaptor ()+--+-- import           Data.ByteString (ByteString)+-- import qualified Data.ByteString as B+-- import qualified Data.ByteString.Lazy as L+-- import           Data.IORef+-- import           System.IO.Unsafe+--+-- secretWord :: IORef ByteString+-- secretWord = unsafePerformIO $ newIORef ""+-- {-\# NOINLINE secretWord \#-}+--+-- testSecretWord :: ByteString -> IO L.ByteString+-- __/testSecretWord/__ v = do+--     s <- readIORef secretWord+--     return $ if B.null s+--                  then \"null\"+--                  else if v == s+--                           then \"set\"+--                           else \"unset\"+-- 'NgxExport.ngxExportIOYY' 'testSecretWord+--+-- changeSecretWord :: ByteString -> IO L.ByteString+-- __/changeSecretWord/__ s = do+--     writeIORef secretWord s+--     return \"The secret word was changed\"+-- 'NgxExport.ngxExportServiceHook' \'changeSecretWord+-- @+--+-- Here we are going to maintain a /secret word/ of type 'ByteString' in+-- run-time. When a worker process starts, the word is empty. The word can be+-- changed in run-time by triggering /service hook/ /changeSecretWord/. Client+-- requests are managed differently depending on their knowledge of the secret+-- which is tested in handler /testSecretWord/.+--+-- ==== File /nginx.conf/+-- @+-- user                    nobody;+-- worker_processes        2;+--+-- events {+--     worker_connections  1024;+-- }+--+-- error_log               \/tmp\/nginx-test-haskell-error.log info;+--+-- http {+--     default_type        application\/octet-stream;+--     sendfile            on;+--     error_log           \/tmp\/nginx-test-haskell-error.log;+--     access_log          \/tmp\/nginx-test-haskell-access.log;+--+--     haskell load \/var\/lib\/nginx\/test_tools_extra_servicehookadaptor.so;+--+--     haskell_run_service __/simpleService_hookAdaptor/__ $hs_hook_adaptor 32k;+--+--     haskell_service_hooks_zone hooks 32k;+--+--     server {+--         listen       8010;+--         server_name  main;+--+--         location \/ {+--             haskell_run __/testSecretWord/__ $hs_secret_word $arg_s;+--+--             if ($hs_secret_word = null) {+--                 echo_status 503;+--                 echo \"Try later! The service is not ready!\";+--                 break;+--             }+--+--             if ($hs_secret_word = set) {+--                 echo_status 200;+--                 echo \"Congrats! You know the secret word!\";+--                 break;+--             }+--+--             echo_status 404;+--             echo \"Hmm, you do not know a secret!\";+--         }+--+--         location \/change_sw {+--             allow 127.0.0.1;+--             deny all;+--+--             haskell_service_hook __/changeSecretWord/__ $hs_hook_adaptor $arg_s;+--         }+--     }+-- }+-- @+--+-- Notice that service /simpleService_hookAdaptor/ is not shared.+--+-- ==== A simple test+-- After starting Nginx, the secret word service must be not ready.+--+-- > $ curl 'http://127.0.0.1:8010/'+-- > Try later! The service is not ready!+--+-- Let's change the secret word,+--+-- > $ curl 'http://127.0.0.1:8010/change_sw?s=secret'+--+-- and try again.+--+-- > $ curl 'http://127.0.0.1:8010/'+-- > Hmm, you do not know a secret!+-- > $ curl 'http://127.0.0.1:8010/?s=try1'+-- > Hmm, you do not know a secret!+-- > $ curl 'http://127.0.0.1:8010/?s=secret'+-- > Congrats! You know the secret word!+--+-- Change the secret word again.+--+-- > $ curl 'http://127.0.0.1:8010/change_sw?s=secret1'+-- > $ curl 'http://127.0.0.1:8010/?s=secret'+-- > Hmm, you do not know a secret!+-- > $ curl 'http://127.0.0.1:8010/?s=secret1'+-- > Congrats! You know the secret word!+--+-- What if a worker process quits for some reason or crashes? Let's try!+--+-- > # ps -ef | grep nginx | grep worker+-- > nobody     13869   13868  0 15:43 ?        00:00:00 nginx: worker process+-- > nobody     13870   13868  0 15:43 ?        00:00:00 nginx: worker process+-- > # kill -QUIT 13869 13870+-- > # ps -ef | grep nginx | grep worker+-- > nobody     14223   13868  4 15:56 ?        00:00:00 nginx: worker process+-- > nobody     14224   13868  4 15:56 ?        00:00:00 nginx: worker process+--+-- > $ curl 'http://127.0.0.1:8010/?s=secret1'+-- > Congrats! You know the secret word!+--+-- Our secret is still intact! This is because service hooks manage new worker+-- processes so well as those that were running when a hook was triggered.++hookAdaptor :: ByteString -> Bool -> IO L.ByteString+hookAdaptor = ignitionService $+    const $ forever $ threadDelaySec $ toSec $ Hr 24+ngxExportSimpleService 'hookAdaptor SingleShotService+
NgxExport/Tools/Subrequest.hs view
@@ -168,7 +168,7 @@ -- and other relevant data such as HTTP method, request body and headers. In -- this configuration we are running a periodical service which gets contents of -- /httpbin.org/ every 10 seconds, and doing a subrequest to a virtual server--- /backend/ on every request to /location \//. In this subrequest, an HTTP+-- /backend/ on every request to location /\//. In this subrequest, an HTTP -- header /Custom-Header/ is sent to the backend with value equal to the value -- of argument /a/ from the client request's URI. --@@ -517,7 +517,7 @@ -- Now we can recognize HTTP response statuses of subrequests and handle them -- differently. We also can read a response header /Subrequest-Header/. ----- ==== File /nginx.conf/: new response header /Subrequest-Header/ in /location \// of server /backend/+-- ==== File /nginx.conf/: new response header /Subrequest-Header/ in location /\// of server /backend/ -- @ --             add_header Subrequest-Header \"This is response from subrequest\"; -- @
ngx-export-tools-extra.cabal view
@@ -1,5 +1,5 @@ name:                       ngx-export-tools-extra-version:                    0.6.2.0+version:                    0.7.0.0 synopsis:                   More extra tools for Nginx haskell module description:                More extra tools for         <https://github.com/lyokha/nginx-haskell-module Nginx haskell module>.@@ -26,8 +26,8 @@   description:              Build EDE module.  flag EDEUsePrettyprinter-  description:              Build EDE module migrated from-                            [ansi-wl-pprint](https://hackage.haskell.org/package/ansi-wl-pprint)+  description:              Build EDE module migrated+                            from [ansi-wl-pprint](https://hackage.haskell.org/package/ansi-wl-pprint)                             to [prettyprinter](https://hackage.haskell.org/package/prettyprinter).  library@@ -69,6 +69,7 @@    exposed-modules:          NgxExport.Tools.Prometheus                           , NgxExport.Tools.Subrequest+                          , NgxExport.Tools.ServiceHookAdaptor    if flag(Aggregate)     exposed-modules:        NgxExport.Tools.Aggregate