0

I have an Angular app in which I have

RouterModule.forRoot([
  ...ContentRoutes,
  // this path acts like an "otherwise", so it must be the last one
  {
    path: '**',
    redirectTo: 'home',
  },
], {
  paramsInheritanceStrategy: 'always',
  onSameUrlNavigation: 'reload',
  scrollPositionRestoration: 'enabled'
})

Therefore, if I navigate with my browser to an image that doesn't exist http://localhost:4200/assets/images/some_image_that_doesnt_exist.jpg

I get redirected to the home page. However, if I do the same request with Postman, I get a 404 response.

On the other hand, if I load the application to an Azure server, when I navigate to http://<my_webpage>.azurewebsites.net/assets/images/some_image_that_doesnt_exist.jpg I also get redirected to the main page, but when I do that request with postman, I get a 200 response and the home content.

Do you have any idea of a possible reason that could explain this difference?

Remark: the reason behind this question is trying to show an alternate image instead of showing a 404 error when the image doesn't exist. I created an endpoint in my C# Backend that checks if the image exists or not, but after the implementation, it works locally but it doesn't work on the server because I am not getting 404 errors...

xavier
  • 1,860
  • 4
  • 18
  • 46
  • Can you provide more details of how your API is hosted and how your Angular app is hosted? What domains are they on? What Azure services are you using to host each of them? – Omkar Khair Mar 07 '23 at 07:53
  • Thank you for your answer! What do you mean with "how is hosted"? I guess it's not important (?) how the API (Backend) is hosted, because the problem can be reproduced with postman. The Frontend Angular application is hosted with an "App Service Plan", in Windows, with runtime stack "Node 12.13.0". What other info would be necessary? – xavier Mar 07 '23 at 18:19
  • I asked how is it hosted because the reverse proxy configurations can affect how your application behaves on 404. It seems on Azure you facing this issue where the App Service is returning your Angular bootstrapping index.html when faced with a 404. – Omkar Khair Mar 09 '23 at 06:30
  • You mention your app is running on Node.js but also mention C#, these details are important to understand how you app might be configured. – Omkar Khair Mar 09 '23 at 06:31
  • I have 2 servers hosted in Azure. One is Backend, C#. The other is Frontend, with Angular. The files are located in the Frontend server. When a file does not exist, I get the same response both if I make the request from my personal computer using Postman and from the backend with `using var client = new HttpClient();` and `using var request = new HttpRequestMessage(HttpMethod.Get, uri);` I have Node - 12.13.0 as a "Runtime Stack" in the Angular server, whereas I have Dotnet - v7.0 in the "Runtime Stack" of the Backend server. – xavier Mar 09 '23 at 21:17
  • Besides that, I don't know exactly how to answer the question "how it is hosted" and I don't know what a reverse proxy is. I'll look for some information but if you can tell me where to find the information you miss, let me know and I'll provide it. Thank you very much. – xavier Mar 09 '23 at 21:19
  • How it is hosted and the configuration of the server are relevant, because the routing is done on the client side, using angular router. When you are pointing to an URL in angular you are not pointing to a particular resource in the server so the server must be instructed to redirect to index.html (which seems like azure is doing correctly) if you do not set up the server this way the routes will be 404s. – Jordi Riera Mar 10 '23 at 19:46
  • A static server routinely returns index.html when it receives a request for http://www.example.com/. But it rejects http://www.example.com/heroes/42 and returns a 404 - Not Found error unless it is configured to return index.html instead where the application would load and handle the urls – Jordi Riera Mar 10 '23 at 19:47
  • I don't know how to check the configuration of the server. I'll look up if I find it, thanks. How can I check if a file exists then? – xavier Mar 11 '23 at 13:17

1 Answers1

0

Why it's returning 200

Angular app is just a bunch of static files as any other website. When you develop it locally you are running a simple server that serves your static files and also has a WebSocket connection in order to reload the page when the rebuild happens.

In production it's usually served on a static host. In AWS it's S3 bucket. In it's called Azure Blob Storage.

Both AWS and Azure allow you to turn your storage into a static web server (what Angular actually needs). After that, Azure manages incoming requests to the storage and returns a corresponding file.

Since the app and the static files are accessed by the same URL you usually configure a 404 page case to return index.html with status code 200. Otherwise, routing won't work as it's done by the JS code included in the index.html.

How to fix

If you are using an SSR (Server Side Rendering) then it's usually done by a NodeJS server and 99% chance you are using Express. There, you have app routing handlers which do the render. Also, you have a middleware that will resolve static files.

With a storage working as a static web hosting usually you can only statically set a custom page redirect page for 404. To return a custom image you would need to spin up your own reverse-proxy like NGINX and manually distinguish which requests are navigation related and which are assets related. Then you can return a fallback image.

Use Angular to provide a fallback image

You could use a directive that would be applied to an image. The element has an onerror event which is called if the image fails to load. Then, you can replace the link to use a fallback image.

@Directive({
  selector: '[fallbackImg]',
  standalone: true,
})
class ImgDirective {
  @HostBinding('src')
  src: string;

  @HostListener('error', ['$event'])
  onError(e) {
    console.log(e)
    this.src = 'fallbackurl'
  }
}
Sergey
  • 7,184
  • 13
  • 42
  • 85
  • Thank you for the answer! Now i am not in front of my computer, but i think the onError does not prevent getting an error in the console, which is what i am trying to avoid… – xavier Mar 11 '23 at 16:48
  • You can remove the log :) The error in the console is just a message and is not a problem as long as it doesn't affect the users. – Sergey Mar 11 '23 at 16:51
  • I don’t want to pollute the console and that’s the reason I’m trying to check from the backend if the image exists… – xavier Mar 11 '23 at 18:19
  • But what's the reason for concern? It's not like performance would degrade or whatever – Sergey Mar 12 '23 at 06:11