Братья и сестры, я создаю конечную точку Express API, которая должна использовать внешний API, выполнять некоторые изменения ключей и значений и возвращать результат клиенту. Вот что у меня есть на данный момент:
const external_endpoint = <external_api_end_point>;
app.get('/', function (req, res, next) {
request({ url: external_endpoint}).pipe(res);
});
Это возвращает точную полезную нагрузку, которую вы получите от прямого попадания в external_endpoint.
Есть ли что-то, что я могу сделать, чтобы изменить res до того, как он будет отправлен клиенту? Я пробовал несколько вещей, но ничего не помогло. Есть какие-нибудь идеи или лучшие практики, связанные с преобразованием входящей полезной нагрузки?
Ради простоты. Допустим, это полезная нагрузка obj.json:
{
"sad": {
"userid": 5,
"username": "jsmith",
"isAdmin": true
}
}
и я хочу заменить sad на happy.
Я знаю, что вне запроса я мог бы сделать что-то вроде этого:
obj = JSON.parse(JSON.stringify(obj).split('"sad":').join('"happy":'));
но бросить obj вместо res не получится. Я попытался присвоить значение этим res и res.body, но без игральных костей.
Заранее благодарим за помощь!
правильно. Извините, что не прояснил это. Я использую request ^2.88.0. Вот ссылка на репозиторий github для него github.com/request/request
Понятно. Да, базовый модуль request обрабатывает потоковую передачу для выражения ответов как первоклассный гражданин. Итак, вы можете использовать метод event-stream, который я описываю в ответе.





Если вы используете request-promise, вы можете просто создать новый ответ и отправить его или изменить полученный ответ:
app.get('/', function (req, res, next) {
request({ url: external_endpoint, json: true})
.then(response => res.json({ happy: response.sad })))
.catch(next);
});
(конечно, вам нужно правильно обрабатывать ошибки)
Если вы хотите обрабатывать его как поток (что имеет смысл, если у вас большой объем данных), вы можете использовать исходный модуль request и использовать event-stream для создания своего канала:
const es = require('event-stream');
const swapper = es.through(
function write(data) {
this.emit("data", data.replace("sad", "happy"));
},
function end() {
this.emit("end");
}
);
request({ url: external_endpoint})
.pipe(es.stringify())
.pipe(swapper)
.pipe(es.parse())
.pipe(res);
Вот песочница для тестирования потоковой обработки: https://codesandbox.io/s/3wqx67pq6
В приведенном выше коде с использованием await вам нужно добавить async непосредственно перед функцией, иначе await вернется как undefined.
Таким образом, на .pipe(es.map(j => j.replace('sad', 'happy')) может показаться, что нам не хватает закрывающего ). Однако даже когда я добавляю это в конец строки, он работает не так, как ожидалось. Я попытался добавить в конец .pipe(res)), он возвращает полезную нагрузку, но без какой-либо замены.
В самом деле, es.map() неправильный, потому что в этот момент мы получаем строку. Заменен на es.through()
Кстати, были проблемы со ссылкой на коды и ящик, но я думаю, что теперь она работает.
Замечательно, но хочется сделать это немного лучше. Скажем, у кого-то есть слово sad в имени пользователя (или в любом другом значении, если на то пошло). Как предотвратить или гарантировать, что .replace не изменит это значение? Я попытался заменить data.replace("sad", "happy") на data.replace('"sad":', '"happy":'), но включение кавычек, похоже, нарушает работу замены. Любые идеи о том, как я могу настроить таргетинг только на изменение ключей вместо данных? До сих пор вы оказали огромную помощь. Спасибо за все.
Просто ответил на мои вопросы. .replace поддерживает использование регулярных выражений. Это означает, что я могу использовать регулярное выражение, что-то вроде И, чтобы еще больше убедиться, что я не заменяю то, что я не собираюсь, я могу использовать регулярное выражение, поскольку кажется, что .replace поддерживает использование регулярных выражений. Однако при тестировании с чем-то вроде "sad": или даже /"user":/. Его не удается заменить, хотя я уверен, что мое регулярное выражение верное. Есть идеи по этому поводу?
Может быть тема для другого вопроса. Регулярные выражения мощные, но непростые. Я рекомендую разбить его и использовать узел в режиме REPL для отладки.
согласованный. Вот почему я пометил это как ответ. Еще раз спасибо!
Можете уточнить, что такое
request? Это может быть несколько библиотек.