feat: Add proxy-chain plugin to chain multiple upstream service calls
Description
This Pull Request introduces the proxy-chain plugin to APISIX, designed to enhance the gateway's ability to orchestrate complex workflows by chaining multiple upstream service calls in a sequential manner. The plugin merges the responses from these services into a single payload, which is then passed to the final upstream, making it ideal for scenarios requiring data aggregation or step-by-step processing across microservices.
Purpose
The primary goal of the proxy-chain plugin is to simplify workflows where a single client request needs to interact with multiple backend services before producing a final response. For example, in an e-commerce checkout process, the plugin can:
- Fetch user data from a customer service.
- Validate payment details from a payment service.
- Combine the results and forward them to an order processing service.
This eliminates the need for clients to manage these interactions manually and reduces latency by handling them server-side within APISIX.
How It Works
The plugin operates in the access phase of APISIX's request lifecycle and performs the following steps:
- Request Parsing: Extracts the incoming request body (JSON) and URI arguments, merging them into an initial data set.
- Token Handling: Optionally extracts an authentication token from a configurable header (e.g.,
TokenorAuthorization) and passes it to downstream services. - Service Chaining: Iterates through a list of configured services, making HTTP requests to each in sequence:
- Sends the current merged data as the request body.
- Merges the response (JSON) into the cumulative data set.
- Final Output: Updates the request body with the merged data and forwards it to the upstream, optionally including the authentication token.
The plugin includes error handling for failed service calls or invalid JSON responses, returning appropriate HTTP status codes and error messages.
Configuration Schema
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
services |
array | Yes | - | List of upstream services to chain. |
services.uri |
string | Yes | - | URI of the upstream service. |
services.method |
string | Yes | "POST" | HTTP method (GET, POST, PUT, DELETE). |
token_header |
string | No | - | Custom header name for passing a token between services. |
Example Usage
Below is an example of how to configure and use the proxy-chain plugin in APISIX:
Route Configuration
{
"uri": "/v1/checkout",
"methods": ["POST"],
"plugins": {
"proxy-chain": {
"services": [
{
"uri": "http://customer_service/api/v1/user",
"method": "POST"
},
{
"uri": "http://payment_service/api/v1/validate",
"method": "POST"
}
],
"token_header": "Token"
},
"proxy-rewrite": {
"uri": "/api/v1/checkout"
}
},
"upstream_id": "550932803756229477"
}
Expected Behavior:
The plugin sends {"order_id": "12345"} to customer_service/api/v1/user, receiving something like {"user_id": "67890"}.
It then sends the merged data {"order_id": "12345", "user_id": "67890"} to payment_service/api/v1/validate, receiving {"status": "valid"}.
The final merged data {"order_id": "12345", "user_id": "67890", "status": "valid"} is rewritten to /api/v1/checkout and sent to the upstream.
Changes Introduced
Added apisix/apisix/plugins/proxy-chain.lua with the plugin implementation.
Updated documentation in docs/en/latest/plugins/proxy-chain.md (to be added in a follow-up commit if needed).
Why Include This Plugin?
Flexibility: Enables complex service orchestration without additional middleware.
Performance: Reduces client-side latency by handling chaining server-side.
Reusability: Useful across various use cases like authentication flows, data aggregation, and microservices coordination.
Testing
The plugin has been tested in a Dockerized APISIX environment (version 3.11.0-debian) with the example configuration above.
Error handling for failed service calls and invalid JSON responses is verified.
Suggestions for unit tests in t/plugin/ are welcome!
Next Steps
Requesting feedback on the implementation and configuration schema.
Willing to add unit tests if required for acceptance
Add proxy-chain plugin to chain multiple upstream service calls
@vahidaghazadeh Thanks so much for your contribution! API orchestration is a highly valuable feature that many developers need. It would be even more helpful if you could include usage documentation and some test cases to make it easier for others to adopt and validate.
Is this similar to the plug-in batch-request?
@vahidaghazadeh Thanks so much for your contribution! API orchestration is a highly valuable feature that many developers need. It would be even more helpful if you could include usage documentation and some test cases to make it easier for others to adopt and validate.
Yes, you are right It was my mistake, I forgot to commit the test file The test plugin was successfully implemented in the introduction repository, I just forgot to put it in the apisix repository
Is there anything wrong with the documentation I provided?
Is this similar to the plug-in batch-request?
No, this plugin is different from the batch-requests plugin in several ways.
Key Differences:
- Purpose:
proxy-chain is designed to sequentially call multiple backend services, merge their responses, and forward the final merged data to the upstream.
batch-requests allows clients to send multiple requests in a single HTTP call, and it executes them in parallel (or optionally in sequence), returning all responses back to the client as a batch.
- Response Handling:
proxy-chain merges the responses of the services into one unified request body that is then forwarded upstream.
batch-requests returns the raw responses of each sub-request as separate items in an array.
- Flow Direction:
proxy-chain is used in the request phase, before the final upstream is called. It acts as a transformation layer before reaching the main backend.
batch-requests is mostly client-driven — clients explicitly request multiple things, and the plugin acts more like a batch router.
- Use Case:
Use proxy-chain when you want to call multiple internal services, combine their outputs, and proceed with the final data as if it was one logical request.
Use batch-requests when a frontend or client needs to hit multiple endpoints in a single API call and receive all results independently.
was this code written by some AI tool?
was this code written by some AI tool?
Parts of the code and test writing were reviewed with auxiliary tools, but the overall structure and implementation were my final work and were done with the need for project development.
Hi @vahidaghazadeh, please fix failed ci
Hi @vahidaghazadeh, please fix failed ci
Hi @Baoyuantop CI failure fixed
Why is there an error in apisix action ci but it passes in my action repo?
I'm seeing some lint checking errors.
I'll convert this PR to draft first, if the changes are done please request review again.
Hi @vahidaghazadeh, please fix failed ci
Hi @vahidaghazadeh, any updates?
Hi @vahidaghazadeh, any updates?
Hi @Baoyuantop , the update is done. But considering the GitHub runners and apisix tests, I need to fix the possible bugs after running the pipelines. Because the plugin works properly in the production environment and only in the test file should the conflicts be fixed
Please fix the errors reported by CI.
This pull request has been marked as stale due to 60 days of inactivity. It will be closed in 4 weeks if no further activity occurs. If you think that's incorrect or this pull request should instead be reviewed, please simply write any comment. Even if closed, you can still revive the PR at any time or discuss it on the [email protected] list. Thank you for your contributions.