Search code examples
angularspring-booturl-rewritingcaddycaddyfile

MIME types error when using URL rewriting on Springboot server and Angular app


I am working on a SpringBoot application with 2 Angular app frontend that are located as such :
Springboot app : src -> main -> java
Angular app 1 (fo) : src -> main -> resources -> public -> fo
Angular app 2 (bo) : src -> main -> resources -> public -> bo

NOTE : In the root folder of the angular apps some files like index.html and runtime-es[...].js can be found (among others)

So I created a Controller class for my Springboot app like this :

@Controller
public class MainController {

    @GetMapping("/fo")
  public String index() {
      return "/fo/index.html";
  }

  @GetMapping("/bo")
  public String admin() {
      return "/bo/index.html";
  }
}

As well as a Configuration class :

@Configuration
@ComponentScan(basePackageClasses = {MainApplicationImpl.class})
@EnableWebSecurity
public class PresentationConfiguration extends WebSecurityConfigurerAdapter implements WebMvcConfigurer {

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests().antMatchers("/**").permitAll();
  }

  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/fo/**")
      .addResourceLocations("classpath:/public/fo/")
      .resourceChain(true)
      .addResolver(new PathResourceResolver() {
        @Override
        protected Resource getResource(String resourcePath, Resource location) throws IOException {
          Resource requestedResource = location.createRelative(resourcePath);

          return requestedResource.exists() && requestedResource.isReadable() ? requestedResource
            : new ClassPathResource("/public/fo/index.html");
        }
      });

    registry.addResourceHandler("/bo/**")
      .addResourceLocations("classpath:/public/bo/")
      .resourceChain(true)
      .addResolver(new PathResourceResolver() {
        @Override
        protected Resource getResource(String resourcePath, Resource location) throws IOException {
          Resource requestedResource = location.createRelative(resourcePath);

          return requestedResource.exists() && requestedResource.isReadable() ? requestedResource
            : new ClassPathResource("/public/bo/index.html");
        }
      });
  }

The idea is that fo should be available on the internet, for example on http://www.fo.com/, and bo only available on the internal network of my client, let's say http://client.bo.internal/.

To simulate that, I setted up some sort of "reverse_proxy" that rewrites the URL using docker and Caddy, here is the example for url rewriting of bo:

Caddyfile

localhost:80 {
    route /* {
        rewrite /* /bo/*
        reverse_proxy http://host.docker.internal:8081
    }
}

docker-compose.yml

version: '3'
services:
  proxy:
    image: caddy
    #command
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
    ports:
      - '8082:80'

That way, when I type http://localhost:8082 on a web browser, it calls my Springboot app as such : http://localhost:8081/bo.
This kinda works since I am getting the index.html file showing on the page but every links to js files and css files are getting an error showing

Failed to load module script: The server responded with a non-JavaScript MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.

Here are some screenshot of what I can see in the developments tools of the browser :

HTML content of http://localhost:8082 : HTML content

Errors in console : Errors in console

Network tab : Network tab

Here's some funny business, every files seems to have the content of index.html: Content of some .js file

Since the problem seems to come from MIME types, how can I specify that the .js files called from a .html files are not text/html but application/javascript (if it is really my problem) ?

From what I've found on the internet about this error, it can be fixed by rewriting the <base href="/" /> tag. But I do not want to do this because it will mean that the URL will have to be http://localhost/fo/.

Hope you can help me, thanks for reading !


Solution

  • Found a way to fix this, the error showed because of the configuration of my CaddyFile. Using the url replace instead of rewrite.

    New CaddyFile :

    localhost:80 {
        route /* {
            uri replace / /bo/ 1
            reverse_proxy http://host.docker.internal:8081
        }
    }
    

    That will replace the first occurence of / to /bo/, so I call http://localhost:8082/ and get http://localhost:8081/bo/. You would expect the rewriting syntax to do exactly this but apparently not.