This is an automated email from the ASF dual-hosted git repository.

zwoop pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git


The following commit(s) were added to refs/heads/master by this push:
     new 36bbf69aca Foundation laid for global Cripts (#11793)
36bbf69aca is described below

commit 36bbf69acafc889f3b0a23c5b9d1ebedf87d19fc
Author: Leif Hedstrom <[email protected]>
AuthorDate: Tue Oct 15 20:11:14 2024 -0600

    Foundation laid for global Cripts (#11793)
    
    * Foundation laid for global Cripts
    
    * Try to fix the enumerated and non-enumerated type errors
    
    * Added documentation for the global hooks
    
    * Fix doc typos, thanks bcall
---
 doc/developer-guide/cripts/cripts-global.en.rst | 153 +++++++
 doc/developer-guide/cripts/index.en.rst         |   1 +
 example/cripts/global.cc                        |  83 ++++
 include/cripts/Bundle.hpp                       |   2 +-
 include/cripts/Context.hpp                      |  10 +-
 include/cripts/Epilogue.hpp                     | 518 +++++++++++++++++++++---
 include/cripts/Instance.hpp                     |   8 +-
 include/cripts/Preamble.hpp                     |  26 +-
 include/cripts/Transaction.hpp                  |  29 +-
 src/cripts/Instance.cc                          |  22 +-
 src/cripts/Urls.cc                              |  17 +-
 11 files changed, 773 insertions(+), 96 deletions(-)

diff --git a/doc/developer-guide/cripts/cripts-global.en.rst 
b/doc/developer-guide/cripts/cripts-global.en.rst
new file mode 100644
index 0000000000..56fd35bb35
--- /dev/null
+++ b/doc/developer-guide/cripts/cripts-global.en.rst
@@ -0,0 +1,153 @@
+.. Licensed to the Apache Software Foundation (ASF) under one
+   or more contributor license agreements.  See the NOTICE file
+   distributed with this work for additional information
+   regarding copyright ownership.  The ASF licenses this file
+   to you under the Apache License, Version 2.0 (the
+   "License"); you may not use this file except in compliance
+   with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing,
+   software distributed under the License is distributed on an
+   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+   KIND, either express or implied.  See the License for the
+   specific language governing permissions and limitations
+   under the License.
+
+.. include:: ../../common.defs
+
+.. highlight:: cpp
+.. default-domain:: cpp
+
+.. _cripts-global:
+
+Cripts for global plugin
+************************
+
+In addition to be a scripting language for per-property, or remap rules, 
Cripts can
+also be used to write global ATS plugins. This is a more advanced use case, 
and requires
+some knowledge of how ATS works.
+
+The automatic building of plugins that Cripts supports as a remap rule is not 
available
+(yet) to global plugins. As such, you must compile any global plugin manually. 
You can
+see this as an alternative to writing a plugin in regular C++, in fact you can 
still
+combine a global plugin with a remap rule plugin in the same Cript file.
+
+Usage
+=====
+
+As with remap rules, global Cripts still requires both the preamble as well as 
the epilogue.
+However, all callbacks are prefixed with ``glb_`` to indicate that they are 
global hooks.
+See the hooks below for more details. Example:
+
+The third step is to put the Cript file in either the configuration or plugin 
installation,
+depending on your preference. The file must be readable by the ATS process. 
Example:
+
+.. code-block:: cpp
+
+   #include <cripts/Preamble.hpp>
+
+   glb_read_request()
+   {
+     borrow url = cripts::Client::URL::get();
+
+     url.query.keep({"foo", "bar"});
+   }
+
+   #include <cripts/Epilogue.hpp>
+
+Hooks
+=====
+
+Hooks are the main way to interact with ATS. The hooks are the same as the ATS 
hooks,
+but with a few differences. The hooks are all in the global namespace, and the 
hooks
+are all functions. Cripts provides a core set of hooks which are always 
available,
+but they are not required to be used.
+
+Not all ATS hooks are available in Cripts, but the most common ones are. Hooks 
are
+implicitly called if they are defined in the Cript file. The Cript will never 
explicitly
+setup the hooks, as this is done by the ATS process.
+
+Normal Hooks
+------------
+
+Lets look at the normal hooks that are available in Cripts. Note here that the 
name
+of the function dictates the underlying ATS hook.
+
+.. _cripts-global-hooks-txn-start:
+
+glb_txn_start()
+^^^^^^^^^^^^^^^
+
+The ``glb_txn_start()`` hook is called at the beginning of a transaction. This 
is also
+where Cripts will setup other HTTP hooks as necessary. Note that in this hook, 
the
+client request has not yet been read, so you cannot access the request headers.
+
+.. _cripts-global-hooks-read-request:
+
+glb_read_request()
+^^^^^^^^^^^^^^^^^^
+
+The ``glb_read_request()`` hook is called after the client request has been 
read. This
+means that you can access the request headers, and the request URL. However, 
remap rules
+has not yet been applied, so the URL may not be the final URL, or even 
complete.
+
+.. _cripts-global-hooks-pre-remap:
+
+glb_pre_remap()
+^^^^^^^^^^^^^^^
+
+This hook may not be particularly useful in Cripts, as remap rules are not 
applied here yet
+as well. We've added it for completeness.
+
+.. _cripts-global-hooks-post-remap:
+
+glb_post_remap()
+^^^^^^^^^^^^^^^^
+
+The ``glb_post_remap()`` hook is called after remap rules have been applied. 
This is the
+closest to the ``do_remap()`` hook in remap rules.
+
+.. _cripts-global-hooks-cache_lookup:
+
+glb_cache_lookup()
+^^^^^^^^^^^^^^^^^^
+
+This is identical to the :ref:`cripts-overview-hooks-do-cache-lookup` hook in 
remap rules.
+
+.. _cripts-global-hooks-send-request:
+
+glb_send_request()
+^^^^^^^^^^^^^^^^^^
+
+This is identical to the :ref:`cripts-overview-hooks-do-send-request` hook in 
remap rules.
+
+.. _cripts-global-hooks-read_response:
+
+glb_read_response()
+^^^^^^^^^^^^^^^^^^^
+
+This is identical to the :ref:`cripts-overview-hooks-do-read-response` hook in 
remap rules.
+
+.. _cripts-global-hooks-send_response:
+
+glb_send_response()
+^^^^^^^^^^^^^^^^^^^
+
+This is identical to the :ref:`cripts-overview-hooks-do-send-response` hook in 
remap rules.
+
+.. _cripts-global-hooks-txn-close:
+
+glb_txn_close()
+^^^^^^^^^^^^^^^
+
+This is identical to the :ref:`cripts-overview-hooks-do-txn-close` hook in 
remap rules.
+
+.. _cripts-global-hooks-init:
+
+glb_init()
+^^^^^^^^^^
+
+This callback is called when the plugin is loaded. This is where you can setup 
any
+global state that you need etc.
diff --git a/doc/developer-guide/cripts/index.en.rst 
b/doc/developer-guide/cripts/index.en.rst
index 155b055deb..c1fb057817 100644
--- a/doc/developer-guide/cripts/index.en.rst
+++ b/doc/developer-guide/cripts/index.en.rst
@@ -26,6 +26,7 @@ Cripts
    :maxdepth: 2
 
    cripts-overview.en
+   cripts-global.en
    cripts-variables.en
    cripts-urls.en
    cripts-headers.en
diff --git a/example/cripts/global.cc b/example/cripts/global.cc
new file mode 100644
index 0000000000..d598884c63
--- /dev/null
+++ b/example/cripts/global.cc
@@ -0,0 +1,83 @@
+/*
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements.  See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership.  The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+*/
+
+// The primary include file, this has to always be included
+#include <cripts/Preamble.hpp>
+
+glb_init()
+{
+  CDebug("Called glb_init()");
+}
+
+glb_txn_start()
+{
+  CDebug("Called glb_txn_start()");
+}
+
+glb_txn_close()
+{
+  CDebug("Called glb_txn_close()");
+}
+
+glb_read_request()
+{
+  borrow req = cripts::Client::Request::Get();
+  borrow url = cripts::Client::URL::Get();
+
+  CDebug("Called glb_read_request()");
+  CDebug("Host Header: {}", req["Host"]);
+  CDebug("Path: {}", url.path);
+}
+
+glb_pre_remap()
+{
+  borrow url = cripts::Client::URL::Get();
+
+  CDebug("Called glb_pre_remap()");
+  CDebug("Client URL: {}", url.String());
+}
+
+glb_post_remap()
+{
+  borrow url = cripts::Client::URL::Get();
+
+  CDebug("Called glb_post_remap()");
+  CDebug("Client URL: {}", url.String());
+}
+
+glb_cache_lookup()
+{
+  CDebug("Called glb_cache_lookup()");
+}
+
+glb_send_request()
+{
+  CDebug("Called glb_send_request()");
+}
+
+glb_read_response()
+{
+  CDebug("Called glb_read_response()");
+}
+
+glb_send_response()
+{
+  CDebug("Called glb_send_response()");
+}
+
+#include <cripts/Epilogue.hpp>
diff --git a/include/cripts/Bundle.hpp b/include/cripts/Bundle.hpp
index 87d5cb30f1..8ba0749ab5 100644
--- a/include/cripts/Bundle.hpp
+++ b/include/cripts/Bundle.hpp
@@ -147,7 +147,7 @@ namespace Bundle
     }
 
   protected:
-    unsigned _callbacks = 0;
+    uint32_t _callbacks = 0;
   }; // Class Base
 
 } // namespace Bundle
diff --git a/include/cripts/Context.hpp b/include/cripts/Context.hpp
index ccc40a2842..6e1520e283 100644
--- a/include/cripts/Context.hpp
+++ b/include/cripts/Context.hpp
@@ -59,11 +59,11 @@ public:
   void              Release();
 
   // These fields are preserving the parameters as setup in DoRemap()
-  cripts::Transaction                      state;
-  std::array<DataType, CONTEXT_DATA_SLOTS> data;
-  TSCont                                   default_cont = nullptr;
-  TSRemapRequestInfo                      *rri          = nullptr;
-  cripts::Instance                        &p_instance; // p_ == public_, since 
we can't use "instance"
+  cripts::Transaction                      state;           // This is the 
transaction state
+  std::array<DataType, CONTEXT_DATA_SLOTS> data;            // Context data
+  TSCont                                   contp = nullptr; // Remap or global 
continuation
+  TSRemapRequestInfo                      *rri   = nullptr; // This may be 
nullptr, if not a remap
+  cripts::Instance                        &p_instance;      // p_ == public_, 
since we can't use "instance"
 
   // These are private, but needs to be visible to our friend classes that
   // depends on the Context.
diff --git a/include/cripts/Epilogue.hpp b/include/cripts/Epilogue.hpp
index 836e677c36..6c63818faf 100644
--- a/include/cripts/Epilogue.hpp
+++ b/include/cripts/Epilogue.hpp
@@ -68,7 +68,7 @@ wrap_do_remap(T * /* context ATS_UNUSED */, bool /* execute 
ATS_UNUSED */, CaseT
   return false;
 }
 
-// send-response-header hook caller
+// post-remap-header hook caller
 template <typename T>
 auto
 wrap_post_remap(T *context, bool execute, CaseTag<1>) -> 
decltype(_do_post_remap(context), bool())
@@ -233,120 +233,382 @@ wrap_delete_instance(T * /* context ATS_UNUSED */, bool 
/* execute ATS_UNUSED */
   return false;
 }
 
-// This is the default continuation handler, for all do_*() callbacks
+// Next are all the wrappers for the global hooks. We intentionally name and 
handle these different,
+// to allow a Cript to define both global and per remap hooks.
+
+// global txn-start hook caller
+template <typename T>
+auto
+wrap_glb_txn_start(T *context, bool execute, CaseTag<1>) -> 
decltype(_glb_txn_start(context), bool())
+{
+  if (execute) {
+    _glb_txn_start(context);
+  }
+  return true;
+}
+
+template <typename T>
+auto
+wrap_glb_txn_start(T * /* context ATS_UNUSED */, bool /* execute ATS_UNUSED 
*/, CaseTag<0>) -> bool
+{
+  return false;
+}
+
+// global read-request hook caller
+template <typename T>
+auto
+wrap_glb_read_request(T *context, bool execute, CaseTag<1>) -> 
decltype(_glb_read_request(context), bool())
+{
+  if (execute) {
+    _glb_read_request(context);
+  }
+  return true;
+}
+
+template <typename T>
+auto
+wrap_glb_read_request(T * /* context ATS_UNUSED */, bool /* execute ATS_UNUSED 
*/, CaseTag<0>) -> bool
+{
+  return false;
+}
+
+// global pre-remap hook caller
+template <typename T>
+auto
+wrap_glb_pre_remap(T *context, bool execute, CaseTag<1>) -> 
decltype(_glb_pre_remap(context), bool())
+{
+  if (execute) {
+    _glb_pre_remap(context);
+  }
+  return true;
+}
+
+template <typename T>
+auto
+wrap_glb_pre_remap(T * /* context ATS_UNUSED */, bool /* execute ATS_UNUSED 
*/, CaseTag<0>) -> bool
+{
+  return false;
+}
+
+// global post-remap hook caller
+template <typename T>
+auto
+wrap_glb_post_remap(T *context, bool execute, CaseTag<1>) -> 
decltype(_glb_post_remap(context), bool())
+{
+  if (execute) {
+    _glb_post_remap(context);
+  }
+  return true;
+}
+
+template <typename T>
+auto
+wrap_glb_post_remap(T * /* context ATS_UNUSED */, bool /* execute ATS_UNUSED 
*/, CaseTag<0>) -> bool
+{
+  return false;
+}
+
+// global cache-lookup hook caller
+template <typename T>
+auto
+wrap_glb_cache_lookup(T *context, bool execute, CaseTag<1>) -> 
decltype(_glb_cache_lookup(context), bool())
+{
+  if (execute) {
+    _glb_cache_lookup(context);
+  }
+  return true;
+}
+
+template <typename T>
+auto
+wrap_glb_cache_lookup(T * /* context ATS_UNUSED */, bool /* execute ATS_UNUSED 
*/, CaseTag<0>) -> bool
+{
+  return false;
+}
+
+// global send-request hook caller
+template <typename T>
+auto
+wrap_glb_send_request(T *context, bool execute, CaseTag<1>) -> 
decltype(_glb_send_request(context), bool())
+{
+  if (execute) {
+    _glb_send_request(context);
+  }
+  return true;
+}
+
+template <typename T>
+auto
+wrap_glb_send_request(T * /* context ATS_UNUSED */, bool /* execute ATS_UNUSED 
*/, CaseTag<0>) -> bool
+{
+  return false;
+}
+
+// global read-response hook caller
+template <typename T>
+auto
+wrap_glb_read_response(T *context, bool execute, CaseTag<1>) -> 
decltype(_glb_read_response(context), bool())
+{
+  if (execute) {
+    _glb_read_response(context);
+  }
+  return true;
+}
+
+template <typename T>
+auto
+wrap_glb_read_response(T * /* context ATS_UNUSED */, bool /* execute 
ATS_UNUSED */, CaseTag<0>) -> bool
+{
+  return false;
+}
+
+// global send-response hook caller
+template <typename T>
+auto
+wrap_glb_send_response(T *context, bool execute, CaseTag<1>) -> 
decltype(_glb_send_response(context), bool())
+{
+  if (execute) {
+    _glb_send_response(context);
+  }
+  return true;
+}
+
+template <typename T>
+auto
+wrap_glb_send_response(T * /* context ATS_UNUSED */, bool /* execute 
ATS_UNUSED */, CaseTag<0>) -> bool
+{
+  return false;
+}
+
+// global txn-close hook caller
+template <typename T>
+auto
+wrap_glb_txn_close(T *context, bool execute, CaseTag<1>) -> 
decltype(_glb_txn_close(context), bool())
+{
+  if (execute) {
+    _glb_txn_close(context);
+  }
+  return true;
+}
+
+template <typename T>
+auto
+wrap_glb_txn_close(T * /* context ATS_UNUSED */, bool /* execute ATS_UNUSED 
*/, CaseTag<0>) -> bool
+{
+  return false;
+}
+
+// glb_init caller (not a hook, called when the global plugin is initialized).
+template <typename T>
+auto
+wrap_glb_init(T *context, bool execute, CaseTag<1>) -> 
decltype(_glb_init(context), bool())
+{
+  if (execute) {
+    _glb_init(context);
+  }
+  return true;
+}
+
+template <typename T>
+auto
+wrap_glb_init(T * /* context ATS_UNUSED */, bool /* execute ATS_UNUSED */, 
CaseTag<0>) -> bool
+{
+  return false;
+}
+
+// This is the HTTP transaction continuation, which is used for all the HTTP 
hooks.
 int
-default_cont(TSCont contp, TSEvent event, void *edata)
+http_txn_cont(TSCont contp, TSEvent event, void *edata)
 {
   auto  txnp    = static_cast<TSHttpTxn>(edata);
   auto *context = static_cast<cripts::Context *>(TSContDataGet(contp));
 
+  // ToDo: We can optimize this once we have header heap generation IDs in 
place.
   context->reset(); // Clears the cached handles to internal ATS data (mloc's 
etc.)
 
   switch (event) {
-  case TS_EVENT_HTTP_SEND_REQUEST_HDR:
-    context->state.hook = TS_HTTP_SEND_REQUEST_HDR_HOOK;
+    // This is only used for global plugin, sine DoRemap() is handled without 
a continuation
+  case TS_EVENT_HTTP_READ_REQUEST_HDR: // 60002
+    context->state.hook = TS_HTTP_READ_REQUEST_HDR_HOOK;
     if (!context->state.error.Failed()) {
-      CDebug("Entering do_send_request()");
+      // Call any bundle callbacks that are registered for this hook
+      if (!context->state.error.Failed() && context->p_instance.Callbacks() & 
cripts::Callbacks::GLB_READ_REQUEST) {
+        for (auto &bundle : context->p_instance.bundles) {
+          if (bundle->Callbacks() & cripts::Callbacks::GLB_READ_REQUEST) {
+            bundle->doSendRequest(context);
+          }
+        }
+      }
+      CDebug("Entering glb_read_request()");
+      wrap_glb_read_request(context, true, CaseArg);
+      cripts::Client::URL::_get(context).Update(); // Make sure any changes to 
the request URL is updated
+    }
+    break;
 
+  case TS_EVENT_HTTP_SEND_REQUEST_HDR: // 60004
+    context->state.hook = TS_HTTP_SEND_REQUEST_HDR_HOOK;
+    if (!context->state.error.Failed()) {
       // Call any bundle callbacks that are registered for this hook
-      if (!context->state.error.Failed() && context->p_instance.Callbacks() & 
cripts::Callbacks::DO_SEND_REQUEST) {
+      if (!context->state.error.Failed() &&
+          context->p_instance.Callbacks() & 
(cripts::Callbacks::DO_SEND_REQUEST | cripts::Callbacks::GLB_SEND_REQUEST)) {
         for (auto &bundle : context->p_instance.bundles) {
-          if (bundle->Callbacks() & cripts::Callbacks::DO_SEND_REQUEST) {
+          if (bundle->Callbacks() & (cripts::Callbacks::DO_SEND_REQUEST | 
cripts::Callbacks::GLB_SEND_REQUEST)) {
             bundle->doSendRequest(context);
           }
         }
       }
-      wrap_send_request(context, true, CaseArg);
+      if (context->state.enabled_hooks & cripts::Callbacks::DO_TXN_CLOSE) {
+        CDebug("Entering do_send_request()");
+        wrap_send_request(context, true, CaseArg);
+      } else if (context->state.enabled_hooks & 
cripts::Callbacks::GLB_SEND_REQUEST) {
+        CDebug("Entering glb_send_request()");
+        wrap_glb_send_request(context, true, CaseArg);
+      }
       cripts::Client::URL::_get(context).Update(); // Make sure any changes to 
the request URL is updated
     }
     break;
+
   case TS_EVENT_HTTP_READ_RESPONSE_HDR: // 60006
     context->state.hook = TS_HTTP_READ_RESPONSE_HDR_HOOK;
     if (!context->state.error.Failed()) {
-      CDebug("Entering do_read_response()");
-
       // Call any bundle callbacks that are registered for this hook
-      if (!context->state.error.Failed() && context->p_instance.Callbacks() & 
cripts::Callbacks::DO_READ_RESPONSE) {
+      if (!context->state.error.Failed() &&
+          context->p_instance.Callbacks() & 
(cripts::Callbacks::DO_READ_RESPONSE | cripts::Callbacks::GLB_READ_RESPONSE)) {
         for (auto &bundle : context->p_instance.bundles) {
-          if (bundle->Callbacks() & cripts::Callbacks::DO_READ_RESPONSE) {
+          if (bundle->Callbacks() & (cripts::Callbacks::DO_READ_RESPONSE | 
cripts::Callbacks::GLB_READ_RESPONSE)) {
             bundle->doReadResponse(context);
           }
         }
       }
-      wrap_read_response(context, true, CaseArg);
+      if (context->state.enabled_hooks & cripts::Callbacks::DO_READ_RESPONSE) {
+        CDebug("Entering do_read_response()");
+        wrap_read_response(context, true, CaseArg);
+      } else if (context->state.enabled_hooks & 
cripts::Callbacks::GLB_READ_RESPONSE) {
+        CDebug("Entering glb_read_response()");
+        wrap_glb_read_response(context, true, CaseArg);
+      }
     }
     break;
+
   case TS_EVENT_HTTP_SEND_RESPONSE_HDR: // 60007
     context->state.hook = TS_HTTP_SEND_RESPONSE_HDR_HOOK;
     if (!context->state.error.Failed()) {
       CDebug("Entering do_send_response()");
 
       // Call any bundle callbacks that are registered for this hook
-      if (!context->state.error.Failed() && context->p_instance.Callbacks() & 
cripts::Callbacks::DO_SEND_RESPONSE) {
+      if (!context->state.error.Failed() &&
+          context->p_instance.Callbacks() & 
(cripts::Callbacks::DO_SEND_RESPONSE | cripts::Callbacks::GLB_SEND_RESPONSE)) {
         for (auto &bundle : context->p_instance.bundles) {
-          if (bundle->Callbacks() & cripts::Callbacks::DO_SEND_RESPONSE) {
+          if (bundle->Callbacks() & (cripts::Callbacks::DO_SEND_RESPONSE | 
cripts::Callbacks::GLB_SEND_RESPONSE)) {
             bundle->doSendResponse(context);
           }
         }
       }
-      wrap_send_response(context, true, CaseArg);
+      if (context->state.enabled_hooks & cripts::Callbacks::DO_SEND_RESPONSE) {
+        wrap_send_response(context, true, CaseArg);
+      } else if (context->state.enabled_hooks & 
cripts::Callbacks::GLB_SEND_RESPONSE) {
+        wrap_glb_send_response(context, true, CaseArg);
+      }
     }
     break;
+
   case TS_EVENT_HTTP_TXN_CLOSE: // 60012
     context->state.hook = TS_HTTP_TXN_CLOSE_HOOK;
-    if (context->state.enabled_hooks & cripts::Callbacks::DO_TXN_CLOSE) {
-      CDebug("Entering do_txn_close()");
-
+    if (context->state.enabled_hooks & (cripts::Callbacks::DO_TXN_CLOSE | 
cripts::Callbacks::GLB_TXN_CLOSE)) {
       // Call any bundle callbacks that are registered for this hook
-      if (!context->state.error.Failed() && context->p_instance.Callbacks() & 
cripts::Callbacks::DO_TXN_CLOSE) {
+      if (!context->state.error.Failed() &&
+          context->p_instance.Callbacks() & (cripts::Callbacks::DO_TXN_CLOSE | 
cripts::Callbacks::GLB_TXN_CLOSE)) {
         for (auto &bundle : context->p_instance.bundles) {
-          if (bundle->Callbacks() & cripts::Callbacks::DO_TXN_CLOSE) {
+          if (bundle->Callbacks() & (cripts::Callbacks::DO_TXN_CLOSE | 
cripts::Callbacks::GLB_TXN_CLOSE)) {
             bundle->doTxnClose(context);
           }
         }
       }
-      wrap_txn_close(context, true, CaseArg);
+      if (context->state.enabled_hooks & cripts::Callbacks::DO_TXN_CLOSE) {
+        CDebug("Entering do_txn_close()");
+        wrap_txn_close(context, true, CaseArg);
+      } else if (context->state.enabled_hooks & 
cripts::Callbacks::GLB_TXN_CLOSE) {
+        CDebug("Entering glb_txn_close()");
+        wrap_glb_txn_close(context, true, CaseArg);
+      }
     }
 
     TSContDestroy(contp);
     context->Release();
     break;
+
   case TS_EVENT_HTTP_CACHE_LOOKUP_COMPLETE: // 60015
     context->state.hook = TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK;
     if (!context->state.error.Failed()) {
-      CDebug("Entering do_cache_lookup()");
-
       // Call any bundle callbacks that are registered for this hook
-      if (!context->state.error.Failed() && context->p_instance.Callbacks() & 
cripts::Callbacks::DO_CACHE_LOOKUP) {
+      if (!context->state.error.Failed() &&
+          context->p_instance.Callbacks() & 
(cripts::Callbacks::DO_CACHE_LOOKUP | cripts::Callbacks::GLB_CACHE_LOOKUP)) {
         for (auto &bundle : context->p_instance.bundles) {
-          if (bundle->Callbacks() & cripts::Callbacks::DO_CACHE_LOOKUP) {
+          if (bundle->Callbacks() & (cripts::Callbacks::DO_CACHE_LOOKUP | 
cripts::Callbacks::GLB_CACHE_LOOKUP)) {
             bundle->doCacheLookup(context);
           }
         }
       }
-      wrap_cache_lookup(context, true, CaseArg);
+      if (context->state.enabled_hooks & cripts::Callbacks::DO_CACHE_LOOKUP) {
+        CDebug("Entering do_cache_lookup()");
+        wrap_cache_lookup(context, true, CaseArg);
+      } else if (context->state.enabled_hooks & 
cripts::Callbacks::GLB_CACHE_LOOKUP) {
+        CDebug("Entering glb_cache_lookup()");
+        wrap_cache_lookup(context, true, CaseArg);
+      }
     }
     break;
+
+  case TS_EVENT_HTTP_PRE_REMAP: // 60016, this is never usable in a remap 
plugin
+    context->state.hook = TS_HTTP_PRE_REMAP_HOOK;
+
+    // Call any bundle callbacks that are registered for this hook
+    if (!context->state.error.Failed() && context->p_instance.Callbacks() & 
cripts::Callbacks::GLB_PRE_REMAP) {
+      for (auto &bundle : context->p_instance.bundles) {
+        if (bundle->Callbacks() & (cripts::Callbacks::GLB_PRE_REMAP)) {
+          bundle->doPostRemap(context);
+        }
+      }
+    }
+
+    if (context->state.enabled_hooks & cripts::Callbacks::GLB_PRE_REMAP) {
+      CDebug("Entering glb_pre_remap()");
+      wrap_glb_pre_remap(context, true, CaseArg);
+    }
+
+    if (!context->state.error.Failed()) {
+      cripts::Cache::URL::_get(context).Update();  // Make sure the cache-key 
gets updated, if modified
+      cripts::Client::URL::_get(context).Update(); // Make sure any changes to 
the request URL is updated
+    }
+    break;
+
   case TS_EVENT_HTTP_POST_REMAP: // 60017
     context->state.hook = TS_HTTP_POST_REMAP_HOOK;
-    CDebug("Entering do_post_remap()");
 
     // Call any bundle callbacks that are registered for this hook
-    if (!context->state.error.Failed() && context->p_instance.Callbacks() & 
cripts::Callbacks::DO_POST_REMAP) {
+    if (!context->state.error.Failed() &&
+        context->p_instance.Callbacks() & (cripts::Callbacks::DO_POST_REMAP | 
cripts::Callbacks::GLB_POST_REMAP)) {
       for (auto &bundle : context->p_instance.bundles) {
-        if (bundle->Callbacks() & cripts::Callbacks::DO_POST_REMAP) {
+        if (bundle->Callbacks() & (cripts::Callbacks::DO_POST_REMAP | 
cripts::Callbacks::GLB_POST_REMAP)) {
           bundle->doPostRemap(context);
         }
       }
     }
-    wrap_post_remap(context, true, CaseArg);
+
+    if (context->state.enabled_hooks & cripts::Callbacks::DO_POST_REMAP) {
+      CDebug("Entering do_post_remap()");
+      wrap_post_remap(context, true, CaseArg);
+    } else if (context->state.enabled_hooks & 
cripts::Callbacks::GLB_POST_REMAP) {
+      CDebug("Entering glb_post_remap()");
+      wrap_glb_post_remap(context, true, CaseArg);
+    }
 
     if (!context->state.error.Failed()) {
       cripts::Cache::URL::_get(context).Update();  // Make sure the cache-key 
gets updated, if modified
       cripts::Client::URL::_get(context).Update(); // Make sure any changes to 
the request URL is updated
     }
     break;
-    // This is for cleanup, and should always be called / wrapped
+
   default:
     CFatal("Cripts continuation: Unknown event %d", event);
     break;
@@ -356,6 +618,137 @@ default_cont(TSCont contp, TSEvent event, void *edata)
   return 0;
 }
 
+// This is the global continuation, used to deal with various hooks as well as 
setting up
+// a per TXN continuation if needed. ToDo: Other non-TXN hooks should be added 
here.
+int
+global_cont(TSCont contp, TSEvent event, void *edata)
+{
+  // Duplicated, but this is cheap and we don't need it in the instance.
+  static bool has_glb_txn_start = 
wrap_glb_txn_start(static_cast<cripts::Context *>(nullptr), false, CaseArg);
+
+  auto glb_ctx       = static_cast<cripts::InstanceContext 
*>(TSContDataGet(contp));
+  auto txnp          = static_cast<TSHttpTxn>(edata);
+  auto ssnp          = TSHttpTxnSsnGet(txnp);
+  auto enabled_hooks = glb_ctx->p_instance.Callbacks();
+
+  switch (event) {
+  case TS_EVENT_HTTP_TXN_START: {
+    auto *context = cripts::Context::Factory(txnp, ssnp, nullptr, 
glb_ctx->p_instance);
+
+    context->state.hook          = TS_HTTP_TXN_START_HOOK;
+    context->state.enabled_hooks = enabled_hooks;
+
+    if (has_glb_txn_start) {
+      wrap_glb_txn_start(context, true, CaseArg);
+    }
+
+    if (enabled_hooks) {
+      context->contp = TSContCreate(http_txn_cont, nullptr);
+      TSContDataSet(context->contp, context);
+      if (enabled_hooks & cripts::Callbacks::GLB_READ_REQUEST) {
+        TSHttpTxnHookAdd(txnp, TS_HTTP_READ_REQUEST_HDR_HOOK, context->contp);
+      }
+      if (enabled_hooks & cripts::Callbacks::GLB_PRE_REMAP) {
+        TSHttpTxnHookAdd(txnp, TS_HTTP_PRE_REMAP_HOOK, context->contp);
+      }
+      if (enabled_hooks & cripts::Callbacks::GLB_POST_REMAP) {
+        TSHttpTxnHookAdd(txnp, TS_HTTP_POST_REMAP_HOOK, context->contp);
+      }
+      if (enabled_hooks & cripts::Callbacks::GLB_CACHE_LOOKUP) {
+        TSHttpTxnHookAdd(txnp, TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, 
context->contp);
+      }
+      if (enabled_hooks & cripts::Callbacks::GLB_SEND_REQUEST) {
+        TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_REQUEST_HDR_HOOK, context->contp);
+      }
+      if (enabled_hooks & cripts::Callbacks::GLB_READ_RESPONSE) {
+        TSHttpTxnHookAdd(txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, context->contp);
+      }
+      if (enabled_hooks & cripts::Callbacks::GLB_SEND_RESPONSE) {
+        TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, context->contp);
+      }
+      TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, context->contp); // 
Release the context later
+    } else {
+      context->Release();
+    }
+  } break;
+
+    // ToDo: Add handlers for other non-HTTP hooks here.
+
+  default:
+    CFatal("Cripts continuation: Unknown event %d", event);
+    break;
+  }
+
+  TSHttpTxnReenable(txnp, TS_EVENT_HTTP_CONTINUE);
+  return 0;
+}
+
+extern void           global_initialization();
+extern pthread_once_t init_once_control;
+
+// This sets up this Cript as a global plugin. This uses the glb_ prefix for 
all
+// the callbacks. This would only be called if the cript is added to 
plugins.config.
+void
+TSPluginInit(int argc, const char *argv[])
+{
+  static bool     has_glb_txn_start = 
wrap_glb_txn_start(static_cast<cripts::Context *>(nullptr), false, CaseArg);
+  static unsigned enabled_txn_hooks =
+    (wrap_glb_read_request(static_cast<cripts::Context *>(nullptr), false, 
CaseArg) ? cripts::Callbacks::GLB_READ_REQUEST :
+                                                                               
       cripts::Callbacks::NONE) |
+    (wrap_glb_pre_remap(static_cast<cripts::Context *>(nullptr), false, 
CaseArg) ? cripts::Callbacks::GLB_PRE_REMAP :
+                                                                               
    cripts::Callbacks::NONE) |
+    (wrap_glb_post_remap(static_cast<cripts::Context *>(nullptr), false, 
CaseArg) ? cripts::Callbacks::GLB_POST_REMAP :
+                                                                               
     cripts::Callbacks::NONE) |
+    (wrap_glb_cache_lookup(static_cast<cripts::Context *>(nullptr), false, 
CaseArg) ? cripts::Callbacks::GLB_CACHE_LOOKUP :
+                                                                               
       cripts::Callbacks::NONE) |
+    (wrap_glb_send_request(static_cast<cripts::Context *>(nullptr), false, 
CaseArg) ? cripts::Callbacks::GLB_SEND_REQUEST :
+                                                                               
       cripts::Callbacks::NONE) |
+    (wrap_glb_read_response(static_cast<cripts::Context *>(nullptr), false, 
CaseArg) ? cripts::Callbacks::GLB_READ_RESPONSE :
+                                                                               
        cripts::Callbacks::NONE) |
+    (wrap_glb_send_response(static_cast<cripts::Context *>(nullptr), false, 
CaseArg) ? cripts::Callbacks::GLB_SEND_RESPONSE :
+                                                                               
        cripts::Callbacks::NONE) |
+    (wrap_glb_txn_close(static_cast<cripts::Context *>(nullptr), false, 
CaseArg) ? cripts::Callbacks::GLB_TXN_CLOSE :
+                                                                               
    cripts::Callbacks::NONE);
+  // ToDo: Add more global hooks here in enabled_other_hooks
+
+  TSPluginRegistrationInfo info;
+  auto                    *inst = new cripts::Instance(argc, argv, false);
+
+  info.plugin_name   = (char *)inst->plugin_debug_tag.c_str();
+  info.vendor_name   = (char *)"Apache Software Foundation";
+  info.support_email = (char *)"[email protected]";
+
+  if (TS_SUCCESS != TSPluginRegister(&info)) {
+    TSError("[%s] plugin registration failed", info.plugin_name);
+    delete inst;
+    return;
+  }
+
+  // ToDo: This InstanceContext should also be usabled / used by other 
non-HTTP hooks.
+  cripts::InstanceContext *context = new cripts::InstanceContext(*inst);
+
+  pthread_once(&init_once_control, global_initialization);
+  bool needs_glb_init = wrap_glb_init(context, false, CaseArg);
+
+  if (needs_glb_init) {
+    wrap_glb_init(context, true, CaseArg);
+  }
+
+  if (has_glb_txn_start || enabled_txn_hooks > 0) {
+    auto contp = TSContCreate(global_cont, nullptr);
+
+    inst->NeedCallback(enabled_txn_hooks);
+    TSContDataSet(contp, context);
+    TSHttpHookAdd(TS_HTTP_TXN_START_HOOK, contp); // This acts similarly to 
the DoRemap callback
+  } else {
+    delete context;
+    delete inst;
+    TSError("[%s] - No global hooks enabled", info.plugin_name);
+  }
+}
+
+// This section is for Cripts as a remap plugin. They all use the do_ prefix 
for all
+// callbacks.
 TSReturnCode
 TSRemapInit(TSRemapInterface *api_info, char *errbuf, int errbuf_size)
 {
@@ -375,28 +768,25 @@ TSRemapInit(TSRemapInterface *api_info, char *errbuf, int 
errbuf_size)
     return TS_ERROR;
   }
 
-  // This is to check, and call, the Cript's do_init() if provided.
-  // Note that the context here is not a Cript context, but rather tha API info
-  extern void           global_initialization();
-  extern pthread_once_t init_once_control;
-
   pthread_once(&init_once_control, global_initialization);
 
+  // This is to check, and call, the Cript's do_init() if provided.
+  // Note that the context here is not a Cript context, but rather tha API info
   bool needs_plugin_init = wrap_plugin_init(api_info, false, CaseArg);
 
   if (needs_plugin_init) {
     wrap_plugin_init(api_info, true, CaseArg);
   }
 
-  // TSDebug("Cript", "Remap plugin %s is successfully initialized", 
__BASE_FILE__);
-
   return TS_SUCCESS;
 }
 
 TSReturnCode
-TSRemapNewInstance(int argc, char *argv[], void **ih, char * /* errbuf 
ATS_UNUSED */, int /* errbuf_size ATS_UNUSED */)
+TSRemapNewInstance(int argc, char *argv[], void **ih, char * /* errbuf 
ATS_UNUSED */
+                   ,
+                   int /* errbuf_size ATS_UNUSED */)
 {
-  auto                   *inst = new cripts::Instance(argc, argv);
+  auto                   *inst = new cripts::Instance(argc, const_cast<const 
char **>(argv));
   cripts::InstanceContext context(*inst);
   bool                    needs_create_instance = 
wrap_create_instance(&context, false, CaseArg);
 
@@ -461,14 +851,20 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, 
TSRemapRequestInfo *rri)
 {
   // Check to see if we need to setup future hooks with a continuation. This
   // should only happen once.
-  static bool     cript_needs_do_remap = 
wrap_do_remap(static_cast<cripts::Context *>(nullptr), false, CaseArg);
-  static unsigned cript_enabled_hooks =
-    (wrap_post_remap(static_cast<cripts::Context *>(nullptr), false, CaseArg) 
? cripts::Callbacks::DO_POST_REMAP : 0) |
-    (wrap_send_response(static_cast<cripts::Context *>(nullptr), false, 
CaseArg) ? cripts::Callbacks::DO_SEND_RESPONSE : 0) |
-    (wrap_send_request(static_cast<cripts::Context *>(nullptr), false, 
CaseArg) ? cripts::Callbacks::DO_SEND_REQUEST : 0) |
-    (wrap_read_response(static_cast<cripts::Context *>(nullptr), false, 
CaseArg) ? cripts::Callbacks::DO_READ_RESPONSE : 0) |
-    (wrap_cache_lookup(static_cast<cripts::Context *>(nullptr), false, 
CaseArg) ? cripts::Callbacks::DO_CACHE_LOOKUP : 0) |
-    (wrap_txn_close(static_cast<cripts::Context *>(nullptr), false, CaseArg) ? 
cripts::Callbacks::DO_TXN_CLOSE : 0);
+  static bool     needs_do_remap = wrap_do_remap(static_cast<cripts::Context 
*>(nullptr), false, CaseArg);
+  static uint32_t enabled_hooks =
+    (wrap_post_remap(static_cast<cripts::Context *>(nullptr), false, CaseArg) 
? cripts::Callbacks::DO_POST_REMAP :
+                                                                               
 cripts::Callbacks::NONE) |
+    (wrap_cache_lookup(static_cast<cripts::Context *>(nullptr), false, 
CaseArg) ? cripts::Callbacks::DO_CACHE_LOOKUP :
+                                                                               
   cripts::Callbacks::NONE) |
+    (wrap_send_request(static_cast<cripts::Context *>(nullptr), false, 
CaseArg) ? cripts::Callbacks::DO_SEND_REQUEST :
+                                                                               
   cripts::Callbacks::NONE) |
+    (wrap_read_response(static_cast<cripts::Context *>(nullptr), false, 
CaseArg) ? cripts::Callbacks::DO_READ_RESPONSE :
+                                                                               
    cripts::Callbacks::NONE) |
+    (wrap_send_response(static_cast<cripts::Context *>(nullptr), false, 
CaseArg) ? cripts::Callbacks::DO_SEND_RESPONSE :
+                                                                               
    cripts::Callbacks::NONE) |
+    (wrap_txn_close(static_cast<cripts::Context *>(nullptr), false, CaseArg) ? 
cripts::Callbacks::DO_TXN_CLOSE :
+                                                                               
cripts::Callbacks::NONE);
 
   TSHttpSsn ssnp         = TSHttpTxnSsnGet(txnp);
   auto     *inst         = static_cast<cripts::Instance *>(ih);
@@ -477,9 +873,9 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, TSRemapRequestInfo 
*rri)
   bool      keep_context = false;
 
   context->state.hook          = TS_HTTP_READ_REQUEST_HDR_HOOK; // Not quite 
true
-  context->state.enabled_hooks = (cript_enabled_hooks | bundle_cbs);
+  context->state.enabled_hooks = (enabled_hooks | bundle_cbs);
 
-  if (cript_needs_do_remap || bundle_cbs & cripts::Callbacks::DO_REMAP) {
+  if (needs_do_remap || bundle_cbs & cripts::Callbacks::DO_REMAP) {
     CDebug("Entering do_remap()");
     for (auto &bundle : context->p_instance.bundles) {
       bundle->doRemap(context);
@@ -495,32 +891,32 @@ TSRemapDoRemap(void *ih, TSHttpTxn txnp, 
TSRemapRequestInfo *rri)
     cripts::Client::URL::_get(context).Update(); // Make sure any changes to 
the request URL is updated
 
     if (context->state.enabled_hooks >= cripts::Callbacks::DO_POST_REMAP) {
-      context->default_cont = TSContCreate(default_cont, nullptr);
-      TSContDataSet(context->default_cont, context);
+      context->contp = TSContCreate(http_txn_cont, nullptr);
+      TSContDataSet(context->contp, context);
 
       if (context->state.enabled_hooks & cripts::Callbacks::DO_POST_REMAP) {
-        TSHttpTxnHookAdd(txnp, TS_HTTP_POST_REMAP_HOOK, context->default_cont);
+        TSHttpTxnHookAdd(txnp, TS_HTTP_POST_REMAP_HOOK, context->contp);
       }
 
       if (context->state.enabled_hooks & cripts::Callbacks::DO_SEND_RESPONSE) {
-        TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, 
context->default_cont);
+        TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_RESPONSE_HDR_HOOK, context->contp);
       }
 
       if (context->state.enabled_hooks & cripts::Callbacks::DO_SEND_REQUEST) {
-        TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_REQUEST_HDR_HOOK, 
context->default_cont);
+        TSHttpTxnHookAdd(txnp, TS_HTTP_SEND_REQUEST_HDR_HOOK, context->contp);
       }
 
       if (context->state.enabled_hooks & cripts::Callbacks::DO_READ_RESPONSE) {
-        TSHttpTxnHookAdd(txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, 
context->default_cont);
+        TSHttpTxnHookAdd(txnp, TS_HTTP_READ_RESPONSE_HDR_HOOK, context->contp);
       }
 
       if (context->state.enabled_hooks & cripts::Callbacks::DO_CACHE_LOOKUP) {
-        TSHttpTxnHookAdd(txnp, TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, 
context->default_cont);
+        TSHttpTxnHookAdd(txnp, TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK, 
context->contp);
       }
 
-      // This is always needed when we have at least one Txn Hook. It will also
+      // This iremaps needed when we have at least one Txn Hook. It will also
       // call the Cript's callback, if it exists.
-      TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, context->default_cont);
+      TSHttpTxnHookAdd(txnp, TS_HTTP_TXN_CLOSE_HOOK, context->contp);
 
       // Make sure we keep the context
       keep_context = true;
diff --git a/include/cripts/Instance.hpp b/include/cripts/Instance.hpp
index ca6ae766b4..b5317f9efd 100644
--- a/include/cripts/Instance.hpp
+++ b/include/cripts/Instance.hpp
@@ -44,7 +44,7 @@ public:
   void operator=(const self_type &) = delete;
 
   // This has to be in the .hpp file, otherwise we will not get the correct 
debug tag!
-  Instance(int argc, char *argv[]) { _initialize(argc, argv, __BASE_FILE__); }
+  Instance(int argc, const char *argv[], bool remap = true) { 
_initialize(argc, argv, __BASE_FILE__, remap); }
   ~Instance()
   {
     plugins.clear();
@@ -58,7 +58,7 @@ public:
   bool DeletePlugin(const cripts::string &tag);
   void AddBundle(cripts::Bundle::Base *bundle);
 
-  // This allows Bundles to require hooks as well.
+  // This allows Bundles and global plugins to require hooks as well.
   void
   NeedCallback(cripts::Callbacks cb)
   {
@@ -121,11 +121,11 @@ public:
   std::vector<cripts::Bundle::Base *>            bundles;
 
 private:
-  void _initialize(int argc, char *argv[], const char *filename);
+  void _initialize(int argc, const char *argv[], const char *filename, bool 
remap);
 
   size_t   _size      = 0;
   bool     _failed    = false;
-  unsigned _callbacks = 0;
+  uint32_t _callbacks = 0;
   DbgCtl   dbg_ctl_cript;
 }; // End class Instance
 
diff --git a/include/cripts/Preamble.hpp b/include/cripts/Preamble.hpp
index 64a6c254d9..518b3bfec2 100644
--- a/include/cripts/Preamble.hpp
+++ b/include/cripts/Preamble.hpp
@@ -41,10 +41,10 @@
 // Having both of these for now, until we decide which we like better...
 #define do_remap()           void _do_remap(cripts::Context *context)
 #define do_post_remap()      void _do_post_remap(cripts::Context *context)
-#define do_send_response()   void _do_send_response(cripts::Context *context)
 #define do_cache_lookup()    void _do_cache_lookup(cripts::Context *context)
 #define do_send_request()    void _do_send_request(cripts::Context *context)
 #define do_read_response()   void _do_read_response(cripts::Context *context)
+#define do_send_response()   void _do_send_response(cripts::Context *context)
 #define do_txn_close()       void _do_txn_close(cripts::Context *context)
 #define do_init()            void _do_init(TSRemapInterface *)
 #define do_create_instance() void _do_create_instance(cripts::InstanceContext 
*context)
@@ -52,15 +52,37 @@
 
 #define DoRemap()          void _do_remap(cripts::Context *context)
 #define DoPostRemap()      void _do_post_remap(cripts::Context *context)
-#define DoSendResponse()   void _do_send_response(cripts::Context *context)
 #define DoCacheLookup()    void _do_cache_lookup(cripts::Context *context)
 #define DoSendRequest()    void _do_send_request(cripts::Context *context)
 #define DoReadResponse()   void _do_read_response(cripts::Context *context)
+#define DoSendResponse()   void _do_send_response(cripts::Context *context)
 #define DoTxnClose()       void _do_txn_close(cripts::Context *context)
 #define DoInit()           void _do_init(TSRemapInterface *)
 #define DoCreateInstance() void _do_create_instance(cripts::InstanceContext 
*context)
 #define DoDeleteInstance() void _do_delete_instance(cripts::InstanceContext 
*context)
 
+// For the global plugins
+#define glb_txn_start()     void _glb_txn_start(cripts::Context *context)
+#define glb_read_request()  void _glb_read_request(cripts::Context *context)
+#define glb_pre_remap()     void _glb_pre_remap(cripts::Context *context)
+#define glb_post_remap()    void _glb_post_remap(cripts::Context *context)
+#define glb_cache_lookup()  void _glb_cache_lookup(cripts::Context *context)
+#define glb_send_request()  void _glb_send_request(cripts::Context *context)
+#define glb_read_response() void _glb_read_response(cripts::Context *context)
+#define glb_send_response() void _glb_send_response(cripts::Context *context)
+#define glb_txn_close()     void _glb_txn_close(cripts::Context *context)
+#define glb_init()          void _glb_init(cripts::InstanceContext *context)
+
+#define GlbTxnStart()     void _glb_txn_start(cripts::Context *context)
+#define GlbReadRequest()  void _glb_read_request(cripts::Context *context)
+#define GlbPreRemap()     void _glb_pre_remap(cripts::Context *context)
+#define GlbPostRemap()    void _glb_post_remap(cripts::Context *context)
+#define GlbSendRequest()  void _glb_send_request(cripts::Context *context)
+#define GlbReadResponse() void _glb_read_response(cripts::Context *context)
+#define GlbSendResponse() void _glb_send_response(cripts::Context *context)
+#define GlbTxnClose()     void _glb_txn_close(cripts::Context *context)
+#define GlbInit()         void _glb_init(cripts::InstanceContext *context)
+
 #include "cripts/Headers.hpp"
 #include "cripts/Urls.hpp"
 #include "cripts/Configs.hpp"
diff --git a/include/cripts/Transaction.hpp b/include/cripts/Transaction.hpp
index 82a5c8c69e..9bcdb83d33 100644
--- a/include/cripts/Transaction.hpp
+++ b/include/cripts/Transaction.hpp
@@ -29,15 +29,24 @@
 namespace cripts
 {
 // This is a bitfield, used to disable a particular callback from a previous 
hook
-enum Callbacks : std::uint8_t {
-  NONE             = 0,
-  DO_REMAP         = 1,
-  DO_POST_REMAP    = 2,
-  DO_SEND_RESPONSE = 4,
-  DO_CACHE_LOOKUP  = 8,
-  DO_SEND_REQUEST  = 16,
-  DO_READ_RESPONSE = 32,
-  DO_TXN_CLOSE     = 64
+enum Callbacks : std::uint32_t {
+  NONE              = 0,
+  DO_REMAP          = 1 << 0,
+  DO_POST_REMAP     = 1 << 1,
+  DO_CACHE_LOOKUP   = 1 << 2,
+  DO_SEND_REQUEST   = 1 << 3,
+  DO_READ_RESPONSE  = 1 << 4,
+  DO_SEND_RESPONSE  = 1 << 5,
+  DO_TXN_CLOSE      = 1 << 6,
+  GLB_TXN_START     = 1 << 7,
+  GLB_READ_REQUEST  = 1 << 8,
+  GLB_PRE_REMAP     = 1 << 9,
+  GLB_POST_REMAP    = 1 << 10,
+  GLB_CACHE_LOOKUP  = 1 << 11,
+  GLB_SEND_REQUEST  = 1 << 12,
+  GLB_READ_RESPONSE = 1 << 13,
+  GLB_SEND_RESPONSE = 1 << 14,
+  GLB_TXN_CLOSE     = 1 << 15,
 };
 
 class Transaction
@@ -58,7 +67,7 @@ public:
   // Keep track of which hook we're currently in. ToDo: Do we still need this 
with the
   // tests being moved out to the linter?
   TSHttpHookID hook          = TS_HTTP_LAST_HOOK;
-  unsigned     enabled_hooks = 0; // Which hooks are enabled, other than the 
mandatory ones
+  uint32_t     enabled_hooks = 0; // Which hooks are enabled, other than the 
mandatory ones
 
   [[nodiscard]] bool
   Aborted() const
diff --git a/src/cripts/Instance.cc b/src/cripts/Instance.cc
index af387a08a2..598e992d17 100644
--- a/src/cripts/Instance.cc
+++ b/src/cripts/Instance.cc
@@ -25,17 +25,19 @@ namespace cripts
 {
 
 void
-Instance::_initialize(int argc, char *argv[], const char *filename)
+Instance::_initialize(int argc, const char *argv[], const char *filename, bool 
remap)
 {
-  from_url = argv[0];
-  to_url   = argv[1];
-  for (int i = 2; i < argc; i++) {
-    auto s = cripts::string(argv[i]);
-
-    s.trim("\"\'");
-    data[i - 2] = s;
+  if (remap) {
+    from_url = argv[0];
+    to_url   = argv[1];
+    for (int i = 2; i < argc; i++) {
+      auto s = cripts::string(argv[i]);
+
+      s.trim("\"\'");
+      data[i - 2] = s;
+    }
+    _size = argc - 2;
   }
-  _size = argc - 2;
 
   // Set the debug tag for this plugin, slightly annoying that we have to 
calculate
   // this for every instantiation, but in general, each Cript is used 
primarily for
@@ -53,7 +55,7 @@ Instance::_initialize(int argc, char *argv[], const char 
*filename)
   }
 
   dbg_ctl_cript.set(plugin_debug_tag.c_str());
-} // namespace Instance::_initialize(intargc,char*argv[],constchar*filename)
+}
 
 bool
 Instance::AddPlugin(const cripts::string &tag, const cripts::string &plugin, 
const Plugin::Options &options)
diff --git a/src/cripts/Urls.cc b/src/cripts/Urls.cc
index 7fcdfd2ba9..9d0423371a 100644
--- a/src/cripts/Urls.cc
+++ b/src/cripts/Urls.cc
@@ -445,9 +445,20 @@ Client::URL::_initialize(cripts::Context *context)
 {
   Url::_initialize(&context->state);
 
-  _bufp    = context->rri->requestBufp;
-  _hdr_loc = context->rri->requestHdrp;
-  _urlp    = context->rri->requestUrl;
+  if (context->rri) {
+    _bufp    = context->rri->requestBufp;
+    _hdr_loc = context->rri->requestHdrp;
+    _urlp    = context->rri->requestUrl;
+  } else {
+    Client::Request &req = Client::Request::_get(context); // Repurpose / 
create the shared request object
+
+    _bufp    = req.BufP();
+    _hdr_loc = req.MLoc();
+
+    if (TSHttpHdrUrlGet(_bufp, _hdr_loc, &_urlp) != TS_SUCCESS) {
+      context->state.error.Fail();
+    }
+  }
 }
 
 Client::URL &


Reply via email to