Прокси с экспресс.js
чтобы избежать проблем AJAX с тем же доменом, я хочу свой узел.JS web server для пересылки всех запросов с URL /api/BLABLA
на другой сервер, например other_domain.com:3000/BLABLA
, и вернуть пользователю то же самое, что этот удаленный сервер вернулся, прозрачно.
все остальные url (кроме /api/*
) должны обслуживаться напрямую, без проксирования.
как я могу достичь этого с помощью узла.js + express.Джей? Можете ли вы привести простой пример кода?
(как веб-сервер, так и удаленный 3000
сервер находится под моим контролем, оба запущенных узла.js с экспресс.js)
пока я нашел это https://github.com/nodejitsu/node-http-proxy/, но чтение документации там не сделало меня мудрее. Я закончил с
var proxy = new httpProxy.RoutingProxy();
app.all("/api/*", function(req, res) {
console.log("old request url " + req.url)
req.url = '/' + req.url.split('/').slice(2).join('/'); // remove the '/api' part
console.log("new request url " + req.url)
proxy.proxyRequest(req, res, {
host: "other_domain.com",
port: 3000
});
});
но ничего не возвращается на исходный веб-сервер (или конечному пользователю), так что не повезло.
10 ответов:
вы хотите использовать
http.request
создать аналогичный запрос к удаленному API и вернуть его ответ.что-то вроде этого:
var http = require('http'); /* your app config here */ app.post('/api/BLABLA', function(req, res) { var options = { // host to forward to host: 'www.google.com', // port to forward to port: 80, // path to forward to path: '/api/BLABLA', // request method method: 'POST', // headers to send headers: req.headers }; var creq = http.request(options, function(cres) { // set encoding cres.setEncoding('utf8'); // wait for data cres.on('data', function(chunk){ res.write(chunk); }); cres.on('close', function(){ // closed, let's end client request as well res.writeHead(cres.statusCode); res.end(); }); cres.on('end', function(){ // finished, let's finish client request as well res.writeHead(cres.statusCode); res.end(); }); }).on('error', function(e) { // we got an error, return 500 error to client and log error console.log(e.message); res.writeHead(500); res.end(); }); creq.end(); });
обратите внимание: я не пытался выше, поэтому может содержать ошибки разобрать, надеюсь, это даст вам подсказку о том, как заставить его работать.
Я сделал что-то подобное, но я использовал запрос вместо:
var request = require('request'); app.get('/', function(req,res) { //modify the url in any way you want var newurl = 'http://google.com/'; request(newurl).pipe(res); });
Я надеюсь, что это помогает, потребовалось некоторое время, чтобы понять, что я мог бы сделать это :)
направить trigomanответ (полные кредиты ему) для работы с POST (также может сделать работу с PUT и т. д.):
app.use('/api', function(req, res) { var url = 'YOUR_API_BASE_URL'+ req.url; var r = null; if(req.method === 'POST') { r = request.post({uri: url, json: req.body}); } else { r = request(url); } req.pipe(r).pipe(res); });
я нашел более короткое и очень простое решение, которое работает без проблем, а также с аутентификацией, используя
express-http-proxy
:const url = require('url'); const proxy = require('express-http-proxy'); // New hostname+path as specified by question: const apiProxy = proxy('other_domain.com:3000/BLABLA', { forwardPath: req => url.parse(req.baseUrl).path });
а потом просто:
app.use('/api/*', apiProxy);
Примечание: как упоминалось @MaxPRafferty, используйте
req.originalUrl
на местеbaseUrl
сохранить файл querystring:forwardPath: req => url.parse(req.baseUrl).path
обновление: как упоминалось Андреем (спасибо!), есть готовое решение, использующее тот же принцип:
npm i --save http-proxy-middleware
и затем:
const proxy = require('http-proxy-middleware') var apiProxy = proxy('/api', {target: 'http://www.example.org/api'}); app.use(apiProxy)
документы: http-proxy-middleware на Github
Я знаю, что опоздал присоединиться к этой партии, но я надеюсь, что это поможет кому-то.
я использовал следующую настройку, чтобы направить все на
/rest
к моему бэкенд-серверу (на порт 8080), и все остальные запросы к интерфейсному серверу (сервер webpack на порт 3001). Он поддерживает все HTTP-методы, не теряет никакой мета-информации запроса и поддерживает websockets (которые мне нужны для горячей перезагрузки)var express = require('express'); var app = express(); var httpProxy = require('http-proxy'); var apiProxy = httpProxy.createProxyServer(); var backend = 'http://localhost:8080', frontend = 'http://localhost:3001'; app.all("/rest/*", function(req, res) { apiProxy.web(req, res, {target: backend}); }); app.all("/*", function(req, res) { apiProxy.web(req, res, {target: frontend}); }); var server = require('http').createServer(app); server.on('upgrade', function (req, socket, head) { apiProxy.ws(req, socket, head, {target: frontend}); }); server.listen(3000);
хорошо, вот готовый к копированию ответ с использованием модуля require ('request') npm и переменной среды *вместо жестко закодированного прокси):
coffeescript
app.use (req, res, next) -> r = false method = req.method.toLowerCase().replace(/delete/, 'del') switch method when 'get', 'post', 'del', 'put' r = request[method]( uri: process.env.PROXY_URL + req.url json: req.body) else return res.send('invalid method') req.pipe(r).pipe res
javascript:
app.use(function(req, res, next) { var method, r; method = req.method.toLowerCase().replace(/delete/,"del"); switch (method) { case "get": case "post": case "del": case "put": r = request[method]({ uri: process.env.PROXY_URL + req.url, json: req.body }); break; default: return res.send("invalid method"); } return req.pipe(r).pipe(res); });
Сначала установите express и http-proxy-middleware
npm install express http-proxy-middleware --save
затем на вашем сервере.js
const express = require('express'); const proxy = require('http-proxy-middleware'); const app = express(); app.use(express.static('client')); // Add middleware for http proxying const apiProxy = proxy('/api', { target: 'http://localhost:8080' }); app.use('/api', apiProxy); // Render your site const renderIndex = (req, res) => { res.sendFile(path.resolve(__dirname, 'client/index.html')); } app.get('/*', renderIndex); app.listen(3000, () => { console.log('Listening on: http://localhost:3000'); });
в этом примере мы обслуживаем сайт на порту 3000, но когда запрос заканчивается с /api, мы перенаправляем его на localhost:8080.
http://localhost:3000/api/login перейти к http://localhost:8080/api/login
Я создал очень простой модуль, который делает именно это: https://github.com/koppelaar/auth-proxy
Я нашел более короткое решение, которое делает именно то, что я хочу https://github.com/nodejitsu/node-http-proxy/
после установки
http-proxy
npm install http-proxy --save
используйте его, как показано ниже, в вашем сервере/индексе/приложении.js
var proxyServer = require('http-route-proxy'); app.use('/api/BLABLA/', proxyServer.connect({ to: 'other_domain.com:3000/BLABLA', https: true, route: ['/'] }));
Я действительно целыми днями искал везде, чтобы избежать этой проблемы, пробовал много решений, и ни один из них не работал, но это.
надеюсь, что это поможет кому-то еще тоже :)
у меня нет экспресс-образца, но один с простым
http-proxy
пакета. Очень урезанная версия прокси, которую я использовал для своего блога.короче говоря, все прокси-пакеты NodeJS http работают на уровне протокола http, а не на уровне tcp(сокета). Это также верно для express и всего промежуточного программного обеспечения express. Ни один из них не может сделать прозрачный прокси, ни NAT, что означает сохранение IP-адреса источника входящего трафика в пакете, отправленном на серверный веб-сервер.
однако, веб-сервер может возьмите исходный IP-адрес из http x-пересылаемых заголовков и добавьте его в журнал.
The
xfwd: true
наproxyOption
включить функцию заголовка x-forward дляhttp-proxy
.const url = require('url'); const proxy = require('http-proxy'); proxyConfig = { httpPort: 8888, proxyOptions: { target: { host: 'example.com', port: 80 }, xfwd: true // <--- This is what you are looking for. } }; function startProxy() { proxy .createServer(proxyConfig.proxyOptions) .listen(proxyConfig.httpPort, '0.0.0.0'); } startProxy();
Ссылка для заголовка X-Forwarded:https://en.wikipedia.org/wiki/X-Forwarded-For
Полная версия моего прокси:https://github.com/J-Siu/ghost-https-nodejs-proxy