Angular 6 SSR : a true 404 / not found page with an 404 HTTP status code

余生颓废 提交于 2019-12-24 11:08:08

问题


I struggle to settle a 404 page that returns to navigators/crawlers a specific HTTP status code : 404. Following SSR guide in https://angular.io/guide/universal, my application is correctly served with SSR.

I set a 'PageNotfound' route in my app-routing.module.ts :

{path: '*', component: NotFoundComponent}

But obviously it still returns 200 as http return statuses. How I can change http return code for this specific route ?


回答1:


Although it is quite well-documented here https://github.com/angular/universal/tree/master/modules/express-engine the proposed token does not work.

It is simply undefined in SSR (in the client it is easy to mock it).

However there is a (very) dirty solution.

Just put some marker on your 404 page (change whatevervaluehere to something unique and meaningless):

<!-- indicator for SSR to return 404 status code -->
<!-- MUST BE LEFT HERE -->
<input type="hidden" value="whatevervaluehere">

and in the server.ts

app.get('*', (req, res) => {
  res.render('index', {
    req,
    res,
  }, (err: Error, html: string) => {
    res.status(html && html.includes('whatevervaluehere') ? 404 : html ? 200 : 500).send(html || err.message);
  });
});

Again, very, very dirty. However, works.




回答2:


add this to the component NotFoundComponent

import {Component, Inject, OnInit, Optional, PLATFORM_ID} from '@angular/core';
import {isPlatformBrowser} from '@angular/common';
import {RESPONSE} from '@nguniversal/express-engine/tokens';
import {Response} from 'express';

@Component({
  selector: 'app-not-found',
  templateUrl: './not-found.component.html',
  styleUrls: ['./not-found.component.scss']
})
export class NotFoundComponent implements OnInit {

  constructor(@Inject(PLATFORM_ID) private platformId: Object,
              @Optional() @Inject(RESPONSE) private response: Response) {
  }


  ngOnInit() {
    if (!isPlatformBrowser(this.platformId)) {
      this.response.status(404);
    }
  }
}

modify server.js file to this

import {REQUEST, RESPONSE} from '@nguniversal/express-engine/tokens';
import {ValueProvider} from '@angular/core';


app.engine('html', (_, options, callback) => {
  renderModuleFactory(AppServerModuleNgFactory, {
    // Our index.html
    document: template,
    url: options.req.url,
    extraProviders: [
      // make req and response accessible when angular app runs on server
      <ValueProvider>{
        provide: REQUEST,
        useValue: options.req
      },
      <ValueProvider>{
        provide: RESPONSE,
        useValue: options.req.res,
      },
    ]
  }).then(html => {
    callback(null, html);
  });
});



回答3:


For me the following snippet worked (Angular 8.2.11). No need to change the default server.ts file.

import { Component, OnInit, Inject, PLATFORM_ID, Optional } from '@angular/core';
import { REQUEST } from '@nguniversal/express-engine/tokens';
import { isPlatformServer } from '@angular/common';
import { Request } from 'express';

@Component({
  selector: 'app-error-not-found',
  templateUrl: './error-not-found.component.html',
  styleUrls: ['./error-not-found.component.scss']
})
export class ErrorNotFoundComponent implements OnInit {

  constructor(
    @Inject(PLATFORM_ID) private platformId: any,
    @Optional() @Inject(REQUEST) private request: Request
  ) { }

  ngOnInit() {
    if (isPlatformServer(this.platformId)) {
      if (this.request.res) {
        this.request.res.status(404);
      }
    }
  }

}

And offcourse we need our routes to be something like this:

export const routes: Routes = [
  ...
  { path: '404', component: ErrorNotFoundComponent },
  { path: '**', redirectTo: '/404' }
];


来源:https://stackoverflow.com/questions/52663743/angular-6-ssr-a-true-404-not-found-page-with-an-404-http-status-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!