apisix icon indicating copy to clipboard operation
apisix copied to clipboard

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

Open vahidaghazadeh opened this issue 8 months ago • 17 comments

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

vahidaghazadeh avatar Apr 08 '25 12:04 vahidaghazadeh

Add proxy-chain plugin to chain multiple upstream service calls

vahidaghazadeh avatar Apr 08 '25 12:04 vahidaghazadeh

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

moonming avatar Apr 09 '25 07:04 moonming

Is this similar to the plug-in batch-request

gxthrj avatar Apr 09 '25 11:04 gxthrj

@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 avatar Apr 09 '25 13:04 vahidaghazadeh

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.

vahidaghazadeh avatar Apr 09 '25 13:04 vahidaghazadeh

was this code written by some AI tool?

shreemaan-abhishek avatar Apr 11 '25 04:04 shreemaan-abhishek

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.

vahidaghazadeh avatar Apr 11 '25 11:04 vahidaghazadeh

Hi @vahidaghazadeh, please fix failed ci

Baoyuantop avatar May 07 '25 01:05 Baoyuantop

Hi @vahidaghazadeh, please fix failed ci

Hi @Baoyuantop CI failure fixed

vahidaghazadeh avatar May 29 '25 22:05 vahidaghazadeh

Why is there an error in apisix action ci but it passes in my action repo? Screenshot

vahidaghazadeh avatar May 30 '25 12:05 vahidaghazadeh

I'm seeing some lint checking errors.

Baoyuantop avatar Jun 03 '25 01:06 Baoyuantop

I'll convert this PR to draft first, if the changes are done please request review again.

Baoyuantop avatar Jun 16 '25 07:06 Baoyuantop

Hi @vahidaghazadeh, please fix failed ci

Baoyuantop avatar Jul 22 '25 08:07 Baoyuantop

Hi @vahidaghazadeh, any updates?

Baoyuantop avatar Jul 28 '25 07:07 Baoyuantop

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

vahidaghazadeh avatar Aug 06 '25 18:08 vahidaghazadeh

Please fix the errors reported by CI.

SkyeYoung avatar Aug 07 '25 05:08 SkyeYoung

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.

github-actions[bot] avatar Nov 13 '25 10:11 github-actions[bot]