无法在 s-s-r 中执行 https 请求
Posted
技术标签:
【中文标题】无法在 s-s-r 中执行 https 请求【英文标题】:Cannot perform https request in s-s-r 【发布时间】:2018-03-24 04:40:00 【问题描述】:我在从服务器调用 https 时遇到了一个非常烦人的错误。
错误是Http failure response for (unknown url): 0 Unknown Error
。
在我的 Angular 应用程序中,我执行了一个 https 调用,当它在浏览器上执行时一切都很好,但是当这个调用在服务器上执行时,我得到了错误。 这是完整的错误:
HttpErrorResponse
headers: HttpHeaders normalizedNames: Map , lazyUpdate: null,
headers: Map ,
status: 0,
statusText: 'Unknown Error',
url: null,
ok: false,
name: 'HttpErrorResponse',
message: 'Http failure response for (unknown url): 0 Unknown Error',
error:
ProgressEvent
type: 'error',
target:
XMLHttpRequest
onloadstart: null,
onprogress: null,
onabort: null,
onerror: null,
onload: null,
ontimeout: null,
onloadend: null,
_listeners: [Object],
onreadystatechange: null,
_anonymous: undefined,
readyState: 4,
response: null,
responseText: '',
responseType: 'json',
responseURL: '',
status: 0,
statusText: '',
timeout: 0,
upload: [Object],
_method: 'GET',
_url: [Object],
_sync: false,
_headers: [Object],
_loweredHeaders: [Object],
_mimeOverride: null,
_request: null,
_response: null,
_responseParts: null,
_responseHeaders: null,
_aborting: null,
_error: null,
_loadedBytes: 0,
_totalBytes: 0,
_lengthComputable: false ,
currentTarget:
XMLHttpRequest
onloadstart: null,
onprogress: null,
onabort: null,
onerror: null,
onload: null,
ontimeout: null,
onloadend: null,
_listeners: [Object],
onreadystatechange: null,
_anonymous: undefined,
readyState: 4,
response: null,
responseText: '',
responseType: 'json',
responseURL: '',
status: 0,
statusText: '',
timeout: 0,
upload: [Object],
_method: 'GET',
_url: [Object],
_sync: false,
_headers: [Object],
_loweredHeaders: [Object],
_mimeOverride: null,
_request: null,
_response: null,
_responseParts: null,
_responseHeaders: null,
_aborting: null,
_error: null,
_loadedBytes: 0,
_totalBytes: 0,
_lengthComputable: false ,
lengthComputable: false,
loaded: 0,
total: 0
我的服务器和我调用的服务器的证书是可信且有效的。 这是我的服务器代码:
import 'reflect-metadata';
import 'zone.js/dist/zone-node';
import renderModuleFactory from '@angular/platform-server';
import enableProdMode from '@angular/core';
import * as express from 'express';
import join from 'path';
import readFileSync from 'fs';
import './global.imports';
import * as https from 'https';
enableProdMode();
const PORT = Number(process.env.PORT) || 4001;
const HOST_NAME = process.env.HOST;
const DIST_FOLDER = join(process.cwd(), 'dist');
const app = express();
const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html')).toString();
const AppServerModuleNgFactory = require('main.server');
app.engine('html', (_, options, callback) =>
const opts = document: template, url: options.req.url;
renderModuleFactory(AppServerModuleNgFactory, opts)
.then(html => callback(null, html));
);
app.set('view engine', 'html');
app.set('views', 'src');
app.get('*.*', express.static(join(DIST_FOLDER, 'browser')));
app.get('*', (req, res) =>
res.render('index', req);
);
const privateKey = readFileSync(`$DIST_FOLDER/server/config/ssl/key.pem`, 'utf8');
const certificate = readFileSync(`$DIST_FOLDER/server/config/ssl/cert.pem`, 'utf8');
const credentials = key: privateKey, cert: certificate;
// your express configuration here
const httpsServer = https.createServer(credentials, app);
httpsServer.listen(PORT, HOST_NAME, () =>
console.log(`listening to https://$HOST_NAME:$PORT`);
);
这是 https 的一个明显问题,因为如果我将这个环境变量放在 nom start 之前一切正常,NODE_TLS_REJECT_UNAUTHORIZED=0
,但这不是解决方案,因为这样我禁用了安全性。
我该如何解决这个问题?
【问题讨论】:
你找到解决办法了吗? 有什么更新吗? 2020年仍然面临同样的问题...... 【参考方案1】:我也遇到了一个非常相似的问题,并为此苦苦挣扎了几个小时。应用 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
修复对我有用,但正如您所说,缺点是您会通过将应用暴露于中间人攻击而危及应用的安全性。
经过进一步调查,我意识到问题不在于 Angular。我在 Node shell 中运行 https.get('<my-api-url>')
,得到:Uncaught Error: unable to verify the first certificate
。事实证明,我只使用叶子证书配置了我的 API 服务器,而不是全链证书(叶子 + CA 包)。与浏览器不同,Node 显然需要全链证书进行验证。
在我的服务器上安装 全链 证书后,问题就消失了,无需对应用代码库进行任何更改。
【讨论】:
以上是关于无法在 s-s-r 中执行 https 请求的主要内容,如果未能解决你的问题,请参考以下文章
NextJs s-s-r 无法识别移动设备的 CSS 媒体查询
Apollo 中 NextJs s-s-r 和 cookie 的问题
Vuejs-nuxt(s-s-r 模式)无法通过插件内部的 getter 获取 UserUUID。它显示未定义的 GetUserUUID