You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在REST API中合并多个API调用?Node.js Express实现方案问询

Hey there! Great question. Let's break this down clearly:

First off, the combined URL format you proposed (http://localhost:3006/send-message?email=abc@mysite.com&password=xxxxxx&count=4&location=US/cancel-request?count=2&usernames=abc,xyz) isn't a standard HTTP request format. Browsers and most HTTP clients won't recognize it as two separate API calls—instead, everything after the first ? gets treated as query parameters for the /send-message endpoint.

That said, if you really need to support this custom format, we can manually parse it in Express. But I strongly recommend using a more standard approach for batch operations instead, since the custom format is fragile (e.g., it breaks if any query parameter contains a /). Let's cover both options:

We'll need to grab the full original URL, split it manually into the two API operations, parse their query parameters, then run the corresponding logic for each.

Here's how to implement this in Express:

const express = require('express');
const qs = require('querystring');
const app = express();

// Catch all GET requests to handle the custom combined format
app.get('*', (req, res, next) => {
  const fullUrl = req.originalUrl;
  // Split into base path and the rest of the URL (after first ?)
  const [basePath, querySection] = fullUrl.split('?');

  // If no query section, pass to regular routing
  if (!querySection) {
    return next();
  }

  // Find the first / in the query section—this is our separator between the two operations
  const splitPoint = querySection.indexOf('/');
  if (splitPoint === -1) {
    return next(); // No separator, treat as normal request
  }

  // Split into first operation's query params and second operation's full path+query
  const firstQueryStr = querySection.slice(0, splitPoint);
  const secondOpFull = querySection.slice(splitPoint + 1);

  // Parse query parameters for both operations
  const firstQuery = qs.parse(firstQueryStr);
  const [secondPath, secondQueryStr] = secondOpFull.split('?');
  const secondQuery = qs.parse(secondQueryStr || '');

  // Run both operations in parallel (assuming you have handler functions)
  Promise.all([
    handleSendMessage(firstQuery),
    handleCancelRequest(secondQuery)
  ])
  .then(results => {
    res.json({
      send_message: results[0],
      cancel_request: results[1]
    });
  })
  .catch(err => {
    res.status(500).json({ error: err.message });
  });
});

// Mock handler functions for your APIs
function handleSendMessage(params) {
  return Promise.resolve({
    status: 'success',
    message: `Sent ${params.count} messages to ${params.email} (location: ${params.location})`
  });
}

function handleCancelRequest(params) {
  return Promise.resolve({
    status: 'success',
    message: `Canceled ${params.count} requests for usernames: ${params.usernames}`
  });
}

app.listen(3006, () => {
  console.log('Server running on http://localhost:3006');
});

Caveats for this approach:

  • If any query parameter value contains a /, the parsing will fail.
  • It's non-standard, so other developers or tools will find it confusing.
  • URL length limits could become an issue if you have many parameters.

A better approach is to create a dedicated batch endpoint that accepts multiple operations in a structured way. This is more flexible, maintainable, and follows HTTP best practices.

Example with POST (best for batch operations):

We'll send an array of operations in the request body:

const express = require('express');
const app = express();

// Parse JSON request bodies
app.use(express.json());

// Batch endpoint
app.post('/batch', (req, res) => {
  const { operations } = req.body;

  // Validate input
  if (!Array.isArray(operations)) {
    return res.status(400).json({ error: '`operations` must be an array' });
  }

  // Map operation types to their handler functions
  const handlers = {
    'send-message': handleSendMessage,
    'cancel-request': handleCancelRequest
  };

  // Run all operations in parallel
  Promise.all(
    operations.map(op => {
      if (!handlers[op.type]) {
        return Promise.reject(new Error(`Unknown operation type: ${op.type}`));
      }
      return handlers[op.type](op.params);
    })
  )
  .then(results => {
    res.json(results);
  })
  .catch(err => {
    res.status(500).json({ error: err.message });
  });
});

// Reuse the same mock handlers as before
function handleSendMessage(params) {
  return Promise.resolve({
    status: 'success',
    message: `Sent ${params.count} messages to ${params.email} (location: ${params.location})`
  });
}

function handleCancelRequest(params) {
  return Promise.resolve({
    status: 'success',
    message: `Canceled ${params.count} requests for usernames: ${params.usernames}`
  });
}

app.listen(3006, () => {
  console.log('Server running on http://localhost:3006');
});

To use this, send a POST request to http://localhost:3006/batch with this JSON body:

{
  "operations": [
    {
      "type": "send-message",
      "params": {
        "email": "abc@mysite.com",
        "password": "xxxxxx",
        "count": 4,
        "location": "US"
      }
    },
    {
      "type": "cancel-request",
      "params": {
        "email": "abc@mysite.com",
        "password": "xxxxxx",
        "count": 2,
        "usernames": "abc,xyz"
      }
    }
  ]
}

Why this is better:

  • It's standard and easy for other developers to understand.
  • You don't have to worry about special characters in parameters breaking the request.
  • It supports more complex operations without hitting URL length limits.
  • You can easily add more operation types later.

内容的提问来源于stack exchange,提问作者Noman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 22:59:04