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 +5/−0
- NgxExport/Tools/EDE.hs +4/−4
- NgxExport/Tools/ServiceHookAdaptor.hs +187/−0
- NgxExport/Tools/Subrequest.hs +2/−2
- ngx-export-tools-extra.cabal +4/−3
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