Позвони в Экспресс роутер вручную - PullRequest
0 голосов
/ 13 февраля 2019

Нello!Я пытаюсь вызвать функцию, которая была передана в expressRouter.post(...) вызов.

Этот expressRouter.post(...) вызов происходит в файле, который я не могу изменить .Код уже был распространен среди многих клиентов, и я не могу изменить их версии файла.В то время как I не имеет возможности обновить этот файл для удаленных клиентов, другие разработчики могут .Поэтому я сталкиваюсь с проблемой изменения поведения конечной точки POST в будущем.

Я также имею дело с проблемами производительности.Эта конечная точка POST ожидает, что req.body будет проанализированным объектом JSON, и этот объект JSON может быть чрезмерно большим.

Моя цель - написать конечную точку GET, которая внутренне активирует эту конечную точку POST.Конечной точке GET потребуется вызвать конечную точку POST с очень большим значением JSON, в которое вставлены параметры URL-запроса.Функциональность GET всегда должна отражать функциональность POST, в том числе, если функциональность POST будет обновлена ​​в будущем.По этой причине я не могу скопировать / вставить логику POST.Обратите также внимание на то, что формат JSON никогда не изменится.

Я понимаю, что проблема вызова конечной точки expressjs внутри системы обычно решается с помощью 1) извлечения функции маршрутизатора в доступную область действия ,или 2) генерация HTTP-запроса к localhost .

К сожалению, в моем случае ни одна из этих опций не подходит:

  1. Я не могу переместить функцию вдоступной области видимости, поскольку я не могу изменить источник, а также не могу скопировать и вставить функцию, так как оригинальная версия может измениться
  2. Избегание HTTP-запроса является высоким приоритетом из соображений производительности.HTTP-запрос потребует сериализации + десериализации чрезмерно большого тела JSON, повторного посещения ряда промежуточных программ аутентификации (которые требуют ожидания дальнейших HTTP-запросов + запросов к базе данных) и т. Д.

Вот мой(продолжение) Конечная точка POST:

expressRouter.post('/my/post/endpoint', (req, res) => {

  if (!req.body.hasOwnProperty('val'))
    return res.status(400).send('Missing "val"');

  return res.status(200).send(`Your val: ${req.body.val}`);

});

Если я сделаю запрос POST для localhost:<port>/my/post/endpoint, я получу ожидаемую ошибку или ответ, основанный на том, включил ли я "val" в тело JSON.

Теперь я хочу, чтобы у меня была точно такая же функциональность, но через GET и с указанием «val» в URL, а не в любом теле JSON.Я попытался сделать следующее:

expressRouter.get('/my/get/endpoint/:val', (req, res) => {

  // Make it seem as if "val" occurred inside the JSON body
  let fakeReq = {
    body: {
      val: req.params.val
    }
  };

  // Now call the POST endpoint
  // Pass the fake request, and the real response
  // This should enable the POST endpoint to write data to the
  // response, and it will seem like THIS endpoint wrote to the
  // response.
  manuallyCallExpressEndpoint(expressRouter, 'POST', '/my/post/endpoint', fakeReq, res);

});

К сожалению, я не знаю, как реализовать manuallyCallExpressEndpoint.

Есть ли решение этой проблемы, которое исключает как извлечение функции в доступнуюобласть действия и создание запроса HTTP?

Ответы [ 2 ]

0 голосов
/ 13 февраля 2019

Это кажется возможным, но может иметь смысл изменить req и передать его, а не создавать новый объект fakeReq.То, что позволяет это, выглядит как функция router.handle(req, res, next).Я не уверен, что это самый разумный способ сделать это, но он, безусловно, позволит избежать больших накладных расходов на отдельный http-запрос!

app.get('/my/get/endpoint/:val', (req, res) => {

  // Modify `req`, don't create a whole new `fakeReq`
  req.body = {
    val: req.params.val
  };

  manuallyCallExpressEndpoint(app, 'POST', '/my/post/endpoint', req, res);

});

let manuallyCallExpressEndpoint = (router, method, url, req, res) => {
  req.method = method;
  req.url = url;
  router.handle(req, res, () => {});
};
0 голосов
/ 13 февраля 2019

Как насчет простого промежуточного программного обеспечения?

function checkVal(req, res, next) {
  const val = req.params.val || req.body.val

  if (!val) {
    return res.status(400).send('Missing "val"'); 
  }

  return res.status(200).send(`Your val: ${val}`);
}

app.get('/my/get/endpoint/:val', checkVal)
app.post('/my/post/endpoint', checkVal)

Этот код не проверен, но дает вам приблизительное представление о том, как можно запустить один и тот же код в обоих местах.

CheckValФункция служит экспресс-обработчиком, с запросом, ответом и следующим.Сначала проверяются параметры, а затем тело.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...