2

I have my angular app running inside docker that exposed on port 83, and I also have a spring-boot rest app inside another docker that exposed on port 8083.

In the host server I have one Nginx server that reroute every requests using below config:

server {
    listen 80;
    server_name mydomain.com;

    location / {
        proxy_pass http://127.0.0.1:83;
    }
}

server {
    listen 80;
    server_name rest.mydomain.com;

    location / {
        proxy_pass http://127.0.0.1:8083;
    }
}

With above config, every request that uses mydomain.com will goes to my Angular 6 app, and every request that uses rest.mydomain.com will goes to my spring-boot rest app.

In the index page of my angular, I have a search form which will trigger the Routing module to open a search result page.

My app-routing.module.ts is like below:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomePgComponent } from './home-pg/home-pg.component';
import { ResultsPgComponent } from './results-pg/results-pg.component';

const routes: Routes = [
  { path: "", component: HomePgComponent },
  { path: "search", component: ResultsPgComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(
    routes,
    { enableTracing: true }
  )],
  exports: [
    RouterModule
  ]
})
export class AppRoutingModule { }
export const RoutingComponents = [
  HomePgComponent, 
  ResultsPgComponent
];

And the trigger on my search form is like below:

onSearchBtnClk(el) {
    if (el.value.length > 0) {
      console.log(">>> SEARCH ARGS = " + el.value);
      this.router.navigate(['/search'], { queryParams: { q: el.value }});
      this.newArgsEmitter.emit(el.value);
    }
}

Everything works well, when I click the search button, my angular will open the search result page and shows the results.

My problem is, whenever I click REFRESH button on the browser, instead of a search page result, it shows 404 page. Why is this happen?

Any advice would be appreciated. Thanks

danday74
  • 52,471
  • 49
  • 232
  • 283
Bromo Programmer
  • 670
  • 2
  • 13
  • 37

2 Answers2

8

You need to add a try_files statement, but because you are using a proxy_pass this makes things a bit more complicated. This is untested but you can try this:

server {
    listen 80;
    server_name mydomain.com;
    try_files $uri $uri/ /index.html @proxy;    

    location @proxy {
      proxy_pass http://127.0.0.1:83;
    }
}

The “@” prefix defines a named location. Such a location is not used for a regular request processing, but instead used for request redirection. They cannot be nested, and cannot contain nested locations.

read more

Poul Kruijt
  • 69,713
  • 12
  • 145
  • 149
  • what is the @proxy for? any documentation? – Niton Aug 12 '22 at 18:15
  • 1
    @Niton it's just a name I used in the `location` declaration, so I can point to it from the `try_files`. I could have named it `@teddybear` and it would have worked. You can read about it [here](http://nginx.org/en/docs/http/ngx_http_core_module.html#location) – Poul Kruijt Aug 15 '22 at 10:22
2

It's because an Agular app is a single page app (SPA).

When you refresh the app your nginx config needs to always serve up index.html.

Currently, when you refresh say for example /some-path

nginx, by default, will look for a file called /some-path.html which obviously does not exist.

To always serve up index.html you need to tweak your nginx.conf something like this:

Nginx config for single page app with HTML5 App Cache

Here's an excerpt from the accepted answer at that link:

root /files/whatever/public;
index index.html;

location / {
    try_files $uri /index.html =404;
}

# Proxy requests to "/auth" and "/api" to the server.
location ~ ^/(auth|api) {
    proxy_pass http://application_upstream;
    proxy_redirect off;
}

Also, just Google configure Nginx to serve Single Page Application

danday74
  • 52,471
  • 49
  • 232
  • 283