Add to API to get a strategy during TSRemapNewInstance - #12593
Open
traeak wants to merge 4 commits into
Open
Conversation
traeak
force-pushed
the
strategy_init
branch
2 times, most recently
from
October 27, 2025 12:44
fd6730e to
7e032e6
Compare
traeak
marked this pull request as ready for review
October 28, 2025 19:45
traeak
force-pushed
the
strategy_init
branch
3 times, most recently
from
November 5, 2025 13:29
ada93a4 to
00c8021
Compare
Contributor
There was a problem hiding this comment.
Pull Request Overview
This PR refactors the next-hop strategy API to separate transaction-level and remap-level strategy operations, introducing new TSRemap* functions for use during TSRemapNewInstance. The API functions have been renamed for consistency and clarity.
- Renamed
TSHttpNextHopStrategyNameGettoTSNextHopStrategyNameGet - Renamed
TSHttpTxnNextHopNamedStrategyGettoTSHttpTxnNextHopStrategyFind - Added new TSRemap* API functions for strategy operations during remap rule loading
Reviewed Changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/proxy/http/remap/RemapConfig.cc | Sets up url_mapping::instance for TSRemap* API access and assigns strategyFactory to new mappings |
| src/api/InkAPI.cc | Implements new TSRemap* functions and renames existing API functions |
| plugins/regex_remap/regex_remap.cc | Updates to use new TSRemapNextHopStrategyFind API during initialization |
| plugins/lua/ts_lua_http.cc | Updates function calls to use renamed API functions |
| plugins/header_rewrite/operators.h | Changes internal storage from Value to explicit strategy pointer |
| plugins/header_rewrite/operators.cc | Refactors to use TSRemapNextHopStrategyFind during initialization and removes runtime hook |
| plugins/header_rewrite/conditions.cc | Updates to use renamed TSNextHopStrategyNameGet function |
| include/ts/ts.h | Updates API documentation and function declarations |
| include/proxy/http/remap/UrlMapping.h | Adds strategyFactory pointer and static instance pointer to url_mapping |
| doc/developer-guide/api/functions/*.en.rst | Adds/updates documentation for new and renamed API functions |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
traeak
force-pushed
the
strategy_init
branch
2 times, most recently
from
November 17, 2025 15:05
6663eb1 to
0650be2
Compare
zwoop
requested changes
Mar 5, 2026
traeak
force-pushed
the
strategy_init
branch
2 times, most recently
from
March 17, 2026 20:31
9a076e8 to
8ddaa2d
Compare
Comment on lines
1645
to
1661
| OperatorSetNextHopStrategy::initialize(Parser &p) | ||
| { | ||
| Operator::initialize(p); | ||
| _stratname = p.get_arg(); | ||
|
|
||
| _value.set_value(p.get_arg(), this); | ||
| Dbg(pi_dbg_ctl, "OperatorSetNextHopStrategy::initialie: %s", _value.get_value().c_str()); | ||
| if (_stratname.empty() || "null" == _stratname) { | ||
| Dbg(pi_dbg_ctl, "OperatorSetNextHopStrategy() 'clear'"); | ||
| } else { | ||
| _strategy = TSRemapNextHopStrategyFind(_stratname.c_str()); | ||
| if (nullptr == _strategy) { | ||
| TSError("[%s] Failed to get strategy '%s'", PLUGIN_NAME, _stratname.c_str()); | ||
| _apply = false; | ||
| } else { | ||
| Dbg(pi_dbg_ctl, "OperatorSetNextHopStrategy() '%s'", _stratname.c_str()); | ||
| } | ||
| } | ||
| } |
Comment on lines
1670
to
1676
| OperatorSetNextHopStrategy::exec(const Resources &res) const | ||
| { | ||
| if (!res.state.txnp) { | ||
| TSError("[%s] OperatorSetNextHopStrategy() failed. Transaction is null", PLUGIN_NAME); | ||
| if (!_apply) { | ||
| Dbg(pi_dbg_ctl, "OperatorSetNextHopStrategy::exec: do nothing"); | ||
| return true; | ||
| } | ||
|
|
||
| auto const txnp = res.state.txnp; |
Comment on lines
+1682
to
1691
| if (nullptr == _strategy) { | ||
| Dbg(pi_dbg_ctl, "OperatorSetNextHopStrategy::exec: Clearing strategy"); | ||
| } else { | ||
| Dbg(pi_dbg_ctl, " Setting strategy '%s'", value.c_str()); | ||
| TSHttpTxnNextHopStrategySet(txnp, stratptr); | ||
| Dbg(pi_dbg_ctl, "OperatorSetNextHopStrategy::exec: Setting strategy to '%s'", _stratname.c_str()); | ||
| } | ||
|
|
||
| TSHttpTxnNextHopStrategySet(txnp, _strategy); | ||
|
|
||
| return true; | ||
| } |
Comment on lines
1663
to
1667
| void | ||
| OperatorSetNextHopStrategy::initialize_hooks() | ||
| { | ||
| add_allowed_hook(TS_HTTP_READ_REQUEST_HDR_HOOK); | ||
| add_allowed_hook(TS_REMAP_PSEUDO_HOOK); | ||
| } |
Comment on lines
+5065
to
5077
| TSStrategy | ||
| TSRemapNextHopStrategyFind(const char *name) | ||
| { | ||
| char const *name = nullptr; | ||
| if (nullptr != stratptr) { | ||
| auto strategy = reinterpret_cast<NextHopSelectionStrategy const *>(stratptr); | ||
| name = strategy->strategy_name.c_str(); | ||
| auto const um = url_mapping::instance; | ||
| sdk_assert(sdk_sanity_check_null_ptr((void *)um) == TS_SUCCESS); | ||
|
|
||
| NextHopSelectionStrategy *strategy = nullptr; | ||
|
|
||
| if (nullptr != um->strategyFactory) { | ||
| // HttpSM has a reference count handle to UrlRewrite which manages | ||
| // the NextHopStrategyFactory pointer. | ||
| strategy = um->strategyFactory->strategyInstance(name); | ||
| } |
Comment on lines
1699
to
+1710
| /** | ||
| Returns either null pointer or null terminated pointer to name. | ||
| DO NOT FREE. | ||
| DO NOT FREE. | ||
|
|
||
| This value may be a nullptr due to: | ||
| - parent proxying not enabled | ||
| - no parent selection strategy (using parent.config) | ||
|
|
||
| @param txnp HTTP transaction whose next hop strategy to get. | ||
| @param pointer to the NextHopStrategy. | ||
|
|
||
| */ | ||
| char const *TSHttpNextHopStrategyNameGet(void const *strategy); | ||
| char const *TSNextHopStrategyNameGet(TSStrategy strategy); |
Comment on lines
+40
to
+44
| Plugins can get a strategy by name by calling | ||
| :func:`TSRemapNextHopStrategyGet` to get the current transaction's active | ||
| strategy or :func:`TSRemapNextHopStrategyFind` to look up a strategy by | ||
| name using the loading remap rule's pointer to the NextHopStrategyFactory | ||
| strategy database. |
Comment on lines
+5036
to
5052
| TSStrategy | ||
| TSHttpTxnNextHopStrategyFind(TSHttpTxn txnp, const char *name) | ||
| { | ||
| sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS); | ||
| sdk_assert(sdk_sanity_check_null_ptr((void *)name) == TS_SUCCESS); | ||
|
|
||
| auto sm = reinterpret_cast<HttpSM const *>(txnp); | ||
|
|
||
| sdk_assert(sdk_sanity_check_null_ptr((void *)sm->m_remap) == TS_SUCCESS); | ||
| sdk_assert(sdk_sanity_check_null_ptr((void *)sm->m_remap->strategyFactory) == TS_SUCCESS); | ||
|
|
||
| // HttpSM has a reference count handle to UrlRewrite which has a | ||
| // pointer to NextHopStrategyFactory | ||
| NextHopSelectionStrategy *const strategy = sm->m_remap->strategyFactory->strategyInstance(name); | ||
|
|
||
| return reinterpret_cast<TSStrategy>(strategy); | ||
| } |
Comment on lines
+5065
to
+5091
| TSStrategy | ||
| TSRemapNextHopStrategyFind(const char *name) | ||
| { | ||
| char const *name = nullptr; | ||
| if (nullptr != stratptr) { | ||
| auto strategy = reinterpret_cast<NextHopSelectionStrategy const *>(stratptr); | ||
| name = strategy->strategy_name.c_str(); | ||
| auto const um = url_mapping::instance; | ||
| sdk_assert(sdk_sanity_check_null_ptr((void *)um) == TS_SUCCESS); | ||
|
|
||
| NextHopSelectionStrategy *strategy = nullptr; | ||
|
|
||
| if (nullptr != um->strategyFactory) { | ||
| // HttpSM has a reference count handle to UrlRewrite which manages | ||
| // the NextHopStrategyFactory pointer. | ||
| strategy = um->strategyFactory->strategyInstance(name); | ||
| } | ||
|
|
||
| return name; | ||
| return reinterpret_cast<TSStrategy>(strategy); | ||
| } | ||
|
|
||
| void const * | ||
| TSHttpTxnNextHopNamedStrategyGet(TSHttpTxn txnp, const char *name) | ||
| void | ||
| TSRemapNextHopStrategySet(TSStrategy strategy) | ||
| { | ||
| sdk_assert(sdk_sanity_check_txn(txnp) == TS_SUCCESS); | ||
| sdk_assert(sdk_sanity_check_null_ptr((void *)name) == TS_SUCCESS); | ||
| auto const um = url_mapping::instance; | ||
| sdk_assert(sdk_sanity_check_null_ptr((void *)um) == TS_SUCCESS); | ||
| // null strategy falls back to parent.config | ||
| // sdk_assert(sdk_sanity_check_null_ptr(stratptr) == TS_SUCCESS); | ||
|
|
||
| auto sm = reinterpret_cast<HttpSM const *>(txnp); | ||
| um->strategy = reinterpret_cast<NextHopSelectionStrategy *>(strategy); | ||
| } |
Comment on lines
+5101
to
5112
| char const * | ||
| TSNextHopStrategyNameGet(TSStrategy stratptr) | ||
| { | ||
| static char const *const nullname = "null"; | ||
| char const *name = nullname; | ||
| if (nullptr != stratptr) { | ||
| auto strategy = reinterpret_cast<NextHopSelectionStrategy *>(stratptr); | ||
| name = strategy->strategy_name.c_str(); | ||
| } | ||
|
|
||
| return static_cast<void const *>(strat); | ||
| return name; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This gives the API access to the RemapConfig
url_mappingduring TSRemapNewInstance calls. This contains both the assigned stragies pointer and a pointer to the loaded strategy factory.This modifies the strategies ts API from the previous PR.
API is:
valid during TSRemapNewInstance:
valid during transaction (the Find call is changed):
with utility function to get the null terminated strategy name (returns "null" if nullptr strategy):
The header_rewrite and regex_remap plugins are modified to look up named strategies during TSRemapNewInstance instead of performing strategy factory lookups during each transaction remap hook.