Skip to content

Instantly share code, notes, and snippets.

@danbev
Created November 1, 2012 07:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danbev/3992369 to your computer and use it in GitHub Desktop.
Save danbev/3992369 to your computer and use it in GitHub Desktop.
AeroGear-Controller Status Response

Background

This gist discusses possible solutions to AEROGEAR-581 "Support listening for "HttpErrorStatusEvent" and return response status/message."

Task description

When a request enters the controller, and the isRouteAllowed() method of the current SecurityProvider implementation denies the request, we want to be able to return a response code instead of redirecting the request to a view. This would be done by having AeroGear-Controller listen for CDI events of something like HttpErrorStatusEvent, and in that case respond with the information in the generated event (status and message).

Current implementation

The current implementation allows for a SecurityProvider implementation to throw an exception and if that exception is of type HttpStatusAwareException the controller sets the status code from the instance on the HttpServletResponse. One things I noticed when looking into this is that there is a bug, which I think I introduced, in the current implementation, we only set the statusCode but do not return the response to the client at that point, instead we enter the "normal" error route handling and if an error route has been configured for the type of exception thrown, that error view will be displayed, or the default AeroGear Controller view will be displayed

CDI Event proposal

I've implemented a version using CDI events where a SecurityProvider implementation can choose to fire an event of either:

  • AccessDeniedExceptionEvent
    When the provider fires such an event it does not want the controller to respond directly to the client but instead delegate to an error route with the exception from the event.

  • AccessDeniedResponseException
    When the provider fires such an event it wants the controller to respond directly to the client with the status/message/contentType contained in the event.

DummySecurityProvider has been updated to show how these events would be used.

To handle these events, DefaultRouter has two observer methods that observe the above events. The second event handler/observer, AccessDeniedRepsonseEvent, needs access to the HttpServletResponse to be able to return the status information to the calling client.
This brings up an issue regarding thread safety since there is only one instance of DefaultRouter but multiple threads servicing incoming calls and delegating to that instance. The current implementation uses a ThreadLocal (hides from qmx) to set the HttpServletResponse before invoking the SecurityProvider

We also have to keep in mind the use case where a user wants to handle a security exception by displaying a view. If the security provider always fires an AccessDeniedResponseExceptionEvent an error route no longer has a specific type of exception to handle.

Conclusion

I feel that using a standard exception for this would provide us with a simpler and more efficient solution.

How about we introduce a AeroGearSecurityException, (I know that Bruno already has such an exception in AeroGear Security so perhaps a different name) and a subclass like AeroGearSecurityResponseException. If an instance of AeroGearSecurityResponseException is thrown, it will be handled by returning the statusCode/statusMessage directly to the calling client by-passing any exception routes. This solution would enable an error route to specify AeroGearSecurityException and be able to display a view for it.

Am I missing something that CDI events brings to the table that I've not considered above, for example, are there any requirements from AeroGear-Security?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment