programing

express.js를 사용하는 프록시

topblog 2023. 5. 8. 21:48
반응형

express.js를 사용하는 프록시

동일한 도메인 AJAX 문제를 방지하기 위해 node.js 웹 서버가 URL의 모든 요청을 전달하도록 합니다./api/BLABLA예를 들어, 다른 서버로other_domain.com:3000/BLABLA이 원격 서버가 투명하게 반환한 것과 동일한 내용을 사용자에게 반환합니다.

기타 모든 URL(별도)/api/*)는 직접 제공되며, 대리인이 아닙니다.

node.js + express.js에서 이를 달성하려면 어떻게 해야 합니까?간단한 코드 예를 들어줄 수 있습니까?

(웹 서버와 원격 모두)3000서버가 모두 express.js로 node.js를 실행하는 내 제어 하에 있습니다.)


지금까지 저는 이 https://github.com/http-party/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
    });
});

그러나 원래 웹 서버(또는 최종 사용자)에 반환되는 내용이 없으므로 운이 없습니다.

2020년 2월 현재 요청이 더 이상 사용되지 않습니다. 역사적인 이유로 아래에 답변을 남기겠습니다. 하지만 이번 호에 나열된 대안으로 이동하는 것을 고려해 주십시오.

기록 보관소

비슷한 작업을 했지만 대신 요청을 사용했습니다.

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);
});

보다 짧고 매우 간단한 솔루션을 찾았습니다. 이 솔루션은 완벽하게 작동하며 인증 기능도 갖추고 있습니다.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', {
    proxyReqPathResolver: req => url.parse(req.baseUrl).path
});

그리고 간단히 말하면,

app.use('/api/*', apiProxy);

참고: @MaxPRAPerty에서 언급한 바와 같이,req.originalUrl대신에baseUrl쿼리 문자열을 보존하려면:

    forwardPath: req => url.parse(req.baseUrl).path

업데이트: Andrew(감사합니다!)가 언급한 바와 같이, 동일한 원리를 사용하여 이미 만들어진 솔루션이 있습니다.

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)

설명서: Github의 http-proxy-middleware

원격 API와 유사한 요청을 생성하고 응답을 반환하는 데 사용하려고 합니다.

이와 같은 것:

const http = require('http');
// or use import http from 'http';


/* your app config here */

app.post('/api/BLABLA', (oreq, ores) => {
  const 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: oreq.headers,
  };

  const creq = http
    .request(options, pres => {
      // set encoding
      pres.setEncoding('utf8');

      // set http status code based on proxied response
      ores.writeHead(pres.statusCode);

      // wait for data
      pres.on('data', chunk => {
        ores.write(chunk);
      });

      pres.on('close', () => {
        // closed, let's end client request as well
        ores.end();
      });

      pres.on('end', () => {
        // finished, let's finish client request as well
        ores.end();
      });
    })
    .on('error', e => {
      // we got an error
      console.log(e.message);
      try {
        // attempt to set error message and http status
        ores.writeHead(500);
        ores.write(e.message);
      } catch (e) {
        // ignore
      }
      ores.end();
    });

  creq.end();
});

주의: 위의 내용을 실제로 시도하지 않았기 때문에 구문 분석 오류가 포함되어 있을 수 있습니다. 이를 통해 작동 방법에 대한 힌트를 얻을 수 있기를 바랍니다.

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);
});

다음 설정을 사용하여 모든 작업을 수행했습니다./rest내 백엔드 서버(포트 8080) 및 프런트엔드 서버(포트 3001의 웹 팩 서버)에 대한 기타 모든 요청.모든 HTTP 방식을 지원하고, 요청 메타 정보를 잃지 않으며, 웹 소켓(핫 새로고침에 필요함)을 지원합니다.

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);

먼저 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/http://localhost:8080/api/http로 리디렉션합니다.

좋아요. 하드코딩된 프록시 대신 require('request') npm 모듈과 환경 변수 *를 사용하여 복사하여 붙여넣을 준비가 된 답변입니다.

커피 대본

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);
});

원하는 것을 정확히 수행하는 짧은 솔루션을 찾았습니다. https://github.com/http-party/node-http-proxy

설치 후http-proxy

npm install http-proxy --save

서버/인덱스/app.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 프록시 패키지는 tcp(소켓) 수준이 아닌 http 프로토콜 수준에서 작동합니다.이는 고속 및 모든 고속 미들웨어에도 해당됩니다.이들 중 누구도 투명 프록시를 수행할 수 없으며 백엔드 웹 서버로 전송되는 패킷에 수신 트래픽 소스 IP를 유지하는 NAT도 수행할 수 없습니다.

그러나 웹 서버는 http x 전달 헤더에서 원본 IP를 가져와 로그에 추가할 수 있습니다.

xfwd: trueproxyOption에 대해 사용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

저는 프록시 요청을 더 잘 제어할 수 있는 방법을 알아냈습니다.

프록시 서버에서 요청한 응답은 xios를 사용하여 스트림 형식으로 클라이언트에 파이프라인으로 연결됩니다.

클라이언트에서 더 많은 정보를 프록시 서버를 통해 전달하기 위해 더 많은 헤더 및 데이터 본문 제어를 수행할 수 있습니다.

// proxy.js

import { Router } from "express";
var router = Router();
import axios from "axios";

// Proxy the request
router.all("/", async function (req, res, next) {
  let url = req.body["url"];
  let method = req.body["method"] ? req.body["method"] : "GET";
  let headers = req.body["headers"] ? req.body["headers"] : null;
  let params = req.body["params"] ? req.body["params"] : null;
  let data = req.body["data"] ? req.body["data"] : null;

  const response = await axios({
    method: method,
    url: url,
    headers: headers,
    params: params,
    data: data,
    responseType: "stream",
  });

  // Set the header of response as the header of the proxy response
  for (let key in response.headers) {
    res.setHeader(key, response.headers[key]);
  }

  // Pipe the response to the client
  const stream = response.data;
  stream.pipe(res);
});

export default router;
// client.js

fetch("http://localhost:3000/proxy", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        url: picURL,
        method: "GET",
        headers: { Host: "wx2.sinaimg.cn" },
      }),
    }).then(async (res) => {
      const blobURL = URL.createObjectURL(await res.blob());
    });

제 생각에 당신은 사용해야 할 것 같습니다.cors npm

const app = express();
const cors = require('cors');
var corsOptions = {
    origin: 'http://localhost:3000',
    optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204
}
app.use(cors(corsOptions));

https://www.npmjs.com/package/cors

언급URL : https://stackoverflow.com/questions/10435407/proxy-with-express-js

반응형