Прекратить исходящие 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()
})