Closed ranjitnadar closed 3 years ago
How does it fail?
Using http powered api SSR working perfectly. But can not figure out with SSR Https why its not working
Bellow are the screen shots It render on client side when i inspect in google chrome, But i do the view source code of it Can not see any meta tag rendering there.
Inspect in chrome
view source code in chrome
As you can see the Difference here the last to meta tag render on client side on inspect but are not there when i view source code when i use SSR Https, But using SSR Http every thing work fine.
Using https://angular.io/api/platform-browser/Meta
My code:
please, provide the network recording in your network recording (example below), I believe some request are pending at status column. other question, do you use firebase or anything else like socket.io ? I have the same problem when fetching data with firebase.
@ranjitnadar I am also facing same issues. Did you find any solution?
Unable to find solution: We tried installing ssl in server side rendering unable to resolve this issue. For now we are using http api url for meta information rendering.
I have the same issue, but it only doesn't work on home page. I'm using https on whole site + on api. When I'm trying to enter home page, AuthGuard from Angular redirect me from https://example.org to https://example.org/en and then I can see Elements in Chrome Dev Tools, but when I'm trying to inspect view source by right mouse click, it's empty (like without Universal). When I'm turning off HTTPS redirect which I did like that
app.use(forceSsl);
app.use('/',function(req, res, next){
console.log(req.headers);
next();
});
and enter, home page on http, home page view source is working good. Any solution ?
Guys, Any update on this topic. Because I'm also facing this problem.
Any update on this?
I havn't been able to reproduce this issue myself. Could someone provide a minimal reproduction for this issue?
i'm same bug
SSR Http every thing work fine
but https not work....
how https seo??
@Baedonghee Sorry but there isn't much we can do without a minimal reproduction of the issue. Are you able to put one together for us?
@Toxicable I think that problem is related to mine described below https://github.com/angular/angular/issues/23427 . It's something wrong with SSR and TransferState.
Here https://github.com/patrykp57/angular-sample You can check how it works.
Edit: On HTTPS (or it's external server problem, dunno) on page first load we can see flickering content I think it's related with site source code because after that, home page code is empty. like without Universal Robots are parsing it good, everything is working fine, but I think it's mostly related to that flicker at the beginning which I described in topic above
app.get('/', (req, res) => {
res.render('index', {
req,
res,
providers: [
{
provide: 'serverUrl',
useValue: ${req.protocol}://${req.get('host')}
}
]
});
});
app.engine('html', ngExpressEngine({
bootstrap: AppServerModuleNgFactory,
providers: [
provideModuleMap(LAZY_MODULE_MAP)
]
}));
app.set('view engine', 'html');
app.set('views', join(DIST_FOLDER));
app.use('/api/user', userRouter);
app.get('*', (req, res) => {
res.render('index', {
req,
res,
providers: [
{
provide: 'serverUrl',
useValue: ${req.protocol}://${req.get('host')}
}
]
});
});
server.ts
this.store.dispatch(new CoreActions.GetUserList(this.queryParams.toString())); this.userListState = this.store.select('userlist');
app.component.ts
http seo ok.... but https seo not working....
inside api server https not seo...
facing the same issue using docker. The app throwing
message: 'Http failure response for (unknown url): 0 Unknown Error',
This is working perfectly in my local environment using self signed certificate. When the api changed to https am getting above error.
Hosted on digital ocean
Structure of docker
Laravel (Api https://api.fabivo.com) Angular (https://fabivo.com) nginx (Nginx Configuration)
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/
environment:
- "DB_HOST=database" #mysql service name - database
- "DB_DATABASE=homestead"
- "DB_USERNAME=homestead"
- "DB_PASSWORD=homestead"
- "REDIS_HOST=cache"
- "REDIS_PORT=6379"
- "APP_URL=http://app.lo"
angular:
build: ./angular
expose:
- 3000
volumes:
- ./angular:/var/www/angular
depends_on:
- laravel
web:
build: ./nginx
volumes:
- ./:/var/www/
ports:
- 80:80
- 443:443
links:
- laravel:laravel
- angular:angular
depends_on:
- laravel
- angular
environment:
- VIRTUAL_HOST=app.lo, portal.app.lo , api.app.lo, shop.app.lo
networks:
default:
aliases:
- api.app.lo
database:
build: ./laravel/docker/mariadb
environment:
- "MYSQL_ROOT_PASSWORD=secret"
- "MYSQL_DATABASE=homestead"
- "MYSQL_USER=homestead"
- "MYSQL_PASSWORD=homestead"
ports:
- 3306:3306
mongodb:
image: mongo:latest
container_name: mongo
restart: always
volumes:
- mongo:/data/db
ports:
- 27017:27017
command: --storageEngine wiredTiger
cache:
image: redis:4.0-alpine
command: redis-server --appendonly yes
ports:
- 6379:6379
nodejs:
build: ./laravel/docker/nodejs
volumes:
- ./:/var/www/laravel
volumes:
mysqldata:
mongo:
networks:
default:
external:
name: nginx-proxy
any suggestion? Update: Here is the full details of docker setup Docker Compose Setup
@Toxicable : here is minimal reproduction repo https://github.com/ssatz/Angular-SSR-HTTPS-Error Deployed to heroku HEROKU
Note : This is working perfectly in my local with Self Signed certificate.
Hello, Issue resolved for me!
After 1 week of trail and error , finally am able to solve the issue.
Incase if any one having the issue, change secp384r1 to prime256v1
ssl_ecdh_curve prime256v1;
And i suggest universal team to provide a error log for ssr.
@ssatz where did you set ssl_ecdh_curve prime256v1;
? I'd like to try your solution. Much appreciated!
@Toxicable
In terms of a reproducible case, this is my scenario:
I'm on Angular 6 and everything works well locally, including HTTPS requests. On server, only works if I remove the HTTPS requests. Environments match up, except my openssl version are different as below:
Local is 0.9.8e
and Server is OpenSSL 1.0.2k-fips
To reproduce, add something like this to ngOnInit()
of your app.component.ts
in the start kit.
ngOnInit() {
this.httpClient
.get(VALID_HTTPS_URL);
.subscribe( res => {
// do something
});
}
That call never completes, so render never returns.
@rkajbaf : i am using nginx as reverse proxy, you need the define it in nginx config
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 prime256v1;
ssl_session_tickets off;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8;`
@Toxicable I'm suffering from the same issue, and only noticed after launching a new site that it was broken. I've also checked previously working apps to find they are broken too. Not sure at what point this bug was introduced but it's causing major issues.
@Toxicable I have found that http requests in a resolver do get ssr it's just the requests made in components that don't.
@Toxicable Look like it's a nodejs issue. https://github.com/nodejs/node/issues/16196 I found that using node 8.5.0 resolves the issue I was using 8.11.3
@Gorniv what is solution for this. I have same issue with https.
@piyushpatil027 you need to reproduce exception on a public repository.
Same issue..
@bastienlemaitre you need to reproduce exception on a public repository.
Hi, really late to this issue, but I was struggling for this issue too myself for 2 days and now finally get it working on my side! Below is how I solve this issue:
Since Angular Universal has some trouble requesting to https backend, I make an additional server block in my nginx setting files, so that my backend can also listen from localhost at http. And all request coming in from clients will be redirect to https. Please see my nginx settings below
`upstream recipe_express { server 127.0.0.1:4000; }
server { listen 80; listen [::]:80; server_name example.com www.example.com; return 301 https://$server_name$request_uri; } server { listen 80; server_name localhost;
root /var/www/html/recipe-backend/public;
location /api {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~\.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
} server {
#
listen 443 ssl default_server;
listen [::]:443 ssl default_server;
server_name example www.example.com localhost;
ssl_certificate /etc/ssl/example.crt;
ssl_certificate_key /etc/ssl/example.key;
root /var/www/html/laravel_backend/public;
# Add index.php to the list if you are using PHP
index index.html index.htm index.php;
location /api {
try_files $uri $uri/ /index.php$is_args$args;
}
location / {
alias /var/www/html/app/dist/browser/;
try_files $uri $uri @backend;
}
location @backend {
proxy_pass http://recipe_express; # <--- 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;
}
# pass PHP scripts to FastCGI server
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
}
} ` In my nginx setting basically I redirect the incoming request ONLY if it matches my domain name (from client browser) and send it to my backend through http if it's from localhost.
Also at your Angular Application, you need to add conditional check to see if your APP is running in browser or is it running server side rendering by Angular Universal. You can check by these two functions provided by Angular isPlatformBrowser and isPlatformServer.
Hope it helps someone else who's still trying to figure this out.
It worked for me after I added this line to my server.ts file "process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';"
Hey all, the https urls that you're requesting; is it on an internal corprate network or can they be each publicallly? Or do they have self signed/not globally trusted certs?
I'm using LetsEncrypt with Nginx -- no internal network and I've done everything I can to make it reachable. I can only think I can't use the HttpClient during app initialization...
EDIT: 1/12/2019 -
This partially ended up being that my "server" was being built without environment transformations -- so the browser build was trying to hit localhost:8089
while the server was still using localhost:8088
.
This is because I did not have environment transformation configuration in my CLI configuration file angular.json
.
This fixed me:
"server": {
"builder": "@angular-devkit/build-angular:server",
"options": {
"outputPath": "dist/server",
"main": "src/main.server.ts",
"tsConfig": "src/tsconfig.server.json"
+ },
+ "configurations": {
+ "production": {
+ "fileReplacements": [
+ {
+ "replace": "src/environments/environment.ts",
+ "with": "src/environments/environment.prod.ts"
+ }
+ ]
+ }
}
}
app.module
providers: [
ConfigService,
{ provide: APP_INITIALIZER, useFactory: app_init, deps: [ConfigService], multi: true}
]
export function app_init(configService: ConfigService) {
return () => configService.initializeApp();
}
config.service resolve for all cases since it always fails right now
public initializeApp(): Promise<any> {
if (this.initializePromise) { return this.initializePromise; }
this.initializePromise = new Promise((resolve, reject) => {
this.testApiWithoutCreds().then((data) => {
console.log('testApiWithoutCreds() success);
resolve();
})
.catch(exception => {
console.error('testApiWithoutCreds() error');
resolve();
});
this.testApiWithCreds().then((data) => {
console.log('testApiWithCreds() success');
resolve();
})
.catch(exception => {
console.error('testApiWithCreds() error}');
resolve();
});
});
return this.initializePromise;
}
private testApiWithoutCreds(): Promise<string> {
const promise = new Promise<string>((resolve, reject) => {
const request = this.http.get(`${environment.serviceUrl}test`, { withCredentials: false })
.subscribe(
(res: any) => {
resolve(res);
},
(exception) => {
console.error(`testApiWithoutCreds() Error doing simple things.`);
console.error(`Error detail: ${inspect(exception)}`);
resolve('');
});
});
return promise;
}
private testApiWithCreds(): Promise<string> {
const promise = new Promise<string>((resolve, reject) => {
const request = this.http.get(`${environment.serviceUrl}test`, { withCredentials: true })
.subscribe(
(res: any) => {
resolve(res);
},
(exception) => {
console.error(`testApiWithCreds() Error doing simple things.`);
console.error(`Error detail: ${inspect(exception)}`);
resolve('');
});
});
return promise;
}
It worked for me after I added this line to my server.ts file "process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';"
This has worked for me for local development !knock on wood!
Same problem but in firebase
ERROR HttpErrorResponse { headers: HttpHeaders { normalizedNames: Map {}, lazyUpdate: null, headers: Map {} }, status: 0, statusText: 'Unknown Error', url: 'https://firebaseapp.com/assets/data/product-1.json', ok: false, name: 'HttpErrorResponse', message: 'Http failure response for https://firebaseapp.com/assets/data/product-1.json: 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: 'text', 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: 'text', 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 } }
Hey all,
This was not working for me too, and after a week long struggle I have found the problem. The actual problem was with the environment.ts file. For some reason, when Angular runs on the server it refers to the environment.ts file, and on the client it refers to environment.prod.ts.
I had http://localhost:3000 reference in environment.ts file. It worked fine for me after updating this. Fingers crossed, I hope the same was the issue at your end. All the best!
Thanks, Roshan
It worked fine for me after updating this.
what did you update?
@roshanj80
It worked for me after I added this line to my server.ts file "process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';"
This resolve my problem! Thanks @tedishero
Hi all. I found the problem for me.
On my server I setup port forwarding by iptables
iptables --table nat --append PREROUTING --protocol tcp --dport 443 --jump REDIRECT --to-ports 3000
That is, my web server is running on port 3000. I did not take this into account when copying the UniversalInterceptor code from the official documentation
Now I fixed it and SSR works correctly. My universal-interceptor.ts
import { Request } from 'express';
import { REQUEST } from '@nguniversal/express-engine/tokens';
import { Inject, Injectable, Optional } from '@angular/core';
import { HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
@Injectable()
export class UniversalInterceptor implements HttpInterceptor {
constructor(
@Optional() @Inject(REQUEST) protected request: Request,
@Optional() @Inject('REQUEST') protected origin_request: any
) {}
intercept(req: HttpRequest<any>, next: HttpHandler) {
let serverReq: HttpRequest<any> = req;
if (this.request) {
let host = this.request.get('host');
/**
* Fix production SSR error
*/
if (!host.includes(':')) {
host += ':3000';
}
let newUrl = `${this.request.protocol}://${host}`;
if (!req.url.startsWith('/')) {
newUrl += '/';
}
serverReq = req.clone({
url: newUrl + req.url,
setHeaders: {
cookie: this.origin_request ? this.origin_request.headers.cookie : ''
}
});
}
return next.handle(serverReq);
}
}
It worked for me after I added this line to my server.ts file "process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';"
This worked for me.. My Application Runs in Angualr V9
You will get below warning form node js console: (node:21308) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
I also faced this problem and struggled with it for a couple of hours. Applying the process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
fix worked for me, but the downside is that you compromise your app's security by exposing it to a man-in-the-middle attack.
Upon investigating further, I realized that the problem was not with Angular. I ran https.get('<my-api-url>')
in a Node shell and I got: Uncaught Error: unable to verify the first certificate
. Turns out, I had configured my API server with only the leaf certificate, not the full-chain certificate (leaf + CA bundle). Node apparently needs the full-chain certificate for verification, unlike browsers.
Upon installing the full-chain certificate on my server, the problem went away without any changes to the app codebase.
WOW This was deff a show stopper. This needs to be added to Angular Docs
@ludoviccyril
So I have an Nginx box with SSL in front of my NodeJS cluster. I thought it would be ok to just proxy traffic to servers with out SSL but what a big mistake.
This worked but is not a good fix.
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
Please reff @ludoviccyril.
Fixed. For us this was caused by Node v 8.17. Upgraded to 12-alpine and it solved the problem.
This doesn't appear to be a problem in Universal, but rather misconfigurations of the servers.
If you do pin point an issue with Universal, please open a new issue, provide a simple repository reproducing the problem, and describe the difference between the expected and current behavior.
I had similar problem and though that it is in HTTPS configuration, but it was in PWA settings, which is working just in HTTPS. So if someone will have similar problem, solution is here https://github.com/angular/angular/issues/30861
This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.
Note: for support questions, please use one of these channels: https://github.com/angular/universal/blob/master/CONTRIBUTING.md#question. This repository's issues are reserved for feature requests and bug reports. Also, Preboot has moved to https://github.com/angular/preboot - please make preboot-related issues there.
I'm submitting a ...
[ ] bug report
[ ] feature request
[ ] support request => Please do not submit support request here, see note at the top of this template.
What modules are related to this Issue?
[ ] aspnetcore-engine
[ ] express-engine
[ ] hapi-engine
Do you want to request a feature or report a bug?
What is the current behavior?
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem by creating a github repo.
What is the expected behavior?
What is the motivation / use case for changing the behavior?
Please tell us about your environment:
Angular version: 4.1
Browser: [all ]
Language: [TypeScript 2.3.1]
OS: [all ]
Platform: [NodeJs | PHP]
Other information (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow, gitter, etc)
SSR fail when we using https api url for seo meta information. Using http working perfect.
Any solution please help me regards this.