codeconsole opened a new pull request, #16797:
URL: https://github.com/apache/grails-core/pull/16797

   ## Description
   
   `GrailsWebRequestTaskDecorator` (#16230) binds each task started during a 
request to a `GrailsWebRequest` of its own, through 
`WebUtils.storeGrailsWebRequest`. That also stores the task's web request in 
the `org.grails.WEB_REQUEST` attribute of the request, which the request thread 
is still processing. Once any task has run, `GrailsWebRequest.lookup(request)` 
on the request thread returns the task's web request instead of the request 
thread's own.
   
   The request thread calls `lookup(request)` in several places, so state lands 
on the task's web request instead of the request's:
   - `UrlMappingsInfoHandlerAdapter` sets the action name and controller 
namespace, and hands the web request to the action result transformers.
   - `GrailsDispatcherServlet.checkMultipart` calls 
`multipartRequestResolved()` (#16149). That rebuilds the task's `params` 
instead of those the request thread read before the multipart request was 
resolved, so the request thread's `params` miss the uploads (the gh-13837 case).
   - `DefaultDataBindingSourceCreator`, `GrailsExceptionResolver` and 
`ResponseRedirector` look it up the same way.
   
   For example, an interceptor whose `before()` starts a `task { }` that 
finishes before the action runs leaves the action name on the task's web 
request.
   
   ### Changes
   
   - **The task's web request is bound to the task's thread only.** The 
decorator sets it in `RequestContextHolder` and no longer stores it on the 
request, so the attribute keeps the request thread's web request.
   - **`GrailsWebRequest.lookup(HttpServletRequest)` returns the thread's own 
web request for its own request.** When the web request bound to the calling 
thread was built with that very request object, it is returned. Otherwise the 
attribute is read as before, falling back to the thread's web request. So a 
task still finds its own web request from the request it was given, as it did 
when the attribute held it, and the request thread finds its own, including 
through a wrapper such as the dispatcher's multipart request. The common case, 
a lookup with the request the web request was built with, now skips the 
attribute read.
   
   ### Tests
   
   - `GrailsWebRequestTaskDecoratorSpec`: after a task of the request has run 
on another thread, the request attribute, `lookup(request)`, `lookup` through a 
wrapper and `lookup()` all return the request thread's web request, and 
`multipartRequestResolved()` through the dispatcher's wrapper rebuilds the 
request thread's `params`. Both fail on 8.0.x. A task still finds its own web 
request from its request.
   - `GrailsWebRequestSpec`: `lookup(request)` returns the thread's web request 
for its own request and the stored one for a wrapper (fails on 8.0.x), the 
stored one for another request, such as a forward's, and the thread's web 
request, or null, when the request holds none.
   
   ### Not covered
   
   `AsyncWebRequestPromiseDecorator` (`WebPromises`) still stores its task's 
web request on the request. Its tasks run once the action has started 
asynchronous processing, and with this change each one finds its own web 
request from the request it renders through.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to