mirror of https://github.com/micromata/borgbackup-butler.git

Kai Reinhard
19.24.2021 7f78d2ed3b282c6bd6bba9dde4110cd4f3d558cf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package de.micromata.borgbutler.server
 
import mu.KotlinLogging
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.web.servlet.ViewResolver
import org.springframework.web.servlet.config.annotation.*
import org.springframework.web.servlet.view.InternalResourceViewResolver
import java.nio.file.Paths
 
 
private val log = KotlinLogging.logger {}
 
@Configuration
@EnableWebMvc
open class WebConfig : WebMvcConfigurer {
 
    override fun addResourceHandlers(registry: ResourceHandlerRegistry) {
        if (RunningMode.webBundled()) {
            registry.addResourceHandler("/**").addResourceLocations(*CLASSPATH_RESOURCE_LOCATIONS);
        } else {
            val localWebDir = Paths.get(".", "borgbutler-webapp", "build").toFile()
            if (localWebDir.isDirectory) {
                registry.addResourceHandler("/**").addResourceLocations(localWebDir.toURI().toString());
            } else {
                log.warn { "*** Can't locate React application. You should run npm/yarn build/start and/or check this path: ${localWebDir.absolutePath}" }
            }
        }
    }
 
    @Bean
    open fun getViewResolver(): ViewResolver? {
        val resolver = InternalResourceViewResolver()
        resolver.setSuffix(".html")
        return resolver
    }
 
    override fun configurePathMatch(configurer: PathMatchConfigurer) {
        configurer.isUseTrailingSlashMatch = true
    }
 
    override fun addViewControllers(registry: ViewControllerRegistry) {
        // https://stackoverflow.com/questions/39331929/spring-catch-all-route-for-index-html
        registry.addViewController("/")
            .setViewName("forward:/index.html")
        // Map "/word", "/word/word", and "/word/word/word" - except for anything starting with "/api/..." or ending with
        // a file extension like ".js" - to index.html. By doing this, the client receives and routes the url. It also
        // allows client-side URLs to be bookmarked.
        // Single directory level - no need to exclude "rest" (api)
        registry.addViewController("/{x:[\\w\\-]+}")
            .setViewName("forward:/index.html")
        // Multi-level directory path, need to exclude "rest" on the first part of the path
        registry.addViewController("/{x:^(?!rest$).*$}/**/{y:[\\w\\-]+}")
            .setViewName("forward:/index.html")
    }
 
    override fun addCorsMappings(registry: CorsRegistry) {
        if (RunningMode.webDevelopment) {
            log.warn("************************************")
            log.warn("***********               **********")
            log.warn("*********** ATTENTION!    **********")
            log.warn("***********               **********")
            log.warn("*********** Running in    **********")
            log.warn("*********** web dev mode! **********")
            log.warn("***********               **********")
            log.warn("************************************")
            log.warn("Don't deliver this app in dev mode due to security reasons (CrossOriginFilter is set)!")
            registry.addMapping("/**")
        }
    }
 
    companion object {
        private val CLASSPATH_RESOURCE_LOCATIONS = arrayOf("classpath:/webapp/static/", "classpath:/webapp/")
    }
}