1

after years of absence from web programming I now start to write a new web application from scratch. I learned the ropes of REST and found some helfful presentations and webinars about good and bad "URI styles". But all these tutorials seems to assume that there are only ressources that can be mapped to entitities that persist in a database. If one needs to GET a HTML (user-friendly) version of something, then the prevalent answer is to use content negiotation via HTTP header fields. The ultimate goal seems to have only URIs that follow the REST paradigm.

But what is the "correct" way to display web pages that cannot be mapped to an entity but are required anyway?

Perhaps I make an example to clarify what I mean. Assume we have a collection Persons and the entity Person.

Then we have

  • POST /Persons/ to create a new person in the collection
  • DELETE /Person/{id}/ to delete the person
  • PUT /Person/{id}/ to modifiy the person (yes, I know it can also mean to create one)
  • GET /Persons/ to get the list of all persons
  • GET /Person/{id}/ to get an individual person
  • and so on

With respect to the GET operations I generally found the advice to use the Accept and X-Requested-With header fields of the request to create a response that either returns the "bare" person object in a computer-readable respresentation (i.e. JSON, XML, etc.) or that returns a fully-fledged web page for a browser.

But what is about the PUT operation. Ultimately, this operation will send a bare person object (i.e. JSON, XLM) that is going to be created, but before this step I need to collect the data from the user. This means I need some empty web form that is just "eye-candy" for the human user. Of course, I could habe something like GET /newPersonForm/ but it seems that this contradict the REST philosophy, because /newPersonForm/ is an URI that only points to some user interface element.

At the moment I see to options:

  1. Use the same name space for both kind of URIs:

    • POST /Persons/ --> REST api
    • DELETE /Person/{id}/ --> REST api
    • PUT /Persons/{id}/ --> REST api
    • GET /Persons/ --> REST api or UI (after content negiotation)
    • GET /Person/{id}/ --> REST api or UI (after content negiotation)
    • GET /Person/creationForm --> non-REST, pure UI
    • GET /aboutus --> non-REST, pure UI, additional company information
  2. Make separate name spaces:

    • /api/... --> contains everything for REST
    • /ui/... --> contains html web pages

With the first approach I feel that it is somebit "unclean". Although the second approach seems cleaner, I see two problems. Firstly, if one follows this approach cleanly, one gets much double URIs, because one dispense with content negiotation and has an UI web page for every REST function. I have GET /api/Person/{id}/ to return a JSON object and GET /ui/Person/{id} to return a browser version. Secondly, I feel that this approach contradict REST philosophy because search egines and web crawlers cannot understand the structure of the site.

Any recommendations what the best practice is?

user2690527
  • 1,211
  • 13
  • 31

1 Answers1

1

First of all, let's get a few misconceptions out of the way.

  1. Anything for which you have semantics identifiable by an URI is a resource.

  2. The HTTP methods don't map to CRUD operations like that. Read this answer for more on that. I recommend you read it before continuing reading this answer. This one is probably going to be helpful too.

  3. There's no such thing as an URI that follows the REST paradigm. The only constraints REST imposes on URIs is that they must identify one and only one resource, and they must be treated as atomic identifiers. The semantics of the URI is irrelevant, although obviously you should design URIs that make sense for the developers and users.

As you already figured out, the correct way to return an user-friendly representation of something is through negotiation via the Accept header. It doesn't matter if it's not something that maps to a database. That's an implementation detail only the server knows, and that's what REST is about. When you retrieve something from a REST API, it doesn't matter if it's coming from the application server, from a cache somewhere, from a static file served by Amazon S3, or even an FTP link. The client should simply follow links, like when you click a link on a webpage and you don't care where the result comes from.

Both options you present are valid, but that has nothing to do with REST. Separating them in api and ui is a nice way to organize things for you, but what really matters to REST is how the client obtains those links. If they are implementing clients by reading those URIs in documentation and filling up values, that's not REST.

Think about it from a web browsing perspective. How do you reach that /newPersonForm html page? You followed a link somewhere else that had a label telling you to click on it to create a new Person. If you are the one clicking, it doesn't matter if it's /newPersonForm or /forms/newperson or simply /persons. REST works in the exact same way.

Community
  • 1
  • 1
Pedro Werneck
  • 38,032
  • 6
  • 53
  • 74
  • I read both links. But I did not find where I used a wrong mapping of HTTP methods to CRUD operations. The only new information to me is that PUSH can be used as a "fallback" method for anything because it is has no predetermined standarized semantic. Anyway, I decided to go for option 1 in order to avoid too much double URIs and will use "GET /person/new" to get an empty form. It best matches to "GET /person/{id}" which returns the same form, but with user data. – user2690527 Oct 31 '14 at 21:33