grails-core
grails-core copied to clipboard
Grails application reachable before fully deployed
Expected Behavior
The Grails application should not allow users to make HTTP requests before the application is fully deployed.
Actual Behaviour
The application accepts and actually processes HTTP requests before 'com.valsight.BootStrap#init' has finished executing.
This is especially problematic in relation to the "org.grails.plugins:database-migration" plugin, because the app processes HTTP requests, before the migrations are done.
Here is an example project that adds a delay to 'com.valsight.BootStrap#init' you can use to easily create HTTP requests before the app is deployed. app-accessible-too-early-bug-report-27092022.zip
Steps To Reproduce
- In any environment
- Start the application (use the attached project to make it easier)
- fire an HTTP request to the application while 'com.valsight.BootStrap#init' is executing
- the actual error: the HTTP request is fully processed before 'com.valsight.BootStrap#init' is finished
Environment Information
Operating system: Ubuntu 22.04
Java version:
openjdk version "1.8.0_342" OpenJDK Runtime Environment (build 1.8.0_342-8u342-b07-0ubuntu1~22.04-b07) OpenJDK 64-Bit Server VM (build 25.342-b07, mixed mode)
Example Application
No response
Version
5.2.4
I know this is an old question but i just got hit by the same bug. Grails 5.3.6
No filters are applied so all requests are running, even protected db access.
Found a patch for now: Service:
class WaitForBootstrapService {
static lazy = false
Boolean bootstrapDone = false
}
Interceptor:
class WaitForBootstrapInterceptor implements Interceptor {
int order = HIGHEST_PRECEDENCE + 50
WaitForBootstrapService waitForBootstrapService
WaitForBootstrapInterceptor() {
matchAll()
}
boolean before() {
if(!waitForBootstrapService.bootstrapDone) {
response.status = 503
}
return waitForBootstrapService.bootstrapDone
}
boolean after() { true }
void afterView() {
// no-op
}
}
In Bootstrap
class BootStrap {
WaitForBootstrapService waitForBootstrapService
def init = { servletContext ->
log.info("Start Bootstrap")
// All normal bootstrap code
waitForBootstrapService.bootstrapDone = true
log.info("Finish Bootstrap")
}
def destroy = {
}
}