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

Handling POST requests #32

Open
xogeny opened this issue Sep 13, 2014 · 6 comments
Open

Handling POST requests #32

xogeny opened this issue Sep 13, 2014 · 6 comments

Comments

@xogeny
Copy link

xogeny commented Sep 13, 2014

This isn't really an issue but more of a question (that might highlight an issue...but I'm not sure).

I've created a HAL based API. So hyperagent seems well suited for that. I don't 100% understand when I'm supposed to fetch and when I'm not, but that is a separate, manageable issue.

The main issue I'm having is with handling POST requests. There are cases where I have to do a POST to create resources on the server. I'm aware of the "dialects" to HAL for such things, but I'm not using those (at least in this case) because I'm uploading files and I don't think HAL makes any sense in that context (although correct me if I'm wrong).

Being a good REST api, the POST returns a 201 status and a Location header. But in a hyperagent context, that is just another URL, not a proper Resource object. What I do now is basically:

var loc = resp.headers("Location");
var new_url = Hyperagent.Resource.resolveUrl(base_url, loc);
return new Hyperagent.Resource(new_url).fetch();

So basically, I read the Location header of the POST response (which is just that path portion), combine that with the base_url for the API to get a fully qualified URL and then create a new Resource object from that. This feels odd to me because I feel that when I stay in the realm of GET, I only have to create one "api" Resource and I can navigate entirely from there (which is how it should be, right).

But here, I have to start messing around with URLs again, which is exactly what I was hoping to avoid with a very hypermedia centric API. The strange thing is...why should a POST complicate things. The Location header is a standard way to return the URL of a new resource. Why not take advantage of that somehow? I didn't see any reference to the Location header anywhere in the hyperagent source so it doesn't seem like this is taken into account.

What I envision is something like this:

var res = api.link('files').post(data, { headers: ... })

The idea here would be a method, post, that (behind the scenes) makes a POST request to the files resource, parses the Location header (like I've done above?) and then returns the resource. In this way, the client code looks clean and avoids all this URL handling?

Is this the "proper" way to go about this or am I missing something. I'm happy to do the work and submit a PR. I just want to make sure a) I'm not doing it wrong, b) there isn't already a way to do this cleanly and c) if it were to be done that this is the way to do it.

Comments?

@sdbondi
Copy link

sdbondi commented Jan 22, 2015

Great question @xogeny - seems currently there is no way to do a POST request?

This line ignores specifying the method option. (EDIT: Actually passing {ajax: {method : "POST"}} option to fetch will enable you to POST)

Any plans to work on this?

@xogeny
Copy link
Author

xogeny commented Jan 22, 2015

@sdbondi It isn't clear if @weluse would accept a PR for this. I'm definitely interested in adding this capability.

For the moment, I guess we have your comment about {ajax: {method: "POST"}} as a workaround. How do you specify the payload for the POST request?!? Is there an ajax option for that as well?

Interestingly, I have a whole bunch of PRs pending for the halgo library which is quite similar to hyperagent, but for Go. They are similar. It would be nice if there was a sort of consistent API across the libraries. For example, I have one pull request there that handles the LOCATION header issue I mention above.

@sdbondi
Copy link

sdbondi commented Jan 23, 2015

The ajax option extends any options passed to the specified ajax method (for e.g. $.ajax) so {ajax: { method: 'POST', data: {...} } would include a payload. See this line

It seems to be considered best practice/standard for resource creation to include a Location header. Some support for Location makes sense. I guess being able to call fetch on the new resource would look at the location header??

api.link['files'].post(data).then(function(newFile) { return newFile.fetch() }).then(...)

I am working my way through building a HAL api with hyperagent on the client-side and may end up submitting various PRs for this repo once I get further.

@xogeny
Copy link
Author

xogeny commented Jan 23, 2015

On the topic of ajax, issue number #38 might also be of interest.

@passy
Copy link
Contributor

passy commented Jan 25, 2015

I just added my thoughts about POST requests in #36.

@vancelopes
Copy link

Hello folks!

When I use POST (like signing up my user) on (http://haltalk.herokuapp.com/), the method you described above works good but the .then(...) is ignored later. Am I doing something wrong?

var signup = root.links['ht:signup'];            
signup.fetch(
              {
                ajax :
                  {
                    method : "POST",
                    data : {'username' : user,'password' : obj.password, 'real_name' : user + 'by IM'}
                  }
              }
            )
            .then(function(data){
              var dataPost = data; /// Pitfall: this is unreachable, but the post is made.
            });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

4 participants