Details

    • Type: Sub-task Sub-task
    • Status: Open
    • Priority: Major Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: 2.4-M2
    • Component/s: None
    • Labels:
      None

      Description

      I have an app that uses a nice url scheme based on product names, so bad URLs are going to happen. There are several actions that require a valid thing but it may not exist. A requirement is to display a nice page, but return a 404. It would be great if I could just throw a MissingThingException and map that to a particular controller/action and have it generate a 404 response.

      A possible URL mapping syntax would be...

      "404"(controller: "missing", action: "thing", exception: MissingThingException)
      

      The presence of the exception key prevents this from being used as a global mapping for 404s. This should be open for any valid HTTP response code.

        Activity

        Hide
        Luke Daley added a comment -

        Moving to 1.4 as it is too big to go in the 1.3 line now.

        Show
        Luke Daley added a comment - Moving to 1.4 as it is too big to go in the 1.3 line now.
        Hide
        cdeszaq added a comment -

        Having exceptions of various types map to response codes is also going to be more important as Grails moves towards better REST support, since proper response code usage is an integral part of a REST architecture.

        Show
        cdeszaq added a comment - Having exceptions of various types map to response codes is also going to be more important as Grails moves towards better REST support, since proper response code usage is an integral part of a REST architecture.
        Hide
        Graeme Rocher added a comment -

        Jeff - please move this one up the priority list when you're done with what you're currently working on

        Show
        Graeme Rocher added a comment - Jeff - please move this one up the priority list when you're done with what you're currently working on
        Hide
        Nicolas BARRE added a comment - - edited

        We have been using this kind of syntax with Grails 2.2.0.

        Example :

        UrlMappings.groovy
        import fr.mma.usage.exceptions.BusinessException
        import fr.mma.usage.exceptions.TechnicalException
        import org.gcontracts.AssertionViolation
        
        class UrlMappings {
        
        	static mappings = {
        		...
        		
        		'502'(controller: 'errors', action: 'indisponibilite') {}
        		'500'(controller: 'errors', action: 'forbidden', exception: AssertionViolation) {}
        		'500'(controller: 'errors', action: 'indisponibilite', exception: TechnicalException) {}
        		'500'(controller: 'errors', action: 'indisponibilite', exception: BusinessException) {}
        		'500'(controller: 'errors', action: 'indisponibilite') {}
        		'404'(controller: 'errors', action: 'notFound') {}
        		'403'(controller: 'errors', action: 'forbidden') {}
        	}
        }
        

        Is it really different with the suggested evolution ?

        Show
        Nicolas BARRE added a comment - - edited We have been using this kind of syntax with Grails 2.2.0. Example : UrlMappings.groovy import fr.mma.usage.exceptions.BusinessException import fr.mma.usage.exceptions.TechnicalException import org.gcontracts.AssertionViolation class UrlMappings { static mappings = { ... '502'(controller: 'errors', action: 'indisponibilite') {} '500'(controller: 'errors', action: 'forbidden', exception: AssertionViolation) {} '500'(controller: 'errors', action: 'indisponibilite', exception: TechnicalException) {} '500'(controller: 'errors', action: 'indisponibilite', exception: BusinessException) {} '500'(controller: 'errors', action: 'indisponibilite') {} '404'(controller: 'errors', action: 'notFound') {} '403'(controller: 'errors', action: 'forbidden') {} } } Is it really different with the suggested evolution ?
        Hide
        cdeszaq added a comment -

        If it's true that the syntax Nicolas showed currently works, then this ticket can be closed I think!

        Show
        cdeszaq added a comment - If it's true that the syntax Nicolas showed currently works, then this ticket can be closed I think!
        Hide
        Jeff Scott Brown added a comment -

        Nicolas,

        I don't think you are doing what the issue is requesting. I think the original request is to allow a specific exception type to be mapped to a controller action and have the response code set to 404. Your response codes are not being set to 404, are they? I don't think you can change your '500's in your mapping to '404's and have that work. Can you?

        Thanks for the feedback.

        Show
        Jeff Scott Brown added a comment - Nicolas, I don't think you are doing what the issue is requesting. I think the original request is to allow a specific exception type to be mapped to a controller action and have the response code set to 404. Your response codes are not being set to 404, are they? I don't think you can change your '500's in your mapping to '404's and have that work. Can you? Thanks for the feedback.
        Hide
        Nicolas BARRE added a comment - - edited

        You are absolutely right the above syntax doesnt set the HTTP status for you. What the above syntax does allow you to do (and that is why we use it) is set the HTTP status code in the controller that handles the error.

        For instance :

        '500'(controller: 'errors', action: 'forbidden', exception: AssertionViolation) {}
        

        Means that for an error raised by a controller : IF status code = 500 AND exception is of type AssertionViolation THEN handle exception with the specified controller / action.

        Then in the 'forbidden' action of errors controller we set the HTTP status code to 403 which is more correct from an HTTP status code standpoint than a 500 status code :

        def forbidden() {
        	response.status = response.SC_FORBIDDEN
        	render view: 'error_403'
        }
        

        I hope it clarifies things.

        Show
        Nicolas BARRE added a comment - - edited You are absolutely right the above syntax doesnt set the HTTP status for you. What the above syntax does allow you to do (and that is why we use it) is set the HTTP status code in the controller that handles the error. For instance : '500'(controller: 'errors', action: 'forbidden', exception: AssertionViolation) {} Means that for an error raised by a controller : IF status code = 500 AND exception is of type AssertionViolation THEN handle exception with the specified controller / action. Then in the 'forbidden' action of errors controller we set the HTTP status code to 403 which is more correct from an HTTP status code standpoint than a 500 status code : def forbidden() { response.status = response.SC_FORBIDDEN render view: 'error_403' } I hope it clarifies things.

          People

          • Assignee:
            Jeff Scott Brown
            Reporter:
            Luke Daley
          • Votes:
            6 Vote for this issue
            Watchers:
            10 Start watching this issue

            Dates

            • Created:
              Updated:
              Last Reviewed:

              Development