Backbone.js restful json API design

2019-04-16 05:23发布

问题:

I have the following functionality at my API and I strumbled upon a few questions:

  1. POST /user (requires fullName, email, password) will create a new user, if the user has been created an unique activation ID is generated and a link to activate the account is send through mail to the user.

  2. PUT /user (requires id, email) will activate the user.

Once the user has activated it's account, it can login.

  1. POST /session (requires email, password) and logs in the user.
  2. GET /session will look at the cookie session id and return user info if auth.
  3. DELETE /session logs the user out.

Once the user is logged in, he is asked to submit their interests (just a HTML textarea) and they can submit a description about their account too (Location, gender, etc but it is all optional so also an HTML textarea just like Twitter account description)

Now my question is:

As you can see 2. PUT /user will activate the user, but how would I handle the submit interests and account description in a proper restful design?

Should I look at the point where at my backend server PUT /user will come in and detect the fields that where submitted?

Or would it make more sence to create a separated PUT /user/activate and PUT /user/interests.

Once this is finished, I want to expand it with restore password, also this would be a PUT /user wouldn't the field detection at the server side will get kinda messy?

Now about backbone, this is my session model:

var Session = Backbone.Model.extend({
  url: '/session'
});

var session = new Session();
session.fetch(); // Get the user authentication of the backend server.

my user model:

var User = Backbone.Model.extend({
  url: '/user'
});

function signup(fullName, email, password){
  var user = new User();
  user.save({
    fullName: fullName,
    email: email,
    password: password
  });
};

function activate(id, activationId){
  var user = new User();
  user.save({
    id: id,
    activationId: activationId
  });
};

// Possibility...?
function submitInterests(id, interests){
  var user = new User(url: '/user/interests/');
  user.save({
    id: id,
    activationid: activationId
  });
}

Thank you for reading.

回答1:

A rule of thumb in RESTful world is:

Verbs down, nouns up.

That's because the magic 4 [GET, POST, PUT, DELETE] should be enough for all actions: no /users/activate / /user/edit stuff around.

While making a PUT over the whole /users for activation may seem legit, so would be making all the requests to /root and passing "entity = users, id = 3, ..." and so on.

I advice you to use /entityname for the collection [where you can POST to create a new one], then /entityname/:id in order to refer to a single entity [in this case, a single user].

Now you can make a PUT on /users/123 to accomplish whatever you need.


Of course you can nest resources:

/users/:id/interests

This is the route for all interests of :id-th user - you can issue a GET over it to retrieve them all, or a POST to add an element to the list, a PUT to set all the list from scratch.


One last thought about your session resource: a true RESTful service should be *stateless, i.e. it should not rely on session. Authorization has to be made on every request, see HTTP Basic Auth, though you can come with a session sometimes.

To be consistent to your schema, you can define a /user/:id/sessions resource where you can POST in order to make a new login, so you can keep track of user accesses.