4

I am attempting to construct a web app in which the back end is a complete RESTful web service. I.e. the models (business logic) would be completely accessible via HTTP. For example:

GET    /api/users/
GET    /api/users/1
POST   /api/users
PUT    /api/users/1
DELETE /api/users/1

Whats the proper way to provide more methods that aren't CRUD (verbs/actions)? Is this considered more of a RPC-api domain? How would one properly design the RPC api to run on top of the RESTful api?

For example, how would I elegantly implement a forgot password method for a user.

POST (?) /api/users/1/forgot

The application (Controllers/View) would then use a https requests (HMVC like) to access the models and methods. What would be the best for authentication? OAuth, Basic Auth over HTTPs?

Although this is "best practice" for scalability later on, am I over engineering this task? Is it best to just follow the typical MVC model and provide a very basic API?

This question has been mostly inspired by ASP.NET's MVC 4 (WebAPI) and a NodeJS module https://github.com/marak/webservice.js

Thanks in advance

tereško
  • 58,060
  • 25
  • 98
  • 150
user1236971
  • 197
  • 2
  • 11

1 Answers1

1

I recently started learning REST, and when developing a new web service I think you're doing the right thing to consider it.

You are correct in your assumptions about the custom verbs. REST acknowledges that some actions need to be handled in a different way, and custom verbs don't violate the requirements. You should use POST when communicating with the server, but the verbs are normally written in imperative. Instead of forgot, I'd probably use remind or something similar. I.e., you should give instructions on what to do, rather than describe what happened without clearly indicating what you expect as a result.

Furthermore, the preferred way to construct the service is to include api into the domain name, and drop it from the path. I'd write your particular example like this:

POST /users/1/remind HTTP/1.1
Host: api.myservice.example.com

Session handling in REST is a bit tricky. The cleanest way of doing it would probably be to authenticate with username and password on every single request, using Basic access authentication. However, I believe that it's rarely done like that. You should read this question (and its accepted answer): OAuth's tokens and sessions in REST

EDIT: I'd also drop the trailing forward slash in the GET request in your example. If the service is truly RESTful, then the resource is not supposed to be accessibly from both /users/ and /users. A particular resource should have one and only one URL pointing to it. A URL with a trailing slash is actually distinct from one without. REST promotes dropping it, and a RESTful web service should not accept both (which in the case of GET means responding with 200 OK), although it may redirect from one to the other. Otherwise, it might lead to confusion about the proper URL, duplicate caching, weeping and gnashing of teeth. :)

EDIT 2: In RESTful Web Services by Richardson & Ruby you're discouraged from putting the new verb in the path. Instead, you could append something like ?_method=remind. It's up to you which one you choose, but please remember that you're not supposed to handle these requests with GET, regardless of what you choose. A GET must not change the resource, and should not cause side effects if the user browses back and forth in the history. Otherwise, you might end up resending the password several times. Use POST instead.

Community
  • 1
  • 1
Anders Sjöqvist
  • 3,372
  • 4
  • 21
  • 22
  • Thanks for your reply Anders. Do you think it is best to build my application with a typical MVC approach at first (models communicate directly with the database) and then worry about making the api.mysite.com later? The models would then be modified to communicate directly with the api instead of the database. It would probably be ideal to abstract my models enough so that no session / authentication is handled in the models, correct? – user1236971 May 21 '12 at 19:59
  • @user1236971 I'm not an expert, but here's how I see it: Developing the model separately sounds a bit like contradiction in terms. Your model should offer the data in a structured way, hiding as much of the underlying implementation as possible. It should also handle some basic security and hide things that shouldn't be exposed. For example, you should be able to alter or verify a password, but never retrieve it (even as a hash). This is more or less exactly what the API should do, and you shouldn't duplicate your code. Your model *is* your API, although you might skip the JSON conversion. – Anders Sjöqvist May 22 '12 at 07:42
  • @user1236971 Oh, and by the way, I'm not sure what you mean with abstracting the models so that they don't deal with authentication. Where are you planning to do that? I would try to implement the model so that a mistake in the view or controller would never be able to corrupt data, and that probably involves doing some permissions checking. But like I said, session management is tricky, and I don't know the best practices. I'm having problems with the same things. – Anders Sjöqvist May 22 '12 at 07:46