【问题标题】:No response using express proxy route使用快速代理路由没有响应
【发布时间】:2011-11-25 11:15:04
【问题描述】:

我用 nodejs、express 和 htt-proxy 编写了一个小型代理。它适用于提供本地文件,但在代理到外部 api 时失败:

var express = require('express'),
    app = express.createServer(),
    httpProxy = require('http-proxy');


app.use(express.bodyParser());
app.listen(process.env.PORT || 1235);

var proxy = new httpProxy.RoutingProxy();

app.get('/', function(req, res) {
    res.sendfile(__dirname + '/index.html');
});
app.get('/js/*', function(req, res) {
    res.sendfile(__dirname + req.url);
});
app.get('/css/*', function(req, res) {
    res.sendfile(__dirname + req.url);
});

app.all('/*', function(req, res) {
    req.url = 'v1/public/yql?q=show%20tables&format=json&callback=';
    proxy.proxyRequest(req, res, {
        host: 'query.yahooapis.com', //yahoo is just an example to verify its not the apis fault
        port: 8080
    });

});

问题是yahoo api没有响应,也许有响应但我没有在浏览器中出现。

【问题讨论】:

    标签: node.js proxy express


    【解决方案1】:

    这就是我已经使用了一段时间的东西。可以处理 JSON 和二进制请求。

    app.use('/api', (req, res, next) => {
        const redirectUrl = config.api_server + req.url.slice(1);
        const redirectedRequest = request({
            url: redirectUrl,
            method: req.method,
            body: req.readable ? undefined : req.body,
            json: req.readable ? false : true,
            qs: req.query,
            // Pass redirect back to the browser
            followRedirect: false
        });
        if (req.readable) {
            // Handles all the streamable data (e.g. image uploads)
            req.pipe(redirectedRequest).pipe(res);
        } else {
            // Handles everything else
            redirectedRequest.pipe(res);
        }
    });
    

    【讨论】:

      【解决方案2】:

      我最终使用了http-proxy-middleware

      代码如下所示:

      var express = require("express");
      var proxy = require("http-proxy-middleware");
      
      const theProxy = proxy({
        target: "query.yahooapis.com",
        changeOrigin: true,
      });
      
      app.use("/", theProxy);
      app.listen(process.env.PORT || 3002);
      

      【讨论】:

        【解决方案3】:

        使用piperequest-Package 更简单

        var request = require('request');
        
        app.use('/api', function(req, res) {
          var url = apiUrl + req.url;
          req.pipe(request(url)).pipe(res);
        });
        

        它将整个请求通过管道传输到 API,并将响应传输回请求者。这也处理 POST/PUT/DELETE 和所有其他请求 \o/

        如果你也关心查询字符串,你也应该使用管道

        req.pipe(request({ qs:req.query, uri: url })).pipe(res);
        

        【讨论】:

        • 当请求具有 json 内容类型时,pipe 行挂起 - 请参阅 this question
        • 只使用上面的request(url).pipe(res); 最终会做到这一点,但您会丢失除 URL 之外的任何请求特定信息。我建议的方法是首先将整个请求传递给 API,然后将响应传递回请求者。这就是为什么会出现两个管道。
        • 如果其他人遇到这个问题,下面的代码可以正确传递查询字符串值 - req.pipe(request({ qs:req.query, uri: db_url })).pipe(res);
        • @HazardouS 感谢您的提示。我相应地更新了答案。
        • 如@Jonathan的链接所示,如果content-type是JSON,则在request参数中添加json: true,这样就变成了:req.pipe(request({ qs:req.query, uri: url, json: true })).pipe(res);
        【解决方案4】:

        也许我以错误的方式使用了 http-proxy。使用 restler 做我想做的事:

        var express = require('express'),
            app = express.createServer(),
            restler = require('restler');
        
        
        app.use(express.bodyParser());
        app.listen( 1234);
        
        
        
        app.get('/', function(req, res) {
            console.log(__dirname + '/index.html')
            res.sendfile(__dirname + '/index.html');
        });
        app.get('/js/*', function(req, res) {
            res.sendfile(__dirname + req.url);
        });
        app.get('/css/*', function(req, res) {
            res.sendfile(__dirname + req.url);
        });
        
        
        app.all('/*', function(req, res) {
        
            restler.get('http://myUrl.com:80/app_test.php/api' + req.url, {
        
                }).on('complete', function (data) {
                        console.log(data)
                       res.json(data)
                    });
        
        });
        

        【讨论】:

          【解决方案5】:

          也许您的代码在测试时有所不同,但我使用以下代码查询与您的代码示例中相同的 URL:

          http://query.yahooapis.com:8080/v1/public/yql?q=show%20tables&format=json&callback=

          我什么也得不到。我的猜测是您想将端口更改为 80(从 8080)- 当我这样更改时它可以工作:

          http://query.yahooapis.com:80/v1/public/yql?q=show%20tables&format=json&callback=

          所以这意味着它应该是:

          proxy.proxyRequest(req, res, {
              host: 'query.yahooapis.com', //yahoo is just an example to verify its not the apis fault
              port: 80
          });
          

          【讨论】:

          • 好的,更改端口也适用于我的项目,但不幸的是我从服务器收到了 404。在浏览器中调用相同的 url 就可以了。
          猜你喜欢
          • 2018-12-26
          • 1970-01-01
          • 2018-03-04
          • 2018-09-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-08-13
          相关资源
          最近更新 更多