Spring Boot 2.1.0 only serve index.html if resource not resolved (SPA, react-router)
Asked Answered
S

3

7

I am serving an SPA made with create-react-app and react-router using Spring Boot 2.1.0 with this configuration

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/**/{path:[^\\.]+}")
                .setViewName("forward:/");
    }
}

Basically what it does is always serve index.html unless there's a period in the path. I would like to align this with create-react-app's provided .htaccess. How can I make Spring Boot match this functionality?

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
Stefan answered 20/11, 2018 at 12:34 Comment(0)
S
3

To reroute "404 : file not found" to "forward:/", which I think is what the .htaccess does, change your WebMvcConfiguration to...

@Configuration
public class WebMvcConfiguration implements ErrorViewResolver
{

    @Override
    public ModelAndView resolveErrorView(HttpServletRequest request, HttpStatus status, Map<String, Object> model) {
        if (status == HttpStatus.NOT_FOUND) {
            return new ModelAndView("forward:/");
        }
        return null;
    }

}
Sinewy answered 29/11, 2018 at 16:38 Comment(0)
S
2

You can catch-all unhandled view controller like below when no other route has been found.

@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
       registry.setOrder(Ordered.LOWEST_PRECEDENCE);
        registry.addViewController("/**").setViewName("forward:/index.html");
    }
}
Synergist answered 23/11, 2018 at 15:58 Comment(3)
Thanks for the response. When I go to a route configured with react-router now and refresh the page, I get a whitelabel error page which I didn't get with the previous configStefan
@RobertoGraham Can you show your directory structure?Synergist
same problem - the accepted answer does not have this problem (Directory structure: resources/public/index.html)Departed
S
0

Following Kotlin code might help:

@Configuration
class WebMvcConfig(val resourceProperties: ResourceProperties) : WebMvcConfigurer {

    override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
        registry.addResourceHandler("/**")
            .addResourceLocations(*resourceProperties.staticLocations)
            .resourceChain(resourceProperties.chain.isCache)
            .addResolver(FallbackPathResourceResolver())
    }

    private class FallbackPathResourceResolver : PathResourceResolver() {
        override fun resolveResource(
            request: HttpServletRequest?,
            requestPath: String,
            locations: MutableList<out Resource>,
            chain: ResourceResolverChain
        ): Resource? {
            return super.resolveResource(request, requestPath, locations, chain) ?: super.resolveResource(
                request,
                "/index.html",
                locations,
                chain
            )
        }
    }
}

Reference: https://jira.spring.io/browse/SPR-16788

Stromberg answered 27/11, 2018 at 8:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.