使用 http-proxy 代理 SAP UI5 應用發起的 HTTP 請求

注销發表於2022-02-20

原始碼如下:使用方法 createProxyServer 建立一個代理伺服器, 監聽在埠 8082 上,把請求傳送給 localhost:9000 上監聽的伺服器。

後者僅僅返回一個 request successfully proxied 的訊息給請求方。

var http = require('http'),
    httpProxy = require('http-proxy');

httpProxy.createProxyServer({target:'http://localhost:9000'}).listen(8082); 

http.createServer(function (req, res) {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.write('request successfully proxied!' + '\n' + JSON.stringify(req.headers, true, 2));
  res.end();
}).listen(9000);

遇到錯誤訊息:

Access to XMLHttpRequest at 'http://localhost:8082/https:/...$metadata?sap-language=EN' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

解決方案

在 HTTP response 頭部欄位增添一條欄位:"Access-Control-Allow-Origin": "*"

重啟 proxy 伺服器之後,錯誤訊息變成了:

Access to XMLHttpRequest at 'http://localhost:8082/https:/...$metadata?sap-language=EN' from origin 'http://localhost:8080' has been blocked by CORS policy: Request header field maxdataserviceversion is not allowed by Access-Control-Allow-Headers in preflight response.

解決辦法是,在 response 裡新增如下欄位:

res.writeHead(200, { 'Content-Type': 'text/plain',
                        "Access-Control-Allow-Origin": "*",
                        "Access-Control-Allow-Headers": "*" });

修改之後問題消失:

SAP UI5 應用發起的 metadata 資料請求,被 proxy 伺服器成功攔截並返回:

Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: Host: localhost. is not in the cert's altnames: DNS:.azurewebsites.net, DNS:.scm.azurewebsites.net, DNS:.azure-mobile.net, DNS:.scm.azure-mobile.net, DNS:*.sso.azurewebsites.net
at Object.checkServerIdentity (tls.js:287:12)
at TLSSocket.onConnectSecure (_tls_wrap.js:1511:27)
at TLSSocket.emit (events.js:315:20)
at TLSSocket._finishInit (_tls_wrap.js:936:8)
at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:710:12) {

reason: "Host: localhost. is not in the cert's altnames: DNS:.azurewebsites.net, DNS:.scm.azurewebsites.net, DNS:.azure-mobile.net, DNS:.scm.azure-mobile.net, DNS:*.sso.azurewebsites.net",
host: 'localhost',

這個錯誤和這個 StackOverflow 討論相關。

程式碼也類似:

var express = require('express');
var app = express();
var httpProxy = require('http-proxy');
var apiProxy = httpProxy.createProxyServer();
var serverOne = 'https://idena.navarra.es/ogc/wms?';

app.all('/idena', function (req, res) {
  apiProxy.web(req, res, {target: serverOne});
});

app.listen(3000, function () {
  console.log('Working!');
});

當請求傳送給 idena 時,代理伺服器試圖傳送往伺服器:https://idena.navarra.es/ogc/...

源伺服器是 HTTP,而目的伺服器是 HTTPS.

解決這個錯誤的辦法:在 proxy option 裡,指定下列這個選項:

changeOrigin: true

重新 proxy 伺服器之後,問題消失:ERR_TLS_CERT_ALTNAME_INVALID 錯誤被修復了。

但是這個錯誤訊息又回來了:

http://localhost:8082/https:/...$metadata?sap-language=EN' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

400 bad request:

直接訪問這個 url:http://localhost:8082/https:/...$metadata?sap-language=EN

會遇到如下錯誤:

更多Jerry的原創文章,盡在:"汪子熙":

相關文章