Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Web-Machine CPAN distribution.

Report information
The Basics
Id: 78631
Status: resolved
Priority: 0/
Queue: Web-Machine

People
Owner: Nobody in particular
Requestors: hanenkamp [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in: 0.03
Fixed in: (no value)



Subject: Why does create_path happen before the accepted handler?
The order of operations in step N11 of the FSM states doesn't make sense to me. If this is a post_is_create operation, we immediately setup the create path. This, then, sets up the Location header in the response. However, this happens even before we know what the status response is and Location only makes sense for 201 (the assumed most likely), 300, 301, 302, 303, 305, and 307 responses. Furthermore, the most useful thing to do is to create the new item inside the accept handler, e.g., from_json. It is very likely that a typical application (e.g., mine or fREW's drinkup) won't even know the path to redirect to until *AFTER* the JSON is parsed and probably not until after the JSON has been used to create a record and some auto-increment or UUID or whatever has been created. All of this happens after we have already setup the Location header. fREW's solution looks like the one I will have to do as well: sub post_is_create { 1 } sub create_path { "worthless" } sub from_json { my $obj = $_[0]->create_resource( $_[0]->decode_json( $_[0]->request->content ) ); $_[0]->redirect_to_new_resource($obj); } The above was taken from https://github.com/frioux/drinkup/blob/master/lib/DU/WebApp/Resource/Role/Set.pm At least an explanation of this ordering would be nice to have in the documentation for Web::Machine::Resource. Personally, I would like to see the order of operations swapped so that Location is setup after we are sure we know what we've just created (if anything). Cheers.
I believe there may be a similar ordering problem in state o14. There we check is_conflict prior to attempting the accept handler. In the situations I envision, it would make more sense to check is_conflict AFTER running the accept handler. This way the accept handler has a chance to read the data encoded and then set or clear the is_conflict flag based on the action taken. Otherwise, we probably have to parse the data early (which requires discovering what the data actually is again by re-examining the Accept header to determine how to parse it), require some customer X-Headers in the request, or require the relevant versioning information in the path itself. I'm not necessarily expecting a behavioral change here (or in response to my original report), but it might at least be helpful to elucidate the ordering of some of these decisions more clearly in the docs. As it stands, it looks like the only sensible route is to ignore is_conflict() and implement my own conflict handling code in from_json. I'd almost like to create a custom state machine extending the existing one, but that looks difficult and seems fraught with peril, and the Knights of the Round Table have forbidden even a little peril because it's too perilous.
Subject: Re: [rt.cpan.org #78631] Why does create_path happen before the accepted handler?
Date: Sun, 29 Jul 2012 21:26:09 -0400
To: bug-Web-Machine [...] rt.cpan.org
From: Stevan Little <stevan.little [...] iinteractive.com>
Andrew, First of all, thanks for diving in so deep :) Second, please keep in mind that Web::Machine currently is a strict port of the erlang/ruby implementations as done but the Basho people. While I want the core to mirror what they have, I am not against straying from said core as we all begin to use it more and more. Let me first address the n11 ordering, because I know I found it strange and so did others. When I brought this up to sean cribbs (the author of the Ruby port, from which my port is heavily based) he said he had also brought up the same point with the original Erlang author (I think it was justin sheehey) and basically the answer was "you shouldn't base your resource URLs on things like Database IDs". Which I have to admit makes sense, however, is highly inconvenient. So, my thoughts on this have been a little scattered, but I am basically thinking that we need to add another predicate to the Web::Machine::Resource (and then alter n11 accordingly) such that you can override this behavior and assign the location after the handler has run. Now, as for the is_conflict flag, I think this is just a misunderstanding of the intention of this predicate. This flag is intended for checking conflicts against things like ETags and vectorclocks (as is the case in Riak). The idea is that within is_conflict you have the ID (parsed from the URL) and access to HTTP headers in which some kind of version information would be stored. From here you can detect the conflict even without having to read the new data being submitted or even read out the old data from the database. Now, I agree, this is not always how you might detect and handle conflicts, in those cases then I suggest your handler actually throw the 409 conflict error (if any handler returns a status code (the reference to the status number), then this will be handled accordingly by Web::Machine). Make sense? If you like we can discuss this on #webmachine on irc.perl.org as well. - Stevan On Jul 28, 2012, at 9:48 PM, Andrew Sterling Hanenkamp via RT wrote: Show quoted text
> Queue: Web-Machine > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=78631 > > > I believe there may be a similar ordering problem in state o14. There we check is_conflict prior > to attempting the accept handler. In the situations I envision, it would make more sense to > check is_conflict AFTER running the accept handler. This way the accept handler has a chance > to read the data encoded and then set or clear the is_conflict flag based on the action taken. > > Otherwise, we probably have to parse the data early (which requires discovering what the data > actually is again by re-examining the Accept header to determine how to parse it), require > some customer X-Headers in the request, or require the relevant versioning information in the > path itself. > > I'm not necessarily expecting a behavioral change here (or in response to my original report), > but it might at least be helpful to elucidate the ordering of some of these decisions more clearly > in the docs. > > As it stands, it looks like the only sensible route is to ignore is_conflict() and implement my > own conflict handling code in from_json. I'd almost like to create a custom state machine > extending the existing one, but that looks difficult and seems fraught with peril, and the > Knights of the Round Table have forbidden even a little peril because it's too perilous.
Subject: Re: [rt.cpan.org #78631] Why does create_path happen before the accepted handler?
Date: Mon, 30 Jul 2012 11:40:16 -0500
To: bug-Web-Machine [...] rt.cpan.org
From: Sterling Hanenkamp <sterling [...] hanenkamp.com>
On Sun, Jul 29, 2012 at 8:26 PM, Stevan Little via RT < bug-Web-Machine@rt.cpan.org> wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=78631 > > > Andrew, > > First of all, thanks for diving in so deep :) >
Your welcome. Show quoted text
> Second, please keep in mind that Web::Machine currently is a strict port > of the erlang/ruby implementations as done but the Basho people. While I > want the core to mirror what they have, I am not against straying from said > core as we all begin to use it more and more. >
Understood. I wasn't posting the bug report to try and force a change. I'm trying to get a feel for the best way to work around this. So far, fREW's Drinkup app seems to be the best available example for how to do things. He's a smart coder so he's probably got a good idea on how to handle these problems, but I wanted some confirmation of that, which you've now given. Show quoted text
> Let me first address the n11 ordering, because I know I found it strange > and so did others. When I brought this up to sean cribbs (the author of the > Ruby port, from which my port is heavily based) he said he had also brought > up the same point with the original Erlang author (I think it was justin > sheehey) and basically the answer was "you shouldn't base your resource > URLs on things like Database IDs". Which I have to admit makes sense, > however, is highly inconvenient. >
While I agree with cribbs and sheehey (and even implemented this particular project in terms of UIDs generated in the Perl code), it's still too soon. I don't even know if I'm going to have a record yet because I still have to verify that the data they've given me is readable, let alone contains all the necessary information. I suppose I could generate the ID first and then just throw it away or keep around for reuse on the next try, but that's still a bit inconvenient. It also means that I'm having the web server decide when to generate the ID, which doesn't seem like the correct separation of concerns to me. This also has a weird side-effect I've just noticed in my testing. If bad stuff happens while creating my records, I end up with a response that looks like: 500 Internal Server Error Location: /base/uri/* Content-Length: 0 Where the "*" here is placeholder I'm using there ("worthless" in fREW's code). If I had set that to the anticipated UID value, that could prove awkward and confusing. Now, my error handler needs to make sure to strip the Location header on the way out to avoid this. Seems like that shouldn't be necessary. Anyway, fREW's work around does the job for now and I can cope with it. Show quoted text
> ... > > Make sense? >
Yep. I can see what you're saying about is_conflict now. On the other hand, my reading of the HTTP/1.1 spec suggests that my intended use of the 409 response is legit. If/when I implement such, I'll do it as you suggest. Show quoted text
> If you like we can discuss this on #webmachine on irc.perl.org as well. >
Maybe I will. I haven't done much IRC in the last few years. I keep saying I'll get back on, but then I don't. Thanks for the help. I won't make any promises, but I'd like to have a cookbook to address some of these issues. If I get around to it, I'll send you a pull request. Cheers. -- Andrew Sterling Hanenkamp sterling@hanenkamp.com 785.370.4454
Subject: Re: [rt.cpan.org #78631] Why does create_path happen before the accepted handler?
Date: Mon, 30 Jul 2012 11:41:23 -0500
To: bug-Web-Machine [...] rt.cpan.org
From: Sterling Hanenkamp <sterling [...] hanenkamp.com>
Show quoted text
> > Your welcome. >
You are welcome, too. -- Andrew Sterling Hanenkamp sterling@hanenkamp.com 785.370.4454
I'm bumping into the same issue with N11 now. The idea that "you shouldn't base your resource URLs on things like Database IDs" has theoretical merit, but forcing the addition of an arbitrary Alternate Key (plus index) is often a significant burden. As you say Stevan, "highly inconvenient". Your suggestion of an extra predicate, so the flow suits typical apps that do automatic key assignment on creation, would be most welcome!
RT-Send-CC: sterling [...] hanenkamp.com
Tim, Andrew, I have created a branch for this (https://github.com/stevan/webmachine-perl/tree/n11-bypass), it was a rather simple fix, hopefully it will work for you both. Here is the code: https://github.com/stevan/webmachine- perl/commit/b2d20776a710958112045de7899229a2e6e9b4d2 Here is the test: https://github.com/stevan/webmachine- perl/commit/69e6f511a17ced92704976d3462eb12c9ddd64a1 If this works for you both I will be happy to add it to core. - Stevan On Fri Feb 08 06:38:39 2013, TIMB wrote: Show quoted text
> I'm bumping into the same issue with N11 now. > > The idea that "you shouldn't base your resource URLs on things like > Database IDs" has theoretical merit, but forcing the addition of an > arbitrary > Alternate Key (plus index) is often a significant burden. As you say > Stevan, "highly inconvenient". > > Your suggestion of an extra predicate, so the flow suits typical apps > that do automatic key assignment on creation, would be most welcome!
Resolved in 0.07