Angular Universal generate 404 (and other HTTP codes) header
Asked Answered
M

3

8

I'm creating a website using Angular Universal. It will have server-side rendering in order to make it indexable by search engines.

I already coded my 404 fallback route, it displays its component correctly, but it displays it with a HTTP 200 header code.

How can I force a specific header code ? I googled some queries, but everything I found seemed to be about reading an HTTP call's status code, and nothing on how to write it to the browser.

Mcclimans answered 14/9, 2017 at 12:52 Comment(3)
... and it's status code.Elum
Sorry, i should have added emphasis on the "reading", which is something I don't care for now, since I want to "write" a response code to the browser.Mcclimans
You can't write a response to the browser, the browser works on HTTP.Elum
M
3

Ok, I've finally succeeded.

I started over, and used Angular Universal Starter (CLI), with Patrick Michalina's scripts described here : https://github.com/DSpace/dspace-angular/issues/91#issuecomment-318547118

Mcclimans answered 22/9, 2017 at 9:43 Comment(2)
Please help me out for Angular 9 Same issue - #70926563Chop
I'm sorry, I didn't tuch any project related to angular since thenMcclimans
M
6

I followed the docs: https://github.com/angular/universal/tree/master/modules/express-engine

Note, you bootstrap the app twice in server.ts, we need to provide the response every request. Also we optionally inject the response into our app components, as the response will be NULL if the platform is the browser.

server.ts

some imports:

import {Response} from 'express';
import {RESPONSE} from '@nguniversal/express-engine/tokens';

engine:

// * NOTE :: leave this as require() since this file is built Dynamically from webpack
const {AppServerModuleNgFactory, LAZY_MODULE_MAP} = require('./dist/server/main');

// Our Universal express-engine (found @ https://github.com/angular/universal/tree/master/modules/express-engine)
app.engine('html', ngExpressEngine({
  bootstrap: AppServerModuleNgFactory,
  providers: [
    provideModuleMap(LAZY_MODULE_MAP),
  ]
}));

request handler:

app.get('*', async (req, res) => {
  res.render('index.html', {req, res, providers: [
      {
        provide: RESPONSE,
        useValue: res,
      },
    ]}, (error, html) => {
    if (error) {
      console.log(`Error generating html for req ${req.url}`, error);
      return (req as any).next(error);
    }
    res.send(html);
    if (!error) {
      if (res.statusCode === 200) {
        //toCache(req.url, html);
      }
    }
  });
});

routing:

const routes: Routes = [
  {path: '404', component: NotFoundComponent},
...
  {path: '**', redirectTo: '/404'}

];

component:

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

@Component({
  selector: 'app-not-found',
  templateUrl: './not-found.component.html',
  styleUrls: ['./not-found.component.scss']
})
export class NotFoundComponent implements OnInit {
  private response: Response;
  constructor(@Optional() @Inject(RESPONSE) response: any) {
    this.response = response;
  }

  ngOnInit() {
    console.log('here with response', this.response);
    if (this.response) {
      // response will only be if we have express
      // this.response.statusCode = 404;
      this.response.status(404);
    }
  }

}
Momently answered 7/5, 2019 at 3:51 Comment(1)
please help me out for angular 9 with this same issue - #70926563Chop
M
3

Ok, I've finally succeeded.

I started over, and used Angular Universal Starter (CLI), with Patrick Michalina's scripts described here : https://github.com/DSpace/dspace-angular/issues/91#issuecomment-318547118

Mcclimans answered 22/9, 2017 at 9:43 Comment(2)
Please help me out for Angular 9 Same issue - #70926563Chop
I'm sorry, I didn't tuch any project related to angular since thenMcclimans
D
1

After a long research, here what i have found

https://skynix.co/resources/how-to-set-404-status-code-in-angular

page-not-found.component.ts

import { Component, Inject, Optional } from '@angular/core';
import { Observable } from 'rxjs';
import { ContentfulService } from '../../contentful/services/contentful.service';
import { CoreService } from '../../core/services/core.service';
import { Utils } from '../../core/utils/utils';
import { PageNotFound } from './interfaces/page-not-found';
import { Router } from '@angular/router';
import { DOCUMENT } from '@angular/common';
import { Response } from 'express';
import { RESPONSE } from '@nguniversal/express-engine/tokens';

@Component({
  selector: 'app-page-not-found',
  templateUrl: './page-not-found.component.html',
  styleUrls: ['./page-not-found.component.scss'],
})
export class PageNotFoundComponent {
  richTextRenderer = Utils.returnHtmlFromRichText;
  data$: Observable<PageNotFound> = this.contentfulService.get404Page();
  locale$ = this.coreService.currentLocale$;
  private response: Response;

  constructor(
    private contentfulService: ContentfulService,
    private coreService: CoreService,
    private router: Router,
    @Inject(DOCUMENT) private dom: Document,
    @Optional() @Inject(RESPONSE) response: any
  ) {
    this.response = response;
  }

  ngOnInit() {
    if (this.response) {
      this.response.status(404);
    }
  }
}
Democrat answered 19/7, 2023 at 11:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.