NodeJS代理不按预期工作

请求的当前路由来自localhost:3001,通过在localhost:3001 / proxy上的同一本地主机上运行的代理,然后将请求路由到Salesforce实例。 代理使用ExpressJS进行,客户端应用使用AngularJS。 注意:我确实记得在我的密码末尾(Salesforce API要求)标记了我的安全令牌,虽然在使用cURL时似乎没有必要。 这里有一系列的HTTP跟踪,希望能够提供一些线索:

来自Angular.JS App的HTTP请求日志:

POST /proxy HTTP/1.1 Host: localhost:3001 Connection: keep-alive Content-Length: 234 Pragma: no-cache Cache-Control: no-cache X-User-Agent: salesforce-toolkit-rest-javascript/v29.0 Origin: http://localhost:3001 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.107 Safari/537.36 Content-Type: application/x-www-form-urlencoded Accept: application/json, text/plain, */* SalesforceProxy-Endpoint: https://uniquename.salesforce.com/services/oauth2/token Referer: http://localhost:3001/ Accept-Encoding: gzip, deflate Accept-Language: en-US,en;q=0.8 Cookie: liveagent_oref=; liveagent_ptid=3c69c2f9-139d-4439-ba6c-fd8d9dcae101; liveagent_vc=5 grant_type=password&client_id=3MVGxyzxyzxyzxyz&client_secret=99889988&username=first.last%40email.com&password=pswdwACYodaYfHs 400 Bad Request Object {error_description: "grant type not supported", error: "unsupported_grant_type"} 

用于代理路由的相关Express.JS代码:

 app.all('/proxy', function(req, res) { var url = req.header('SalesforceProxy-Endpoint'); console.log(req.body); //prints all form data variables in JSON format console.log(res.body); //undefined request({url: url}).pipe(res).on('error', function(error){ //I think I may need to pipe more information using request? console.log(error); }); }); 

使用cURL请求详细信息:

 curl -v https://uniquename.salesforce.com/services/oauth2/token -d "grant_type=password" -d "client_id=3MVGxyzxyzxyzxyz" -d "client_secret=99889988" -d "username=jfirst.last@email.com" -d "password=pswd" > POST /services/oauth2/token HTTP/1.1 > User-Agent: curl/7.41.0 > Host: uniquename.salesforce.com > Accept: */* > Content-Length: 207 > Content-Type: application/x-www-form-urlencoded > * upload completely sent off: 207 out of 207 bytes < HTTP/1.1 200 OK < Date: Wed, 29 Jul 2015 06:04:55 GMT < Set-Cookie: BrowserId=auu1mgvHSMS1EedDEduz8Q;Path=/;Domain=.salesforce.com;Exp ires=Sun, 27-Sep-2015 06:04:55 GMT < Expires: Thu, 01 Jan 1970 00:00:00 GMT < Pragma: no-cache < Cache-Control: no-cache, no-store < Content-Type: application/json;charset=UTF-8 < Transfer-Encoding: chunked < { "id":"https://test.salesforce.com/id/05390530530", "issued_at":"1438132525896197", "token_type":"Bearer", "instance_url":"https://uniquename.salesforce.com", "signature":"blahblah", "access_token":"XXXXXXXXXXXXXXXXX" } * Connection #0 to host uniquename.salesforce.com left intact 

正如你所看到的,我从cURL请求中获得有效的响应。 我怀疑代理有问题,因为它可能不会将所有表单数据转发到Salesforce,但我不知道如何在Express.JS中进行debugging。 我怀疑这是因为如果我尝试curl https://uniquename.salesforce.com/services/oauth2/token它返回相同的unsupported_grant_type错误。

我终于通过切换到使用Cors的任何地方代理得到这个工作。 我在端口8080上部署了我的AngularJS应用程序,并在端口3001上部署了代理。我的软件包使用npmgrunt进行pipe理。 这里是代理的代码:

 var host = 'localhost'; var port = 3001; var cors_proxy = require('cors-anywhere'); cors_proxy.createServer().listen(port, host, function() { console.log('CORS proxy running on ' + host + ':' + port); }); 

这里是我如何在AngularJS中发出HTTP请求(你必须在数据对象中填写你自己的凭证):

 var login = { method: 'POST', url: 'http://localhost:3001/https://login.salesforce.com/services/oauth2/token', data: 'grant_type=password&client_id='+encodeURIComponent(CLIENT_ID)+'&client_secret='+encodeURIComponent(CLIENT_SECRET)+'&username='+encodeURIComponent(EMAIL)+'&password='+encodeURIComponent(PASSWORD+USER_SECURITY_TOKEN), headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Accept': '*/*' } }; $http(login).success(function(response){ console.log(response); }) .error( function(response, status){ console.log(response); console.log("Status: " + status); }); 

您可以使用node server.js命令运行代理,并使用grunt运行AngularJS应用程序。 我希望这能帮助别人,这是一个难以解决的问题。

我不认为你在HTTP请求中代理所有的东西。 我已经包含了下面的一些代码,将请求方法和请求头传递给你的端点。还可以尝试使用'request-debug'库,以便比较代理HTTP请求和你的curl请求并寻找差异

 var express = require('express'); var app = express(); var request = require('request'); require('request-debug')(request); app.all('/proxy', function(req, res) { var url = req.header('SalesforceProxy-Endpoint'); var options = { url: url, method: req.method, headers: req.headers } request(options).pipe(res).on('error', function (error, response, body) { if (!error && response.statusCode == 200) { //TODO: do something useful with the response } else { console.log('ERROR: ' + error); } }); });