Skip to content

feat: Add proxy-chain plugin to chain multiple upstream service calls #12128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

vahidaghazadeh
Copy link

@vahidaghazadeh vahidaghazadeh commented Apr 8, 2025

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:

  1. Fetch user data from a customer service.
  2. Validate payment details from a payment service.
  3. 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:

  1. Request Parsing: Extracts the incoming request body (JSON) and URI arguments, merging them into an initial data set.
  2. Token Handling: Optionally extracts an authentication token from a configurable header (e.g., Token or Authorization) and passes it to downstream services.
  3. 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.
  4. 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

@dosubot dosubot bot added size:L This PR changes 100-499 lines, ignoring generated files. enhancement New feature or request plugin labels Apr 8, 2025
@vahidaghazadeh
Copy link
Author

Add proxy-chain plugin to chain multiple upstream service calls

@moonming
Copy link
Member

moonming commented Apr 9, 2025

@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.

@gxthrj
Copy link
Contributor

gxthrj commented Apr 9, 2025

Is this similar to the plug-in batch-request

@vahidaghazadeh
Copy link
Author

vahidaghazadeh commented Apr 9, 2025

@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?

@vahidaghazadeh
Copy link
Author

vahidaghazadeh commented Apr 9, 2025

Is this similar to the plug-in batch-request

No, this plugin is different from the batch-requests plugin in several ways.

Key Differences:

  1. 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.

  1. 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.

  1. 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.

  1. 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.

@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Apr 9, 2025
@vahidaghazadeh vahidaghazadeh changed the title Add proxy-chain plugin to chain multiple upstream service calls feat: Add proxy-chain plugin to chain multiple upstream service calls Apr 9, 2025
@shreemaan-abhishek
Copy link
Contributor

was this code written by some AI tool?

@vahidaghazadeh
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request plugin size:XL This PR changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants