(未知 url)的 Http 失败响应 - Angular Docker 上的通用 (SSL)
Http failure response for (unknown url) - Angular Universal(SSL) on Docker
仅当api为HTTPS时才会出现该错误。
测试站点托管在 Digital Ocean.But 上,以下设置在我的本地(MAC Os)上使用自签名证书运行。
我尝试过的东西:
- 在 digitalocean 中禁用防火墙(sudo ufw 禁用)
- 节点 SSL 验证已禁用(NODE_TLS_REJECT_UNAUTHORIZED=0)
- 没有 cors 问题,我已经允许来自 api
的任何客户
下面是我的 docker 撰写设置
- web - 这是 nginx 容器
- laravel - 这是一个 api
- angualr - Angular 从网络
消耗 api 的通用
- 数据库 - mariadb 数据库
docker-compose.yml
version: '3'
services:
laravel:
build: ./laravel/docker/php
depends_on:
- database
expose:
- 9000
volumes:
- ./laravel:/var/www/laravel
- $HOME/.composer/:$HOME/.composer/
- ./laravel/docker/php/php-custom.ini:/usr/local/etc/php/conf.d/php-custom.ini
angular:
build: ./angular
expose:
- 9000
volumes:
- ./angular:/var/www/angular:rw
depends_on:
- laravel
links:
- laravel:laravel
web:
build: ./nginx
volumes:
- ./:/var/www/
- ./dh-param/dhparam-2048.pem:/etc/ssl/certs/dhparam-2048.pem:ro
- /docker-volumes/etc/letsencrypt/live/fabivo.com/fullchain.pem:/etc/letsencrypt/live/fabivo.com/fullchain.pem
- /docker-volumes/etc/letsencrypt/live/fabivo.com/privkey.pem:/etc/letsencrypt/live/fabivo.com/privkey.pem
ports:
- 80:80
- 443:443
links:
- laravel:laravel
- angular:angular
depends_on:
- laravel
- angular
environment:
- VIRTUAL_HOST=fabivo.com, portal.fabivo.com , api.fabivo.com, shop.fabivo.com
networks:
default:
aliases:
- api.fabivo.com
- portal.fabivo.com
- shop.fabivo.com
- fabivo.com
- api.paisaclub.com
database:
build: ./laravel/docker/mariadb
environment:
- "MYSQL_ROOT_PASSWORD=secret"
- "MYSQL_DATABASE=homestead"
- "MYSQL_USER=homestead"
- "MYSQL_PASSWORD=homestead"
ports:
- 3306:3306
volumes:
mysqldata:
networks:
default:
external:
name: nginx-proxy
nginx 配置
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name fabivo.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/fabivo.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/fabivo.com/privkey.pem;
ssl_buffer_size 8k;
ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
location / {
# NOTE THERE IS NO TRAILING SLASH AT THE END. NO TRAILING SLASH. NO SLASH. NO!
proxy_pass http://angular:9000; # <--- THIS DOES NOT HAVE A TRAILING '/'
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name api.fabivo.com portal.fabivo.com shop.fabivo.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/fabivo.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/fabivo.com/privkey.pem;
ssl_buffer_size 8k;
ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
location / {
try_files $uri /index.php?$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass laravel:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
#CSP
# add_header Content-Security-Policy "frame-src 'self'; default-src 'self'; script-src 'self' 'unsafe-inline' https://maxcdn.bootstrapcdn.com https://ajax.googleapis.com; img-src 'self'; style-src 'self' https://maxcdn.bootstrapcdn.com; font-src 'self' data: https://maxcdn.bootstrapcdn.com; form-action 'self'; upgrade-insecure-requests;" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}
}
server.ts
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
const domino = require('domino');
import { enableProdMode } from '@angular/core';
import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { join } from 'path';
import { readFileSync } from 'fs';
//import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens';
// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();
// Express server
const app = express();
const compression = require('compression');
const PORT = process.env.PORT || 9000;
const DIST_FOLDER = join(process.cwd(), 'dist');
//
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
// Our index.html we'll use as our template
const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html'), 'utf8').toString();
const win = domino.createWindow(template);
global['window'] = win;
Object.defineProperty(win.document.body.style, 'transform', {
value: () => {
return {
enumerable: true,
configurable: true
};
},
});
global['document'] = win.document;
global['$'] = require('jquery');
global['jQuery '] = global['$'];
global['Materialize'] = win.Materialize;
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main.bundle');
const { provideModuleMap } = require('@nguniversal/module-map-ngfactory-loader');
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
}));
app.use(compression());
app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER, 'browser'));
// Server static files from /browser
app.get('*.*', express.static(join(DIST_FOLDER, 'browser'), { maxAge: '1y' }));
// All regular routes use the Universal engine
app.get('*', (req, res) => {
res.render('index', {
req: req,
res: res
});
});
// Start up the Node server
app.listen(PORT, () => {
console.log(`Node server listening on http://localhost:${PORT}`);
});
更新:
这里是最小复制回购
https://github.com/ssatz/Angular-SSR-HTTPS-Error
部署到 heroku HEROKU
注意:这在我的本地使用自签名证书完美运行。
这是因为 SSL 配置。
如果有人遇到问题,请将 secp384r1 更改为 prime256v1
ssl_ecdh_curve prime256v1;
仅当api为HTTPS时才会出现该错误。 测试站点托管在 Digital Ocean.But 上,以下设置在我的本地(MAC Os)上使用自签名证书运行。
我尝试过的东西:
- 在 digitalocean 中禁用防火墙(sudo ufw 禁用)
- 节点 SSL 验证已禁用(NODE_TLS_REJECT_UNAUTHORIZED=0)
- 没有 cors 问题,我已经允许来自 api 的任何客户
下面是我的 docker 撰写设置
- web - 这是 nginx 容器
- laravel - 这是一个 api
- angualr - Angular 从网络 消耗 api 的通用
- 数据库 - mariadb 数据库
docker-compose.yml
version: '3'
services:
laravel:
build: ./laravel/docker/php
depends_on:
- database
expose:
- 9000
volumes:
- ./laravel:/var/www/laravel
- $HOME/.composer/:$HOME/.composer/
- ./laravel/docker/php/php-custom.ini:/usr/local/etc/php/conf.d/php-custom.ini
angular:
build: ./angular
expose:
- 9000
volumes:
- ./angular:/var/www/angular:rw
depends_on:
- laravel
links:
- laravel:laravel
web:
build: ./nginx
volumes:
- ./:/var/www/
- ./dh-param/dhparam-2048.pem:/etc/ssl/certs/dhparam-2048.pem:ro
- /docker-volumes/etc/letsencrypt/live/fabivo.com/fullchain.pem:/etc/letsencrypt/live/fabivo.com/fullchain.pem
- /docker-volumes/etc/letsencrypt/live/fabivo.com/privkey.pem:/etc/letsencrypt/live/fabivo.com/privkey.pem
ports:
- 80:80
- 443:443
links:
- laravel:laravel
- angular:angular
depends_on:
- laravel
- angular
environment:
- VIRTUAL_HOST=fabivo.com, portal.fabivo.com , api.fabivo.com, shop.fabivo.com
networks:
default:
aliases:
- api.fabivo.com
- portal.fabivo.com
- shop.fabivo.com
- fabivo.com
- api.paisaclub.com
database:
build: ./laravel/docker/mariadb
environment:
- "MYSQL_ROOT_PASSWORD=secret"
- "MYSQL_DATABASE=homestead"
- "MYSQL_USER=homestead"
- "MYSQL_PASSWORD=homestead"
ports:
- 3306:3306
volumes:
mysqldata:
networks:
default:
external:
name: nginx-proxy
nginx 配置
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name fabivo.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/fabivo.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/fabivo.com/privkey.pem;
ssl_buffer_size 8k;
ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
location / {
# NOTE THERE IS NO TRAILING SLASH AT THE END. NO TRAILING SLASH. NO SLASH. NO!
proxy_pass http://angular:9000; # <--- THIS DOES NOT HAVE A TRAILING '/'
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_http_version 1.1;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name api.fabivo.com portal.fabivo.com shop.fabivo.com;
server_tokens off;
ssl_certificate /etc/letsencrypt/live/fabivo.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/fabivo.com/privkey.pem;
ssl_buffer_size 8k;
ssl_dhparam /etc/ssl/certs/dhparam-2048.pem;
ssl_protocols TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDH+AESGCM:ECDH+AES256:ECDH+AES128:DH+3DES:!ADH:!AECDH:!MD5;
ssl_ecdh_curve secp384r1;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;
location / {
try_files $uri /index.php?$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass laravel:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
#CSP
# add_header Content-Security-Policy "frame-src 'self'; default-src 'self'; script-src 'self' 'unsafe-inline' https://maxcdn.bootstrapcdn.com https://ajax.googleapis.com; img-src 'self'; style-src 'self' https://maxcdn.bootstrapcdn.com; font-src 'self' data: https://maxcdn.bootstrapcdn.com; form-action 'self'; upgrade-insecure-requests;" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
}
}
server.ts
import 'zone.js/dist/zone-node';
import 'reflect-metadata';
const domino = require('domino');
import { enableProdMode } from '@angular/core';
import { ngExpressEngine } from '@nguniversal/express-engine';
import * as express from 'express';
import { join } from 'path';
import { readFileSync } from 'fs';
//import { REQUEST, RESPONSE } from '@nguniversal/express-engine/tokens';
// Faster server renders w/ Prod mode (dev mode never needed)
enableProdMode();
// Express server
const app = express();
const compression = require('compression');
const PORT = process.env.PORT || 9000;
const DIST_FOLDER = join(process.cwd(), 'dist');
//
process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;
// Our index.html we'll use as our template
const template = readFileSync(join(DIST_FOLDER, 'browser', 'index.html'), 'utf8').toString();
const win = domino.createWindow(template);
global['window'] = win;
Object.defineProperty(win.document.body.style, 'transform', {
value: () => {
return {
enumerable: true,
configurable: true
};
},
});
global['document'] = win.document;
global['$'] = require('jquery');
global['jQuery '] = global['$'];
global['Materialize'] = win.Materialize;
// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const { AppServerModuleNgFactory, LAZY_MODULE_MAP } = require('./dist/server/main.bundle');
const { provideModuleMap } = require('@nguniversal/module-map-ngfactory-loader');
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
}));
app.use(compression());
app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER, 'browser'));
// Server static files from /browser
app.get('*.*', express.static(join(DIST_FOLDER, 'browser'), { maxAge: '1y' }));
// All regular routes use the Universal engine
app.get('*', (req, res) => {
res.render('index', {
req: req,
res: res
});
});
// Start up the Node server
app.listen(PORT, () => {
console.log(`Node server listening on http://localhost:${PORT}`);
});
更新:
这里是最小复制回购 https://github.com/ssatz/Angular-SSR-HTTPS-Error 部署到 heroku HEROKU
注意:这在我的本地使用自签名证书完美运行。
这是因为 SSL 配置。 如果有人遇到问题,请将 secp384r1 更改为 prime256v1
ssl_ecdh_curve prime256v1;