Remap Plugins

Remap plugins are called during remap (URL rewriting). The particular plugins and the order is determined by the remap rule. The remap.config file can contain explicit references to remap plugins in a rule and the presence of such a reference in a rule causes the plugin to be invoked when the rule is matched. For example, a rule such as

map http://example.one/ http://example.two/ @plugin=example.so @pparam=first_arg @pparm=second_arg

will, if matched, cause the plugin "example.so" to be called with parameters http://example.one/, http://example.two/, "first_arg" and "second_arg". Please keep in mind that "from" URL and "to" URL will be converted to their canonical view.

A key difference between global and remap plugins is reconfiguration and reloading. If remap.config is reloaded, then all remap plugins are reconfigured based on the new version of the file. Global plugins need to handle their own configuration reloading, if any.

In addition, as of Traffic Server 9.0, remap plugins can be reloaded during runtime. During a remap.config reload, if the plugin image file has changed, a new one is loaded and used.

All of the externally invoked functions must be declared as extern "C" in order to be correctly located by the Traffic Server core. This is already done if include/ts/remap.h is included, otherwise it must be done explicitly.

Initialization

If any rule uses a plugin, the remap configuration loading will load the dynamic library and then call TSRemapInit(). The plugin must return TS_SUCCESS or the configuration loading will fail. If there is an error during the invocation of this function a C string style message should be placed in errbuff, taking note of the maximum size of the buffer passed in errbuff_size. The message is checked if the function returns a value other than TS_SUCCESS.

If TSRemapInit() returns TS_ERROR then the remap configuration loading is aborted immediately.

This function should perform any plugin global initialization, such as setting up static data tables. It only be called immediately after the dynamic library is loaded from disk.

Configuration

For each plugin invocation in a remap rule, TSRemapNewInstance() is called.

The parameters argc, argv specify an array of arguments to the invocation instance in the standard way. argc is the number of arguments present and argv is an array of pointers, each of which points to a plugin parameter. The number of valid elements is argc. Note these pointers are valid only for the duration of the function call. If any part of them need persistent storage, that must be provided by the plugin.

ih is for invocation instance storage data. This initially points at a nullptr. If that pointer is updated the new value will be preserved and passed back to the plugin in later callbacks. This enables it to serve to identify which particular rule was matched and provide context data. The standard use is to allocate a class instance, store rule relevant context data in that instance, and update ih to point at the instance. The most common data is that derived from the invocation arguments passed in argc, argv.

errbuff and errbuff_size specify a writeable buffer used to report errors. Error messages must be C strings and must fit in the buffer, including the terminating null.

In essence, TSRemapNewInstance() is called to create an invocation instance for the plugin to store rule local data. If the plugin is invoked multiples time on a rule, this will be called multiple times for the rule, once for each invocation. Only the value store in ih will be available when the rule is actually matched. In particular the plugin arguments will not be available.

Calls to TSRemapNewInstance() are guaranteed to be serialized. All calls to TSRemapNewInstance() for a given new configuration are guaranteed to be called and completed before any calls to TSRemapDoRemap().

If there is an error then the callback should return TS_ERROR and fill in the errbuff with a C-string describing the error. Otherwise the function must return TS_SUCCESS.

If TSRemapNewInstance() returns TS_ERROR then the remap configuration loading is aborted immediately.

Configuration reload notifications

Most of the plugins is assumed to use per-plugin-instance data-structures when reloading their configs and only a few of them that wish to optimize performance or deal with the complexities of using a per-plugin DSO "global" data-structures would use plugin configuration reload notifications like TSRemapPreConfigReload() and TSRemapPostConfigReload().

Instead of trying to foresee the needs or the expectations of each use-case, a more "open-ended" and straight-forward design was chosen for the configuration reload notifications. The notifications are broadcast to all loaded plugins at the moments before and after the reload attempt, regardless of whether a plugin is part of the new configuration or not.

TSRemapPreConfigReload() is called before the parsing of a new remap configuration starts to notify plugins of the coming configuration reload. It is called on all already loaded plugins, invoked by current and all previous still used configurations. This is an optional entry point.

TSRemapPostConfigReload() is called to indicate the end of the new remap configuration load. It is called on the newly and previously loaded plugins, invoked by the new, current and previous still used configurations. It also indicates whether the configuration reload was successful by passing TSREMAP_CONFIG_RELOAD_FAILURE in case of failure and to notify the plugins if they are going to be part of the new configuration by passing TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_USED or TSREMAP_CONFIG_RELOAD_SUCCESS_PLUGIN_UNUSED. This is an optional entry point.

These calls are called per plugin, not per invocation of the plugin in remap.config and only will be called if the plugin was instantiated by at least one configuration loaded after Traffic Server started and at least one configuration using it is still loaded.

TSRemapPreConfigReload() will be called serially for all loaded plugins before any call to TSRemapNewInstance() during parsing of the new configuration.

TSRemapPostConfigReload() will be called serially for all plugins after all calls to TSRemapNewInstance() during parsing of the new configuration.

The intention of these callbacks can be demonstrated with the following use-case. A plugin could use TSRemapPreConfigReload() as a signal to drop (or allocate) temporary per plugin data structures. These structures can be created (or updated) as needed when a plugin invocation instance is loaded (TSRemapNewInstance() is called). Then it could be used in subsequent invocation instances loading. After the configuration reload is done TSRemapPostConfigReload() could be used to confirm the data structures update if reload was successful, recover / clean-up after a failed reload attempt, or if so wishes to ignore the notification if plugin is not part of the new configuration..

Runtime

At runtime, if a remap rule is matched, the plugin is invoked by calling TSRemapDoRemap(). This function is responsible for performing the plugin operation for the transaction.

ih is the same value set in TSRemapNewInstance() for the invocation instance. This is not examined or checked by the core. rh is the transaction for which the rule matched. rri is information about the rule and the transaction.

The callback is required to return a TSRemapStatus indicating whether it performed a remap. This is used for verifying a request was remapped if remapping is required. This can also be used to prevent further remapping, although this should be used with caution.

Calls to TSRemapDoRemap() are not serialized, they can be concurrent, even for the same invocation instance. However, the callbacks for a single rule for a single transaction are serialized in the order the plugins are invoked in the rule.

No calls to TSRemapDoRemap() will occur before TSRemapPostConfigReload() for all plugin instances invoked by the new configuration.

The old configurations, if any, are still active during the calls to TSRemapPreConfigReload() and TSRemapPreConfigReload() and therefore calls to TSRemapDoRemap() may occur concurrently with those functions.

Cleanup

When a new remap.config is loaded successfully, the prior configuration is cleaned up. For each call to TSRemapNewInstance() a corresponding call to TSRemapDeleteInstance() is called. The only argument is the invocation instance handle, originally provided by the plugin to TSRemapNewInstance(). This is expected to suffice for the plugin to clean up any rule specific data. Calls to TSRemapDeleteInstance() will be serial for all plugin invocations in a remap configuration.

If no rule uses a plugin, it may be unloaded. In that case TSRemapDone() is called. This is an optional entry point, a plugin is not required to provide it. It corresponds to TSRemapInit(). It is called once per plugin, not per plugin invocation.