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
:
Here's some funny business, every files seems to have the content of index.html
:
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 !
Found a way to fix this, the error showed because of the configuration of my CaddyFile. Using the
url replace
instead ofrewrite
.New CaddyFile :
That will replace the first occurence of
/
to/bo/
, so I callhttp://localhost:8082/
and gethttp://localhost:8081/bo/
. You would expect therewriting
syntax to do exactly this but apparently not.