node.js - 无法在 ssr 中执行 https 请求

标签 node.js angular https angular-universal

我在从服务器调用 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 之前放置这个 env 变量,一切正常,NODE_TLS_REJECT_UNAUTHORIZED=0 ,但这不是解决方案,因为通过这种方式我禁用了安全性。

我该如何解决这个问题?

最佳答案

我也遇到了一个非常相似的问题,并为此苦苦挣扎了几个小时。申请 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0' fix 对我有用,但是,正如您所说,缺点是您将应用程序暴露给中间人攻击,从而损害了应用程序的安全性。
经过进一步调查,我意识到问题不在于 Angular。我跑了https.get('<my-api-url>')在 Node shell 中,我得到了:Uncaught Error: unable to verify the first certificate .事实证明,我只用叶证书配置了我的 API 服务器,而不是全链证书(叶 + CA 包)。与浏览器不同,Node 显然需要全链证书进行验证。
在我的服务器上安装全链证书后,问题就消失了,应用程序代码库没有任何更改。

关于node.js - 无法在 ssr 中执行 https 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46706273/

相关文章:

node.js - extraHeaders 未附加到请愿书上

未将 Angular 2 HTTP header 添加到请求中

Angular/Typescript 在接口(interface)中从蛇形大小写转换为驼峰大小写

https - 让 HTTPS 与 Traefik 和 GCE Ingress 配合使用

javascript - googleapis npm 模块和 webpack bundle 错误

android - 文件 style.xml 中不支持的 Node 'item'

http - HTTP 响应 header 中的校验和 - 为什么不呢?

android - (1002) - 没有可用的客户端连接器支持所需的协议(protocol) : 'HTTPS'

javascript - 从文件中打印换行数(node.js)

javascript - 来自 Node JS 中查询 SELECT Mongoose 的 JSON 解析错误