Прекратить исходящие http-запросы, когда входящий http-запрос клиента прекращается.

Обзор приложения

У меня есть серверное приложение node.js, реализованное с помощью модуля express.js 4 и основного http-модуля node.js. На высоком уровне приложение принимает входящие клиентские http-сообщения, выполняет различные http-вызовы (используя http-модуль) к другим внешним API-интерфейсам и, наконец, отправляет ответ клиенту на основе ответов от вышеупомянутых различных внешних http-API-ответов.

Проблема

Моя проблема заключается в том, что, когда входящий клиентский запрос http завершается клиентом (например, когда клиент хочет отменить свой запрос), мое приложение node.js продолжает выполнять вышеупомянутые различные внешние вызовы HTTP API. Кажется, я не могу найти способ дать остальной части моего приложения node.js сигнал прекратить свои различные исходящие http-запросы к внешним API в таких случаях.

Когда клиент завершает свой запрос, приложение Express (т.е. сервер экспресс-http) получает событие "close", которое я слушаю. Слушатель события close в моем коде перехватывает это событие; тем не менее, я не могу понять, как затем подать сигнал "нисходящим" или "последующим" http-запросам, сделанным моим кодом, о прекращении.

Моя цель

Как я могу сигнализировать всем исходящим http-запросам на внешние API, которые связаны с одним клиентским входящим запросом, для прекращения, когда клиент прекращает свой входящий запрос к моей службе?

Я предоставил упрощенную версию моего приложения node.js ниже с некоторыми встроенными комментариями кода, чтобы помочь проиллюстрировать мою проблему более четко. Любая помощь или понимание будет очень цениться. Спасибо!

Дополнительная информация

Я использую промежуточное программное обеспечение Apigee swagger-tools для маршрутизации API.

Я нашел несколько ответов на вопросы, которые похожи, но не совсем применимы к моему вопросу:

Обработка отмененного запроса с помощью Express/Node.js и Angular

Как обнаружить, что пользователь отменяет запрос

Лучший,

Крис

тест-app.js

// test-app.js
"use strict";

var swaggerTools = require("swagger-tools");
var app = require("express")();

// swaggerRouter configuration
// sends incoming http messages to test-controller.js
var options = {
    controllers: './controllers'
};

// The Swagger document (require it, build it programmatically, fetch it from a URL, ...)
// describes the API specification
var apiSpec = require('./test-swagger.json');

// Initialize the Swagger middleware
swaggerTools.initializeMiddleware(apiSpec, function (middleware) {
    "use strict"

    // Interpret Swagger resources and attach metadata to request - must be first in swagger-tools middleware chain
    app.use(middleware.swaggerMetadata());

    // Validate Swagger requests/responses based on test-swagger.json API specification
    app.use(middleware.swaggerValidator());

    // Route validated requests to appropriate controller, test-controller.js
    app.use(middleware.swaggerRouter(options));
});

// Run http server on port 8080
app.listen(8080, function () {
    "use strict";
    console.log("Server running on port %d", this.address().port);
})
    .on("connection", function (socket) {
        console.log("a new connection was made by an incoming client request.");
        socket.on("close", function () {
            console.log("socket connection was closed by client");
            // somehow signal to the rest of my node.js app to terminate any
            // http requests being made to external APIs, e.g. twitter api
            socket.destroy();
        });
    })

тест-controller.js

//test-controller.js
"use strict";
var http = require("https");

// only one function currently, consequently, all incoming http requests are
// routed to this function, i.e. "compile"
module.exports = {
    compile: compile
};

function compile(req, res, next) {
    var options = {
        "method": "GET",
        "hostname": "api.twitter.com",
        "path": "/1.1/statuses/mentions_timeline.json?count=2&since_id=14927799",
        "headers": {"accept": "application/json"}
    };
    // how can i terminate this request when the http.server in test-app.js receives the "close" event?
    http.request(options)
        .on("response", function(response) {
            var apiResponse = [];
            response.on("data", function (chunk) {
                apiResponse.push(chunk);
            });
            response.on("end", function () {
                apiResponse = Buffer.concat(apiResponse).toString();
                res.status(response.statusCode).set(response.headers).send(apiResponse);
            });
        })
}

1 ответ

Решение

В методе компиляции вашего тестового контроллера вы должны просто сделать что-то вроде этого:

var request = http.request(options, function (response) {
  res.writeHead(response.statusCode, response.headers)
  response.pipe(res, { end: true })
})
req.on('close', function(){
  request.abort()
})
Другие вопросы по тегам