tags:

views:

83

answers:

4

I would like to POST an entity as follows

POST /example.org/MyEntity/100

Based on the passed entity, the server would like to draw the users attention to a particular part of the response using a fragment identifier. e.g.

/example.org/MyEntity/100#InterestingPart

How do I return this new URL to the client. I am assuming I could do some form of redirect using a 3XX response code, but I actually do not want the client to do another request because the only difference between the two URLs is the fragment. At the moment it seems that a 307 return code would be the most appropriate because according to the spec you should not automatically redirect a POST.

Is there are better way?

Update: My client is not limited to the constraints of a web browser. I am just looking at this from the perspective of HTTP.

Update2: Based on my reading of RFC2616, I can see nothing stopping me from returning a 200 and a Location header that contains the fragment identifier. Anyone know of a reason why I cannot do that?

+1  A: 

I think the only sensible solution is to have action URL have static fragment identifier, like <form method="post" action="/action#anchored"> and then put an anchor wherever you want user to look at while generating page.

But, to answer the Update2: no, there's no reason to avoid it.

Michael Krelin - hacker
I can see how that would work if what I want to identify is predefined, but what about in the cases where it is dynamic. Say for example, the server did some validation and if there was an error, you wanted to point to that error. Or if the server created a new element in the response with a unique identifier that was previously unknown.
Darrel Miller
No, that's the idea, you chose static id, which you then put into proper point in page when generating it. Something like *if there was an error in email field, put anchor with id "anchored" before the field*.
Michael Krelin - hacker
Thanks for the update. I like your original suggestion and it will work for a number of scenarios. Just not all of my current ones.
Darrel Miller
You're welcome. Sure it is not always possible or may be too much work sometimes. It's just that you were asking about the way to position page without performing another HTTP request.
Michael Krelin - hacker
A: 

You should normally redirect every POST to avoid problems with refreshing the page and the use of the back button. This is known as the PRG (POST Redirect Get) pattern:

http://blog.httpwatch.com/2007/10/03/60-of-web-users-can%E2%80%99t-be-wrong-%E2%80%93-don%E2%80%99t-break-the-back-button/

Although, this does incur the cost of another round trip to the server it makes your web application much more user friendly.

You could then add the fragment onto the redirected URL.

There's an example of PRG with a fragment on this page:

http://www.httpwatch.com/httpgallery/redirection/

HttpWatchSupport
I cannot do a GET because the response from the POST is dynamically generated and is not stored on disk and I do not have any server side session state.
Darrel Miller
A: 

My inclination is to return 201 - and have the location header point to the URI you want the client to GET.

I didn't look, but IIRC nothing dictates that the location header points to the resource created, so it should be spec legal.

Jon Flanders
My understanding of 201 is that the server is indicating that it has created a new "Resource". In my case I have not done that. I may have created a new element within a resource, but not a whole new resource.
Darrel Miller
In that case, maybe your resource isn't fine-grained enough. Is it possible to break MyEntity into a main resource and one or more subordinate resources?
Rich Apodaca
If you are able to address that element - it isn't a resource? Why not as Rich suggests - refactor your resources.
Jon Flanders
Sometimes you cannot manipulate an item in isolation. In my case I have cost object with a cost distribution items. I want to warn the user that their distribution exceeds 100% before they attempt to PUT the updated cost object along with the distribution items. I cannot deal with a single cost item in isolation in a stateless manner. The only other direction I could go is to make the "in-progress" editing of the cost record a persisted resource. I'm not quite ready to give up just yet :-)
Darrel Miller
Oh, yeah. I'm not is a web browser, so I don't have javascript to do code-download. Maybe that's my real problem. :-/
Darrel Miller
A: 

POSTing to the URI:

http://example.org/MyEntity/100

implies to me that a MyEntity resource called "100" already exists. If that's the case, why not use PUT instead? Is this an update or a create operation?

An alternative might be:

POST http://example.org/MyEntities

Now your service has a choice to make from at least two possibilities:

  1. Return 201 Created. Set the Location header to be the URI you want the client to use (e.g.: http://example.org/MyEntities/100#InterestingPart). Add the representation of the new resource to the body.
  2. Return 204 No Content. Same as above, but no body. This option requires a subsequent GET to fetch the representation, which sounds like what you're trying to avoid.

Neither approach requires redirection and both can return as specific a URI as you desire.

I am curious though, why is the #InterestingPart significant? Why not just return the entire representation and its URI http://example.org/MyEntities/100 in the Location header - and let clients decide for themselves what's interesting or not? If the answers have something to do with only a small part of the resource being of interest (or being modified) during a request, how feasible would it be to break MyResource into a main resource and one or more subordinate resources? For example:

  • /MyResources/100/CoolThings
  • /MyResources/100/CoolThings/42
  • /MyResources/100/InterestingThings
  • /MyResources/100/InterestingThings/109
Rich Apodaca
My mistake, on oversimplification. I am actually POSTing to a "sandbox" resource http://example.org/MyEntity/100/Sandbox which is a special kind of processing resource that allows a user to interactively build an entity and when finished they PUT the entire resource to the /MyEntity/100 endpoint.In this case I am using a custom media type that represents a resource that maps to an aggregate root domain object that contains some child objects. Only the aggregate root is exposed as a resource as there complex dependencies between the child objects and the root object.
Darrel Miller
Because the response returned from the sandbox is only held in client state, it must POSTed back completely on each change. I want to be able to indicate to a client application that within the complete resource a new child object has been created by a previous request. This will allow the client to render not only the main resource but also a pop-up window for editing the specific child object.
Darrel Miller
201 is misleading because it infers that the server created a new aggregate root. However, it appears that I would not be violating the HTTP spec by returning a 200 with a modified Location header.
Darrel Miller
204 would not work for me because I cannot GET from sandbox as it does not hold a representation of the entity currently being edited as that would be client session state.
Darrel Miller