【问题标题】:Accessing webservices from a website which is running behind a proxy从在代理后面运行的网站访问 Web 服务
【发布时间】:2013-12-17 20:50:01
【问题描述】:

我正在使用 ember 和 express over node 设计一个网站。它在服务器中运行,例如:SERVER_1。

我在另一台服务器上运行的 web 服务很少,比如:SERVER_2。

即:

SERVER_1 中的网站和 SERVER_2 中可用的网络服务

SERVER_1 位于代理服务器后面。我正在尝试从 SERVER_1 访问网络服务:

SERVER_1 =====[PROXY]===> SERVER_2

当我从 SERVER_1 进行 AJAX 网络服务调用时,我收到:

NetworkError: 500 Internal Server Error

但是,我可以通过浏览器成功检索值。仅通过 AJAX 代码,我正在检索 Network 500 错误

另外为了测试,我删除了我的代理服务器设置:

SERVER_1 =====> SERVER_2

我能够通过 AJAX 代码和浏览器成功访问所有这些 Web 服务。

如果我在它们之间有代理服务器:

SERVER_1 =====[PROXY]===> SERVER_2

我收到了 -- NetworkError: 500 Internal Server Error

我想知道从在代理服务器后面运行的网站访问第三方网络服务的程序?

附加信息:

已经解决了跨域 Web 服务访问问题(网站在一台服务器上运行,Web 服务在其他具有不同端口的不同服务器上运行),我正在使用 http-proxy npm,我的代码是如下:

var express = require('express');
var routes = require('./routes');
var http = require('http');
var path = require('path');
var httpProxy = require('http-proxy');
var endpoint  = {
    host:   'IP_ADDRESS_WHERE_MY_WEBSERVICES_RUN',
    port:   80,
    prefix: '/api'
}

var proxy = new httpProxy.RoutingProxy();
var app = express();

app.set('port', process.env.PORT || 3000);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.methodOverride());
app.use(express.cookieParser('xxxxx'));
app.use(express.session());
app.use(app.router);
app.use(express.static(path.join(__dirname, 'public')));
app.use(function(req, res) {
    if (req.url.indexOf(endpoint.prefix) === 0) {
        proxy.proxyRequest(req, res, endpoint);
    }
});
app.use(express.bodyParser());

if ('development' == app.get('env')) {
    app.use(express.errorHandler());
}
app.get('/', routes.index);

http.createServer(app).listen(app.get('port'), function(){
    console.log('Express server listening on port ' + app.get('port'));
});

我的 AJAX 调用:

$.ajax({
            type: 'GET',
            async: false,
            url: 'API_URL',
            success: function (data) {
                alert('success');
            },
            failure: function(error){
                alert('error');
            }
        });

我已经使用 http-proxy 来处理所有 url 的请求了。

如何在上面的代码中配置我的代理服务器的IP地址和端口,以便我可以成功访问所有这些网络服务?或者有什么方法可以让我的代理配置在 AJAX 调用中?

谁能指导我?

谢谢

【问题讨论】:

  • 使用forward proxy怎么样?
  • Node.js 中的许多对象不会引发错误,而是会发出 error 事件。只需收听错误事件并console.log 它,以便我们知道发生了什么。
  • 我尝试使用正向代理。但是,它并没有帮助我。你能指导我吗?
  • 设置NPM配置与你的问题无关。据我了解,您有一个本地服务器 S1 正在尝试访问代理后面的外部 url S2: [ S1 ] ==== [ proxy ] ===> [ S2 ] 您使用库来请求 S2 S1 ?除非您直接从 Ajax 的浏览器中使用这些 REST Web 服务?
  • 感谢 Feugy 的回复。我在 S1 中使用 http 和 http-proxy 库来访问 Web 服务(在 S2 中运行)。你是对的,S1 在代理服务器后面。如果我删除此代理服务器,我可以成功访问 Web 服务。代码在“附加信息”部分提供。我的问题是,当我有代理服务器时。我在访问网络服务时遇到了麻烦。

标签: node.js ember.js proxy node-http-proxy webproxy


【解决方案1】:

通常你需要做这两件事:

npm config set proxy your-proxy-address:port npm 配置设置注册表“http://registry.npmjs.org/

【讨论】:

  • 这两个我都试过了。但是,它没有帮助。正如我之前所说,我可以安装所有 npm 包(这意味着我的节点服务器可以连接到互联网并下载所有包)。但是,如果我在我的公司代理后面调用那些第 3 方网络服务,我会收到这样的错误。所以我觉得我的网站节点设置中应该有一些代码(包括我的代理 IP 和端口).. 你能进一步指导我吗?
  • 如果一切都失败了,您始终可以将主机配置为整体以使用代理服务器。是windows还是linux主机?您应该首先确保代理确实是您的问题,首先登录到(节点服务器)主机并使用跟踪路由到您尝试使用的 Web 服务的地址应该向您显示数据包在您的网络上停止的位置。 wget --proxy-user=USERNAME --proxy-password=PASSWORD path.to.domain.com/some.html 。将让您直接尝试从代理访问端点。当
  • 感谢达伦·怀特的回复。我已经编辑了我的问题。能否请您谈谈您对此的看法?
  • 你需要执行我建议的网络命令。您不是在沙箱中工作 - 正如其他人建议的那样,您需要隔离您的问题。您的浏览器显然正在使用代理设置。您的主机上还有其他内容吗?如果您的主机在代理之后,您如何从 Internet 更新或修补?这些应用是否也正确使用了代理?
  • 感谢达伦的回复。它真的在指导我。我觉得只有我的 [PROXY] 服务器阻止了所有 API 调用(请求没有通过代理服务器)。我通过以下场景发现了这一点:最初客户端和服务器之间没有代理服务器。我能够成功访问 API。当我在客户端和服务器之间引入代理服务器时,我收到了这个错误。因此,我觉得代理服务器正在阻止我的 API 请求。我觉得,我必须以某种方式在客户端代码中配置代理服务器的 IP 和端口才能访问 API。
【解决方案2】:

一般来说,我建议您尝试通过更多隔离问题来解决此问题。

开放变量仍然太多。您的请求是真的通过代理还是在代理中消失了?如果它离开代理 - 为什么不只构建 [代理] -> Server2?

我有一种直觉,问题出在代理转发的(丢失的)标头中。例如,当进程在发送输出时终止时,这个“NetworkError:500”是由 PHP 服务器创建的。也许你在 Server2 中触发了一个错误,因为你的代理输出与 Server1 的输出不同?

只需将 Proxy 的输出与 Server1 的输出进行比较(nc 是您的朋友)。希望这会有所帮助。

【讨论】:

  • 我觉得我的 [PROXY] 服务器正在阻止所有 API 调用(这些 API 请求没有通过代理服务器)。我通过代理服务器的 squid 访问日志确认了这一点。首先,我从浏览器访问 API(通过调用 API URL)。我成功收到响应,并且在 squid 中有一个用于此 API 调用的日志条目。现在,我通过我的 AJAX 代码尝试了相同的 API 调用,现在 squid 日志中没有响应并且没有条目。我觉得,我的 squid 代理服务器正在阻止或不允许这些 api 调用。你能指导我进一步吗?
  • 嗯...好消息似乎问题完全在您的控制之下。查看您调用代理的代码。我不知道这个模块,但你不返回任何值,也不交回电话。也许那里有问题?穷人调试器:console.log 可能有帮助?
  • 对不起,我对这个 node-http-proxy 模块太陌生了。已经解决了跨域 AJAX 问题,我正在使用 RoutingProxy(请查看我在“附加信息”部分中找到的代码。现在我觉得,我需要以某种方式包含我的代理服务器的 ip 和端口,以便从我的客户端到服务器。你能说在哪里调试我的代码吗?
  • 优秀 - 发布您的 squid 配置 :)
  • 您可能希望通过使用整个主机的代理设置来完全消除所有节点 - 例如导出 http_proxy=server-ip:port。然后,您可以使用 wget 或 telnet 访问您正在使用的服务来确认代理正在阻塞,而不是您应用中的任何内容配置错误。
【解决方案3】:

如果孙子在这个线程上,他会告诉你正确的策略是一开始就不在这个位置。由于端口 443 通常在所有公司网络上都是开放的,为了允许 https 流量考虑使用(某人的)云产品在某处创建服务器并在端口 443 上通过 ssh 连接到它。您甚至可以使用此技术创建自己的代理以用于开发目的(参见 squidd)- 这样至少您至少可以看到代理日志。

您正试图同时解决两个问题 - 一个是联网,另一个是您正在编写的代码。这样做意味着您一次只需要解决一个问题,也不会阻碍您的进步。

【讨论】:

    【解决方案4】:

    我发现,我的代理路由 API URL 在这里造成了麻烦。我的代理服务器阻止了所有这些路由 URL。

    由于我无法在代理服务器后面找到路由代理 API 调用的答案,因此我进行了如下临时补丁修复:

    从应用服务器中删除了现有的代理路由代码(我之前用来解决跨域 AJAX 问题):

    var express = require('express');
    var routes = require('./routes');
    var http = require('http');
    var path = require('path');
    
    var app = express();
    
    app.set('port', process.env.PORT || 3000);
    app.set('views', path.join(__dirname, 'views'));
    app.set('view engine', 'ejs');
    app.use(express.favicon());
    app.use(express.logger('dev'));
    app.use(express.methodOverride());
    app.use(express.cookieParser('xxxxx'));
    app.use(express.session());
    app.use(app.router);
    app.use(express.static(path.join(__dirname, 'public')));
    app.use(express.bodyParser());
    
    if ('development' == app.get('env')) {
        app.use(express.errorHandler());
    }
    app.get('/', routes.index);
    
    http.createServer(app).listen(app.get('port'), function(){
        console.log('Express server listening on port ' + app.get('port'));
    });
    

    现在,我的 AJAX 调用将是:

            $.ajax({
                type: 'GET',
                async: false,
                url: 'FULL_API_URL', 
                success: function (data) {
                    alert('success');
                },
                failure: function(error){
                    alert('error');
                }
            });
    

    为了处理 AJAX 调用中的跨域问题,我通过在来自服务器的所有 API 响应中添加“Access-Control-Allow-Origin”标头来进行服务器端修复。

    一些附加信息: 如果有人在 AJAX 中遇到跨域问题,需要 IE8 和 IE9 浏览器,请参阅: https://github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest

    谢谢

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-02
      • 2016-03-20
      • 1970-01-01
      相关资源
      最近更新 更多