Cripts for global plugin
In addition to being 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.
Global plugins must be compiled manually and loaded through the standard ATS plugin configuration. Here's a complete example:
#include <cripts/Preamble.hpp>
glb_init()
{
CDebug("Global Cript plugin initialized");
}
glb_read_request()
{
borrow url = cripts::Client::URL::Get();
borrow req = cripts::Client::Request::Get();
// Example: Add a custom header to all requests
req["X-Global-Plugin"] = "active";
// Example: Filter query parameters globally
url.query.Keep({"foo", "bar"});
}
glb_send_response()
{
borrow resp = cripts::Client::Response::Get();
// Example: Add response header to all responses
resp["X-Processed-By"] = "Cripts-Global";
}
#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
Let's look at the normal hooks that are available in Cripts. Note here that the name of the function dictates the underlying ATS hook.
glb_init()
This callback is called when the plugin is loaded. This is where you can setup any global state that you need, initialize metrics, or perform other one-time setup tasks.
Example:
glb_init()
{
CDebug("Initializing global Cript plugin");
// Setup global metrics, configurations, etc.
}
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.
This hook is useful for initializing per-transaction data or setting up transaction-specific state.
Example:
glb_txn_start()
{
// Initialize transaction data
txn_data[0] = integer(0); // Request counter
txn_data[1] = cripts::Time::Local::Now().Epoch();
}
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
have not yet been applied, so the URL may not be the final URL, or even complete.
This is the earliest point where you can examine and modify the client request.
Example:
glb_read_request()
{
borrow req = cripts::Client::Request::Get();
borrow url = cripts::Client::URL::Get();
// Log all incoming requests
CDebug("Request: {} {}", req.method, url.path);
// Add tracking headers
req["X-Request-ID"] = cripts::UUID::Request::Get();
}
glb_pre_remap()
The glb_pre_remap()
hook is called just before remap rules are processed. This hook
may not be particularly useful in most Cripts, as remap rules have not yet been applied.
We've added it for completeness and advanced use cases.
glb_post_remap()
The glb_post_remap()
hook is called after remap rules have been applied. This is the
closest equivalent to the do_remap()
hook in remap rules, but operates globally
across all transactions.
At this point, the request URL has been finalized and you can make decisions based on the final destination.
Example:
glb_post_remap()
{
borrow url = cripts::Client::URL::Get();
// Apply global policies after remap
if (url.host == "sensitive.example.com") {
borrow req = cripts::Client::Request::Get();
req["X-Security-Level"] = "high";
}
}
glb_cache_lookup()
The glb_cache_lookup()
hook is called when a cache lookup is performed. This allows
you to take action based on whether the content was found in cache or not, and to
modify cache behavior globally.
This is equivalent to the do_cache_lookup()
hook in remap rules.
Example:
glb_cache_lookup()
{
auto status = transaction.LookupStatus();
CDebug("Cache lookup status: {}", static_cast<int>(status));
// Global cache policy decisions can be made here
}
glb_send_request()
The glb_send_request()
hook is called when the request is ready to be sent to the
origin server. This is the main hook for globally modifying requests to origin servers.
This is equivalent to the do_send_request()
hook in remap rules.
Example:
glb_send_request()
{
borrow req = cripts::Server::Request::Get();
// Add global origin request headers
req["X-Forwarded-By"] = "ATS-Cripts";
req["X-Request-Time"] = cripts::Time::Local::Now().Epoch();
}
glb_read_response()
The glb_read_response()
hook is called when the response is being read from the origin
server. This is the main hook for globally modifying responses from origin servers before
they are cached or sent to clients.
This is equivalent to the do_read_response()
hook in remap rules.
Example:
glb_read_response()
{
borrow resp = cripts::Server::Response::Get();
// Global response processing
if (resp.status == 500) {
CDebug("Server error detected from origin");
// Could implement global error handling here
}
}
glb_send_response()
The glb_send_response()
hook is called when the response is ready to be sent to the
client. This allows you to make final modifications to the response headers and implement
global response policies.
This is equivalent to the do_send_response()
hook in remap rules.
Example:
glb_send_response()
{
borrow resp = cripts::Client::Response::Get();
// Add global response headers
resp["X-Served-By"] = "ATS-Cripts-Global";
resp["X-Response-Time"] = cripts::Time::Local::Now().Epoch();
// Global security headers
resp["X-Content-Type-Options"] = "nosniff";
resp["X-Frame-Options"] = "DENY";
}
glb_txn_close()
The glb_txn_close()
hook is called when the transaction is closed. This is useful
for cleanup, logging, and metrics collection.
This is equivalent to the do_txn_close()
hook in remap rules.
Example:
glb_txn_close()
{
// Log transaction completion
auto start_time = AsInteger(txn_data[1]);
auto duration = cripts::Time::Local::Now().Epoch() - start_time;
CDebug("Transaction completed in {} seconds", duration);
// Update global metrics
// Cleanup transaction-specific resources
}
Hook Execution Order
The global hooks are executed in the following order during a typical transaction:
glb_init()
- Called once when plugin loadsglb_txn_start()
- Transaction beginsglb_read_request()
- Client request is readglb_pre_remap()
- Before remap processingglb_post_remap()
- After remap processingglb_cache_lookup()
- Cache lookup performedglb_send_request()
- Request sent to origin (if cache miss)glb_read_response()
- Response read from originglb_send_response()
- Response sent to clientglb_txn_close()
- Transaction cleanup
注釈
Not all hooks are called for every transaction. For example, glb_send_request()
and glb_read_response()
are only called on cache misses when ATS needs to
contact the origin server.
Best Practices
When writing global Cripts plugins:
Performance Considerations: Global hooks affect all traffic, so keep processing lightweight and efficient.
Conditional Logic: Use conditional logic to apply policies only where needed:
glb_read_request() { borrow url = cripts::Client::URL::Get(); // Only process specific hosts if (url.host.find("api.") == 0) { // API-specific processing } }
Error Handling: Implement proper error handling to avoid affecting other traffic:
glb_send_response() { if (something_went_wrong) { CDebug("Error in global response processing"); // Don't let errors affect the response } else { // Continue with normal processing borrow resp = cripts::Client::Response::Get(); resp["X-Processed-By"] = "Cripts-Global"; } }
Metrics and Monitoring: Use global plugins for comprehensive monitoring:
glb_init() { instance.metrics[0] = cripts::Metrics::Counter::Create("global.requests.total"); instance.metrics[1] = cripts::Metrics::Counter::Create("global.errors.total"); }
Resource Management: Clean up any resources in
glb_txn_close()
to prevent leaks.