এক্সপ্রেস.জেএস সহ প্রক্সি


168

একই ডোমেনের এজেএক্স সমস্যাগুলি এড়াতে, আমি চাই আমার নোড.জেএস ওয়েব সার্ভারটি ইউআরএল থেকে সমস্ত অনুরোধ /api/BLABLAঅন্য সার্ভারে ফরোয়ার্ড করবে , উদাহরণস্বরূপ other_domain.com:3000/BLABLA, এবং ব্যবহারকারীর কাছে এই দূরবর্তী সার্ভারটি স্বচ্ছভাবে ফিরে এসেছিল।

অন্যান্য সমস্ত ইউআরএল (পাশে /api/*) সরাসরি পরিবেশন করা হবে, কোনও প্রক্সিং নয়।

আমি কীভাবে এটি নোড.জেএস + এক্সপ্রেস.জেএস দিয়ে অর্জন করব? আপনি একটি সহজ কোড উদাহরণ দিতে পারেন?

(ওয়েব সার্ভার এবং রিমোট 3000সার্ভার উভয়ই আমার নিয়ন্ত্রণাধীন, এক্সপ্রেস.জেএস সহ নোড.জেস উভয়ই চলছে)


এখনও অবধি আমি এই 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
    });
});

তবে আসল ওয়েব সার্ভারে (বা শেষ ব্যবহারকারীকে) কিছুই ফিরিয়ে দেওয়া হয়নি, তাই ভাগ্য নেই।


আপনি যেভাবে এটি করছেন তা কোনও পরিবর্তন ছাড়াই আমার পক্ষে কাজ করছে
Saule

1
যদিও উত্তর দিতে কিছুটা দেরী হয়েছে, তবে অনুরূপ সমস্যার মুখোমুখি হয়েছিল এবং বডি পার্সারটি সরিয়ে এটি সমাধান করেছে যাতে অনুরোধের বডিটি আরও প্রক্সিং করার আগে পার্স করা যায় না।
ভিভিট

উত্তর:


52

আপনি ব্যবহার করতে চান http.request দূরবর্তী এপিআই তে অনুরূপ অনুরোধ তৈরি করতে এবং তার প্রতিক্রিয়া ফিরিয়ে দিতে চান।

এটার মতো কিছু:

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

বিজ্ঞপ্তি: আমি সত্যিই উপরেরটি চেষ্টা করে দেখিনি, সুতরাং এতে পার্স ত্রুটি থাকতে পারে আশা করি এটি আপনাকে কীভাবে এটি কাজ করবে তা সম্পর্কে একটি ইঙ্গিত দেয়।


5
হ্যাঁ, কিছু পরিবর্তন প্রয়োজন ছিল, তবে আমি অতিরিক্ত নতুন "প্রক্সি" মডিউল নির্ভরতা প্রবর্তন করার চেয়ে ভাল এটি পছন্দ করি। কিছুটা ভার্জোজ, তবে কমপক্ষে আমি জানি ঠিক কী চলছে। চিয়ার্স।
ব্যবহারকারী 124114

দেখে মনে হচ্ছে আপনাকে ডেটা চিঙ্ক লেখার আগে পুনরায় রাইটারহাইডটি করা দরকার, অন্যথায় আপনি ত্রুটি পাবেন (শিরোনাম শরীরের পরে লেখা যায় না)।
setec

3
@ ব্যবহারকারী 124114 - দয়া করে আপনি যে পুরো সমাধানটি ব্যবহার করেছেন তা রাখুন
মাইকেল সাসাদোক

1
মনে হচ্ছে আপনার এইভাবে শিরোনাম স্থাপন করতে সমস্যা হবে। Cannot render headers after they are sent to the client
শনিবার

1
আমি এস -6 সিনট্যাক্সের উত্তর আপডেট করেছি এবং লিখিতহাইড ইস্যুটি ঠিক করেছি
মেকওয়াল

219

অনুরোধটি ২০২০ সালের ফেব্রুয়ারি পর্যন্ত অবহেলা করা হয়েছে, আমি নীচের উত্তরটি historicalতিহাসিক কারণে ছেড়ে দেব, তবে দয়া করে এই ইস্যুতে তালিকাভুক্ত বিকল্পটিতে যাওয়ার কথা বিবেচনা করুন ।

সংরক্ষাণাগার

আমি অনুরূপ কিছু করেছি তবে পরিবর্তে আমি অনুরোধটি ব্যবহার করেছি:

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

আমি আশা করি এটি সাহায্য করে, আমি এটি করতে পারি বুঝতে পেরে আমাকে কিছুটা সময় নিল :)


5
ধন্যবাদ, নোড.জেএস'এইচটিপি অনুরোধের চেয়ে অনেক বেশি সহজ
অ্যালেক্স টারপিন

17
এমনকি সহজ, আপনি যদি অনুরোধটিও পাইপ করেন: স্ট্যাকওভারফ্লো.com
স্টিফান হোয়ের

1
সুন্দর এবং পরিষ্কার সমাধান। এটি পোস্ট পোস্টের অনুরোধের সাথে কাজ করার জন্য আমি একটি উত্তর পোস্ট করেছি (অন্যথায় এটি আপনার পোস্ট বডিটি এপিআইতে ফরোয়ার্ড করে না)। আপনি যদি আপনার উত্তরটি সম্পাদনা করেন তবে আমি আমার অপসারণ করতে পেরে খুশি হব।
হেনরিক পিনার

উন্নত ত্রুটি পরিচালনার জন্য এই উত্তরটি দেখুন ।
তামিলেন

যখনই আমি অনুরূপ রাউটিংটি করার চেষ্টা করি (বা ঠিক একই) আমি নিম্নলিখিতটি দিয়ে শেষ করি: স্ট্রিম.জেএস: ৯৯ নিক্ষেপ; // পাইপে আনহ্যান্ডেল স্ট্রিম ত্রুটি। ^ ত্রুটি: getaddrinfo ENOTFOUND google.com এ errnoException (dns.js: 44: 10) এ getAddrInfoReqWrap.onlookup এ (অনুলিপি হিসাবে) (dns.js: 94: 26) কোনও ধারণা?
কেইনাবেল

82

আমি একটি সংক্ষিপ্ত এবং খুব সোজা সমাধান খুঁজে পেয়েছি যা নিরবচ্ছিন্নভাবে কাজ করে এবং প্রমাণীকরণের পাশাপাশি, ব্যবহার করে 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);

নোট: যেমন @MaxPRafferty উল্লেখ, ব্যবহার req.originalUrlস্থানে baseUrlquerystring সংরক্ষণ:

    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- প্রক্সি-মিডলওয়্যার

আমি জানি আমি এই পার্টিতে যোগ দিতে দেরি করেছি, তবে আমি আশা করি এটি কারও সাহায্য করবে helps


3
রেক.আরএল এর সম্পূর্ণ ইউআরএল নেই, তাই পুনঃআরকেলে পরিবর্তে রেক.বেস ইউআরএল ব্যবহারের উত্তর আপডেট করেছেন
বিনোথ কুমার

1
আমি ক্যোরিস্ট্রিংগুলি সংরক্ষণের জন্য বেসউআরএলটির জায়গায় req.originalUrl ব্যবহার করতে চাই তবে এটি সর্বদা পছন্দসই আচরণ নাও হতে পারে।
ম্যাক্সপ্রেফার্টি

@ ম্যাক্সপিআরএফের্টি - উদাসীন মন্তব্য। মূল্যবান। ধন্যবাদ।
স্বার্থপর

4
এটিই সেরা সমাধান। আমি এইচটিপি-প্রক্সি-মিডলওয়্যার ব্যবহার করছি তবে এটি একই ধারণা। ইতিমধ্যে যখন খুব ভাল রয়েছে তখন আপনার নিজের প্রক্সি সমাধানটি স্পিন করবেন না।
অ্যান্ড্রু

1
@ ট্যানারবার্টন ধন্যবাদ! আমি উত্তর আপডেট।
স্বার্থপর

46

পোষ্টের সাথে কাজ করার জন্য ট্রিগম্যানের জবাব (তার কাছে সম্পূর্ণ ক্রেডিট) প্রসারিত করা ( পিটি ইত্যাদি দিয়েও কাজ করতে পারে):

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

1
এটি পুট দিয়ে কাজ করতে পারেনি। তবে জিইটি এবং পোষ্টের জন্য দুর্দান্ত কাজ করে। ধন্যবাদ!!
মারিয়ানো দেশানজে

5
@ পুটোর অনুরোধের জন্য প্রোট্রন ঠিক if(req.method === 'PUT'){ r = request.put({uri: url, json: req.body}); }
তেমন

যদি আপনাকে পুট বা পোষ্ট অনুরোধের অংশ হিসাবে শিরোনাম দিয়ে যেতে হয় তবে বিষয়বস্তু-দৈর্ঘ্যের শিরোনামটি মুছে ফেলার বিষয়টি নিশ্চিত করুন যাতে অনুরোধটি এটি গণনা করতে পারে। অন্যথায়, গ্রহণকারী সার্ভারটি ডেটা কেটে ফেলতে পারে, যা ত্রুটির দিকে পরিচালিত করবে।
কার্লোস রাইমার

@Henrik Peinar, এই সাহায্যের যখন আমি একটি লগইন পোস্ট অনুরোধ এবং web.com/api/login থেকে web.com/ পুনর্চালনা আশা করবে
valik

22

আমি /restআমার ব্যাক-এন্ড সার্ভারে (পোর্ট ৮০৮০) এবং অন্যান্য সমস্ত অনুরোধগুলি ফ্রন্টএন্ড সার্ভারে (পোর্ট 3001 পোর্টের একটি ওয়েবপ্যাক সার্ভার) নির্দেশ করতে নীচের সেটআপটি ব্যবহার করেছি। এটি সমস্ত এইচটিটিপি-পদ্ধতি সমর্থন করে, কোনও অনুরোধ মেটা-তথ্য হারাবে না এবং ওয়েবসকেটগুলি সমর্থন করে (যা আমার গরম পুনরায় লোড করার জন্য প্রয়োজন)

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

1
এটি কেবলমাত্র ওয়েব সকেটগুলির সাথেও কাজ করে।
সেকেন্ড এবং

11

প্রথমে এক্সপ্রেস এবং http- প্রক্সি-মিডলওয়্যার ইনস্টল করুন

npm install express http-proxy-middleware --save

তারপরে আপনার সার্ভার.জে

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 পোর্টে সাইটটি পরিবেশন করি তবে যখন কোনও অনুরোধটি / এপিআই দিয়ে শেষ হয় তখন আমরা এটিকে লোকালহোস্টে পুনঃনির্দেশ করি: 8080।

http: // লোকালহোস্ট: 3000 / এপিআই / লগইন পুনঃনির্দেশ HTTP: // লোকালহোস্ট: 8080 / এপিআই / লগইন


6

ঠিক আছে, এখানে প্রয়োজনীয় ('অনুরোধ') এনপিএম মডিউল এবং হার্ডকোডযুক্ত প্রক্সিটির পরিবর্তে পরিবেশ পরিবর্তনশীল * ব্যবহার করে একটি কপি-পেস্টের উত্তর দেওয়া আছে:

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

জাভাস্ক্রিপ্ট:

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

2
কোনও কেস স্টেটমেন্টের পরিবর্তে আলাদা আলাদা অনুরোধের ফাংশন ব্যবহার ব্যতীত একই কাজটি করে) আপনি প্রথমে স্যানিটাইজ করতে পারেন (উদাহরণস্বরূপ, যদি কোনও পদ্ধতি যদি অনুমোদিত পদ্ধতিগুলির তালিকায় না থাকে তবে আপনার ডিফল্টকে ডাকে এমন একটি বিবৃতি), এবং তারপরে ঠিক করুন আর = অনুরোধ [পদ্ধতি] (/ * বাকি * /);
পল

2

আমি একটি সংক্ষিপ্ত সমাধান পাওয়া না যে, আমি ঠিক কি আপনি চান https://github.com/http-party/node-http-proxy

ইনস্টল করার পরে http-proxy

npm install http-proxy --save

এটি আপনার সার্ভার / সূচী / অ্যাপ.জেজে নীচের মতো ব্যবহার করুন Use

var proxyServer = require('http-route-proxy');
app.use('/api/BLABLA/', proxyServer.connect({
  to: 'other_domain.com:3000/BLABLA',
  https: true,
  route: ['/']
}));

আমি এই সমস্যাটি এড়াতে সব জায়গাতেই সত্যই দিন কাটিয়েছি, প্রচুর সমাধানের চেষ্টা করেছি এবং তাদের কেউই এই ব্যতীত কাজ করে নি।

আশা করি এটি অন্য কাউকেও সহায়তা করবে :)


0

আমার কাছে এক্সপ্রেস নমুনা নেই, তবে সরল http-proxyপ্যাকেজ সহ একটি। আমি আমার ব্লগের জন্য ব্যবহৃত প্রক্সিটির খুব স্ট্রিপ ডাউন সংস্করণ।

সংক্ষেপে, সমস্ত নোডেজ HTTP প্রক্সি প্যাকেজগুলি টিসিপি (সকেট) স্তর নয়, HTTP প্রোটোকল স্তরে কাজ করে। এক্সপ্রেস এবং সমস্ত এক্সপ্রেস মিডলওয়্যারের ক্ষেত্রে এটি সত্য। এগুলির মধ্যে কেউ স্বচ্ছ প্রক্সি বা নাটি করতে পারে না, যার অর্থ ব্যাকএন্ড ওয়েব সার্ভারে প্রেরিত প্যাকেটে আগত ট্র্যাফিক সোর্স আইপি রাখা।

যাইহোক, ওয়েব সার্ভার HT এক্স এক্স-ফরওয়ার্ডড শিরোনামগুলি থেকে মূল আইপিটি নিতে এবং এটিকে লগে যুক্ত করতে পারে।

xfwd: trueমধ্যে proxyOptionজন্য x- এগিয়ে হেডার বৈশিষ্ট্যটি সক্ষম 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();

এক্স-ফরওয়ার্ড শিরোলেখের জন্য রেফারেন্স: https://en.wikedia.org/wiki/X- ফরওয়ার্ড- ফর

আমার প্রক্সিটির সম্পূর্ণ সংস্করণ: https://github.com/J-Siu/ghost-https-nodejs-proxy

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.