Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle 404 server code response #19

Closed
mxgnr opened this issue Sep 18, 2018 · 8 comments
Closed

Handle 404 server code response #19

mxgnr opened this issue Sep 18, 2018 · 8 comments
Labels
enhancement New feature or request

Comments

@mxgnr
Copy link

mxgnr commented Sep 18, 2018

Hi there,

Thank you @enten for this very useful starter kit !

I'm currently trying to set my app to be able to send a 404 server code response when a visited route is not available. I've found a few tutorials for Angular Universal (here, this one or even here) but each time the server file script is quite different from this project, i've been trying to make it work for a couple hours without success.

Can you describe how implement this functionnality into this starter kit ?

Thanks

@enten enten added the enhancement New feature or request label Sep 21, 2018
@enten
Copy link
Owner

enten commented Sep 21, 2018

The simple way to achieve that:

Gotcha: the request injection should be optional because it will be underfined in browser bundle/side.

I will write an example soon to illustrate this usecase.

@mxgnr
Copy link
Author

mxgnr commented Sep 21, 2018

I would like an example indeed, since i can't make it work either with RESPONSE or REQUEST token, as you describe above.

I've seen output errors in my console about dependencies which seems to be only for server purpose (like express), maybe angular-cli related ? It seems to be similar to this issue.

@enten
Copy link
Owner

enten commented Sep 21, 2018

@maxgranier
I will write that example this weekend.

About the issue that you linked: do you think that you encountered that issue?
Have you a repository which reproduce this issue?

@mxgnr
Copy link
Author

mxgnr commented Sep 24, 2018

Hi,

This is what i tried so far :

import { Component, OnInit, Optional, PLATFORM_ID, APP_ID, Inject } 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.less']
})
export class NotFoundComponent implements OnInit {

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

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

And i got this output errors from the console :

[...]

WARNING in ./node_modules/express/lib/view.js
81:13-25 Critical dependency: the request of a dependency is an expression

ERROR in ./node_modules/cookie-signature/index.js
Module not found: Error: Can't resolve 'crypto' in '[...]/node_modules/cookie-signature'
ERROR in ./node_modules/etag/index.js
Module not found: Error: Can't resolve 'crypto' in '[...]/node_modules/etag'
ERROR in ./node_modules/destroy/index.js
Module not found: Error: Can't resolve 'fs' in '[...]/node_modules/destroy'
ERROR in ./node_modules/etag/index.js
Module not found: Error: Can't resolve 'fs' in '[...]/node_modules/etag'
ERROR in ./node_modules/express/lib/view.js
Module not found: Error: Can't resolve 'fs' in '[...]/node_modules/express/lib'
ERROR in ./node_modules/send/index.js
Module not found: Error: Can't resolve 'fs' in '[...]/node_modules/send'
ERROR in ./node_modules/send/node_modules/mime/mime.js
Module not found: Error: Can't resolve 'fs' in '[...]/node_modules/send/node_modules/mime'
ERROR in ./node_modules/express/lib/application.js
Module not found: Error: Can't resolve 'http' in '[...]/node_modules/express/lib'
ERROR in ./node_modules/express/lib/request.js
Module not found: Error: Can't resolve 'http' in '[...]/node_modules/express/lib'
ERROR in ./node_modules/express/lib/response.js
Module not found: Error: Can't resolve 'http' in '[...]/node_modules/express/lib'
ERROR in ./node_modules/express/lib/request.js
Module not found: Error: Can't resolve 'net' in '[...]/node_modules/express/lib'
ERROR in ./node_modules/content-disposition/index.js
Module not found: Error: Can't resolve 'path' in '[...]/node_modules/content-disposition'
ERROR in ./node_modules/express/lib/application.js
Module not found: Error: Can't resolve 'path' in '[...]/node_modules/express/lib'
ERROR in ./node_modules/express/lib/view.js
Module not found: Error: Can't resolve 'path' in '[...]/node_modules/express/lib'
ERROR in ./node_modules/express/lib/response.js
Module not found: Error: Can't resolve 'path' in '[...]/node_modules/express/lib'
ERROR in ./node_modules/mime-types/index.js
Module not found: Error: Can't resolve 'path' in '[...]/node_modules/mime-types'
ERROR in ./node_modules/send/index.js
Module not found: Error: Can't resolve 'path' in '[...]/node_modules/send'
ERROR in ./node_modules/send/node_modules/mime/mime.js
Module not found: Error: Can't resolve 'path' in '[...]/node_modules/send/node_modules/mime'
ERROR in ./node_modules/serve-static/index.js
Module not found: Error: Can't resolve 'path' in '[...]/node_modules/serve-static'
ERROR in ./node_modules/destroy/index.js
Module not found: Error: Can't resolve 'stream' in '[...]/node_modules/destroy'
ERROR in ./node_modules/iconv-lite/lib/streams.js
Module not found: Error: Can't resolve 'stream' in '[...]/node_modules/iconv-lite/lib'
ERROR in ./node_modules/iconv-lite/lib/extend-node.js
Module not found: Error: Can't resolve 'stream' in '[...]/node_modules/iconv-lite/lib'
ERROR in ./node_modules/send/index.js
Module not found: Error: Can't resolve 'stream' in '[...]/node_modules/send'
ERROR in ./node_modules/body-parser/lib/read.js
Module not found: Error: Can't resolve 'zlib' in '[...]/node_modules/body-parser/lib'
Child: server
  Date: 2018-09-24T09:17:44.760Z
  Hash: 4d6f0c0353c3c7e9a4c6
  Time: 228ms

ERROR in [udk] compilation cancelled due to errors in previous compilers: browser

It seems to happen when i try to inject Response from express.

@enten
Copy link
Owner

enten commented Sep 24, 2018

@maxgranier
Firstly: commit 365497b which implement a dummy not found component which set response status 404.

Below some information which can help to fix your issue.

In the commit, we use NotFoundComponent when browser hit special route **.
The component use RESPONSE to set status 404.

The most important part on the server side is to provide RenderOptions req and res when your render the template:

api.get('*', (req, res) => res.render('index', { req, res }));

The second important part is to design your angular project in an universal way.
You can notice that our issue is relative to server stuff which can't be resolved in the browser bundle.
udk avoid server compilation (because there is an error in the browser bundle): but if you run ng run yourproject:server you will see that your server build well.

The NotFoundComponent should work in browser and server. To fix the error: we need to remove express import and use a partial response interface.

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

interface PartialResponse {
  status(code: number): this;
}

@Component({
  selector: 'app-not-found',
  template: '<h1>Page Not Found</h1>',
})
export class NotFoundComponent implements OnInit {
  constructor(
    @Inject(PLATFORM_ID) private platformId: Object,
    @Inject(APP_ID) private appId: string,
    @Optional() @Inject(RESPONSE) private response: PartialResponse,
  ) { }

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

Of course, in real application, setting response status must be accomplish with a service.

@Injectable()
export class HttpContextService {
  constructor(
    @Optional() @Inject(REQUEST) readonly request: PartialRequest,
    @Optional() @Inject(RESPONSE) readonly response: PartialResponse,
  ) { }

  setStatusCode(code: number) {
    if (this.response) {
      this.response.status(code);
    }
  }
}

@mxgnr
Copy link
Author

mxgnr commented Sep 26, 2018

Really helpful, thanks a lot, also for the explanation !

@enten
Copy link
Owner

enten commented Sep 26, 2018

@maxgranier You're welcome. Can we close your issue?

@mxgnr
Copy link
Author

mxgnr commented Sep 26, 2018

Sure no problem

@enten enten closed this as completed Sep 26, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants