Alexander Klimetschek skrev:
Currently internal BlockServlet calls do not contain the original request parameters or attributes, i.e. the BlockCallHttpServletRequest has none of them and no reference to the original request (when called from a BlockSource, but this is currently the only scenario anyway). We are using the request attributes to store the name of the logged-in user, because the authentication is done by a servlet filter (which sits before the DispatcherServlet). Now when you make an internal call to another block this username request attribute gets lost which is bad, because you are forced to put all user-related functionality (eg. authorisation) in the front-end block sitemap, which is often not possible.

I solved it that way to not need to answer lots of complicated questions about exactly how this should work.

For request parameters you can in the current solution just resend the parameters that you need as query parameters in the block protocol.

This could be complemented by giving access to the original request parameters. For this case we need a call stack where each block protocol call pushes a new request object, and where all parameter lookup is done through the stack.

For request parameters the situation is more complicated, we need a call stack where the local attribute context is pushed. Otherwise your block will aways risk that some other block in the call chain happen to use the same parameter name and affect your block. But you probably also need to be able to set the global attribute to communicate state information between blocks. For the Cocoon protocol this is done by having booth a global and a local scope for parameters (see o.a.c.environment.Request). But this solution requires an extension to the standard HttpServletRequest, and I preferred to avoid that. But if we have a need for it we could extend the current design.

For the rest of the request (and response) object we would need to evaluate what should be available everywhere and what should be specific for the current block call.

There is also no possibility to make pipelines only available to other blocks in the same cocoon webapp, but not for external HTTP requests, like you can define an internal-only="true" for pipelines inside a sitemap. That would be at least a workaround for having working authorization.
There should be a simple possibility, just remove the block path property from a managed servlet and then the dispatcher servlet will not use it. And it will still be available as a component and thus possible to connect to and use through the block protocol. Now this will not be usable for the block servlet as it has a getBlockPath method and therefore always will be connected. If we strengthen the condition in the dispatcher servlet to only connect to servlet that has a *non null* block path property, it would be enough to not configure the block path property to make the block servlet internal..

My idea would be to include the original request in the BlockCallHttpServletRequest, either by referencing it, or by completely including all request params and attributes of the original request.
As described above there is a little bit more one have to think about.

Technically this could be implemented by storing the original HttpRequest in the BlockCallStack (in a ThreadLocalStorage, one request per thread) and then provide a static method BlockCallStack.getOriginalRequest() that returns that request object, which can be called inside BlockConnection where the BlockCallHttpServletRequest is created. That one should hold a reference and include the params and attributes.
Would probably work, but as indicated above it should probably be stack based.

Thinking further about it, you could take a look at the request scope for Spring managed beans (http://static.springframework.org/spring/docs/2.0.x/reference/beans.html#beans-factory-scopes-request). Using that you could put your login information in a request scoped bean, and use that from the different blocks.

The main question is: is it feasible to always include all request parameters and attributes and other information (HTTP method, original URI...) or do you sometimes want a "clean" call to another BlockServlet?
The clean call is probably the default scenario.

/Daniel

Reply via email to