How to handle 4xx status but valid JSON entity?

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

How to handle 4xx status but valid JSON entity?

Lanny Ripple
Hi,

I've come across a situation in dispatch that isn't as easy to handle as I think it should be.  I have a web-service from which you can query for people based on an id.  If the person is not in our datastore I return status 404 but also provide a JSON response from the app.  As dispatch is written if the response code is not in the 2xx range my ># handler will not be run.

It looks like I need to set up a try{} block and then hand-execute the JSON parsing that ># was good enough to have ready for me already.   What I'd like to see is some version of HttpExecutor's apply() which I could provide the code check to.  Something as straightforward as

   final def apply[T](hand: Handler[T], expectedCode: Int => Boolean) = excepting[T] {
      (this when expectedCode)(hand)
   }

giving

  http( req ># { handleJv(_) }, code => { val h = (code/100).toInt; h == 2 || h == 4 })

although better sugar would be... sweeter.  (Yes, I know.  /groan)

If I've missed a way this can be achieved that's already available please clue me in.  Thanks,

  -ljr
Reply | Threaded
Open this post in threaded view
|

Re: How to handle 4xx status but valid JSON entity?

n8han
Administrator
You can use Http#x instead of Http#apply. Look for "allow any status code with x" in the specs:
http://sourced.implicit.ly/net.databinder/dispatch-http.test/0.7.8/HttpSpec.scala.html

On 02/24/2011 11:40 PM, Lanny Ripple [via Databinder] wrote:
Hi,

I've come across a situation in dispatch that isn't as easy to handle as I think it should be.  I have a web-service from which you can query for people based on an id.  If the person is not in our datastore I return status 404 but also provide a JSON response from the app.  As dispatch is written if the response code is not in the 2xx range my ># handler will not be run.

It looks like I need to set up a try{} block and then hand-execute the JSON parsing that ># was good enough to have ready for me already.   What I'd like to see is some version of HttpExecutor's apply() which I could provide the code check to.  Something as straightforward as

   final def apply[T](hand: Handler[T], expectedCode: Int => Boolean) = excepting[T] {
      (this when expectedCode)(hand)
   }

giving

  http( req ># { handleJv(_) }, code => { val h = (code/100).toInt; h == 2 || h == 4 })

although better sugar would be... sweeter.  (Yes, I know.  /groan)

If I've missed a way this can be achieved that's already available please clue me in.  Thanks,

  -ljr



If you reply to this email, your message will be added to the discussion below:
http://databinder.3617998.n2.nabble.com/How-to-handle-4xx-status-but-valid-JSON-entity-tp6063423p6063423.html
To start a new topic under Databinder, email [hidden email]
To unsubscribe from Databinder, click here.

Reply | Threaded
Open this post in threaded view
|

Re: How to handle 4xx status but valid JSON entity?

Lanny Ripple
Aha.  The lightbulb is on now.  You've already got what I was looking for as when() (which I looked through to write my post but I was fixating on the handler being an argument to apply.)

Many thanks,
  -ljr
Reply | Threaded
Open this post in threaded view
|

Re: How to handle 4xx status but valid JSON entity?

chris_lewis
In reply to this post by n8han
Thanks for this tip Nathan. I'm wanting to exploit this a bit further, but I can't track down why that works. Assuming this x method is:

HttpExecutor#x[T](req: Request)(block: Handler.F[T])

where Handler.F is defined as:

type F[T] = (Int, HttpResponse, Option[HttpEntity]) => T

How can we match on 4 arguments, given that x invokes block with only 3?

-chris
Reply | Threaded
Open this post in threaded view
|

Re: How to handle 4xx status but valid JSON entity?

n8han
Administrator
In that example:

    (test / "do_not_want" as_str)

Is a Handler, so the function after that which pattern matches on 4 parameters is actually this Handler#apply:
http://sourced.implicit.ly/net.databinder/dispatch-http/0.7.8/dispatch/Http.scala.html#19978

The return value of that is what's actually passed to http.x.

Yeah, the overloading three is needlessly confusing. I could perhaps get rid of the other HttpExcutor#x, which takes a Request and a Handler.F[T], because I doubt anyone is using it. When I was writing that originally I thought people might want to have a lower level way of executing requests, but the Handlers seem to be used universally. It helps that you can always define your own Handler, so it is effectively as low level as it needs to be.

In the 080 branch I already shifted things around such that the x method that takes a Handler is the more fundamental one. I think I'll just deprecate def x[T](req: Request)(block: Handler.F[T]) and see if anybody complains.

Nathan