Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overriding default JSON GET/POST behavior #1522

Merged
merged 13 commits into from Jun 7, 2014
Merged

Conversation

Shadowfiend
Copy link
Member

Creating a ticket as per https://groups.google.com/d/msg/liftweb/E-XlChwJd10/-8Uix3KJDXEJ.

To summarize, the idea was to allow the customization of how JSON requests are handled; currently, the framework is hardcoded to require the Content-Type header of any JSON requests to always be application/json. However, this is not how many JSON based web services work, and shouldn't be a hardcoded requirement in the case of e.g. web services that are designed to only use JSON anyway (i.e. the content-type selection is redundant).

However YMMV, and perhaps for the sake of keeping the framework simple—although at least the HTTP REST code is not overly simple and easy to follow anyway—it might be worth to keep things how they are.

@Shadowfiend
Copy link
Member

I've started looking into this, but don't have any working code yet. More to come soon, hopefully :)

Until now, it returned Empty. This helps clarify what’s going on
to consumers. Additionally, added a test to verify this, and
some clarifying documentation to the method.
This reflects the motivation for using it a little better.
bodyAsJson ignores content type and forcibly tries to parse
a request body as JSON. Failure is only reported when there
is an issue doing the actual JSON parse.
This lays the groundwork for an easy mockXmlReq to test
XML body types.
bodyAsXml ignores content type and forcibly tries to parse
a request body as XML. Failure is only reported when there
is an issue doing the actual XML parse.
@Shadowfiend Shadowfiend added this to the 2.6-M4 milestone Apr 9, 2014
@Shadowfiend
Copy link
Member

Ok, I've attached some code here that implements bodyAsJson/bodyAsXml, and switches json and xml to return descriptive Failures when we don't parse due to content-type mismatches.

@Shadowfiend
Copy link
Member

Any feedback here?

@erikkaplun
Copy link
Author

I don't really have a way to test this out right now... embarrassingly, I decided to switch back to pure servlets for my purposes because Lift was just too much hassle, undocument complexity and learning curve for my relatively small project, which wasn't alleviated by the fact that a lot of things in Lift happen with no real static typing, so the type system can't lead/guide you in most situations. Apologies for having stirred up dust and then sort of leaving the scene...

@Shadowfiend
Copy link
Member

That's fine. I think it's a valuable addition anyway, so if any committers have thoughts that would be appreciated, and then we can look at getting it in.

@Shadowfiend
Copy link
Member

I'm probably going to merge this in over the next week or so if no one objects.

@farmdawgnation
Copy link
Member

👀

* Forcibly tries to parse the request body as JSON. Does not perform any
* content type checks, unlike the json method.
*/
lazy val bodyAsJson: Box[JsonAST.JValue] = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this is more aptly named bodyAsJosn_!?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm… So this won't throw an exception, and there's generally nothing dangerous about it that I can see. What about it makes you want a _!?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, that's true, this is returning a Box. I wanted something to indicate that this is bypassing a guardrail you might otherwise want turned on. Unless I'm inclined to go hunting for the scaladoc, which not everyone is, the difference between json and bodyAsJson seems subtle enough for someone to very easily misunderstand what the difference is.

Maybe I'm just over-thinking it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see @farmdawgnation 's point and I agree, we should make it a bit more obvious that most people should use json and not this new method, maybe forceBodyAsJson?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm…

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh. Whoops! What I meant was… Hmmm…

I don't think we should discourage this method that strongly. I think it's more of making the “most standard” method easier than it is discouraging the less standard method. json follows the standard to a T, refusing to even attempt to parse a request that isn't explicitly marked as JSON as such. But not doing this isn't a security hole per se, in that we are about as certain as we are with any other part of the system that our JSON parser is secure.

That said, I do think forcedBodyAsJson is more descriptive of what's happening than just bodyAsJson. So I'm a little torn.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At first I was going to suggest unsafeBodyAsJson but I think that really looks like discouraging it very strongly :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bodyConvertedToJsonRegardlessOfContentType

lol

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's do forcedBodyAsJson. I think that communicates enough of the difference to make that mental switch flip in somebody's head.

@farmdawgnation
Copy link
Member

There don't appear to be specs demonstrating what the forcible methods do if the content can't actually be converted to that type. Do they return Empty or Failure? Can we add a spec for that case?

@Shadowfiend
Copy link
Member

Yeah, I can add specs. It'll be a Failure (with an exception).

Conflicts:
	web/webkit/src/test/scala/net/liftweb/http/ReqSpec.scala
We do this to more clearly indicate that you are bypassing
built-in safeguards against incorrect Content-Types when
you use these methods.
These specs clarify that we expect Failures when the
content types are either correct or ignored but the contents
of the request bodies are not valid XML or JSON bodies,
depending on which method is being called.
@Shadowfiend
Copy link
Member

Ok, made those two changes:

  • bodyAsXml and bodyAsJson are now forcedBodyAsXml and forcedBodyAsJson, respectively.
  • Specs to verify that we get a Failure when content type checks pass but contents cannot be properly parsed as the requested type.

@fmpwizard
Copy link
Member

awesome! 👍

@farmdawgnation
Copy link
Member

Going to verify locally, then merge.

@farmdawgnation
Copy link
Member

Let's ship it.

farmdawgnation added a commit that referenced this pull request Jun 7, 2014
Expose forcedBodyAsJson and forcedBodyAsXml to allow you to convert body content to those respective formats and bypass the Content-Type check.
@farmdawgnation farmdawgnation merged commit 091c837 into master Jun 7, 2014
@farmdawgnation farmdawgnation deleted the 1522-forcibly-jsonic branch June 7, 2014 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants