Denis Evseev
Denis Evseev

Reputation: 1710

Retrieve 404 status when route is not found. Angular 6+ and Universal

I have released my project using Universal and specified in .htaccess that all requests should go to index.html (root page of the Angular application)

as it was asked here: https://angular.io/guide/universal

it allows sharing a link and to open a component specified in a URL

Also, created a component in case if an incorrect route is opened: Handling 404 with Angular2

export const routes:RouterConfig = [
  ...Routes,
  // Show the 404 page for any routes that don't exist.
  { path: '**', component: Four04Component }
];

The problem is that search engines treat the Four04Component as a simple page with 200 OK status rather an error page. Do you know how can retrieve a 404 error together with the Four04Component?

Upvotes: 5

Views: 2593

Answers (2)

blaimi
blaimi

Reputation: 819

With Angular 17 and the SSR-Server, you may need some more:

Source: angular-migrations/replace-nguniversal-engines

  • create a file express.tokens.ts in /src/
    import { InjectionToken } from '@angular/core';
    import { Request, Response } from 'express';
    
    export const REQUEST = new InjectionToken<Request>('REQUEST');
    export const RESPONSE = new InjectionToken<Response>('RESPONSE');
    
  • add import { REQUEST, RESPONSE } from './src/express.tokens'; to your server.ts
  • add { provide: REQUEST, useValue: req}, { provide: RESPONSE, useValue: res} to the list of your providers passed to angular in the render opts in server.ts
  • create the PageNotFoundComponent with its wildcard route like described in the angular docs
  • ajust the page-not-found.component.ts
    import {Component, inject, PLATFORM_ID} from '@angular/core';
    import {RESPONSE} from "../../express.tokens";
    import {Response} from "express";
    import {isPlatformServer} from "@angular/common";
    
    @Component({
      selector: 'app-page-not-found',
      standalone: true,
      imports: [],
      templateUrl: './page-not-found.component.html',
      styleUrl: './page-not-found.component.scss'
    })
    export class PageNotFoundComponent {
      response: Response|null = inject(RESPONSE, {optional: true})
      platformId: Object = inject(PLATFORM_ID)
    
      ngOnInit(){
        if(isPlatformServer(this.platformId) && this.response){
          this.response.status(404);
        }
      }
    }
    

More helpful links:

Upvotes: 0

Reza
Reza

Reputation: 410

You have to inject Response into your angular app , to achieve that first change these lines in your server.ts :

app.get('*', (req, res) => { //you can find these line easily
res.render('index', {
    req: req,
    res: res,
    providers: [
        {
            provide: REQUEST, useValue: (req)
        },
        {
            provide: RESPONSE, useValue: (res)
        }
    ]
    });
});

Then in your Four04 component inject response like this :

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

After that simply try something like this on ngoninit of Four04 component :

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

Hope these help someone.

Upvotes: 7

Related Questions