Search code examples
jsonresthttpcontent-negotiationhttp-accept-header

Serving HTML application pages and JSON data in REST


In a RESTful application, is it a good idea to use a "resource" URL to serve up both JSON data and a page to access the data? If not, how should I differentiate the two things?

Suppose I have a page /routes and I have a page to list all routes. Should I do this:

HTML page

GET /routes
Accept: text/html

Response:
<h1>Routes</h1>
<p>blah blah blah</p>
... <table></table>
<script>
    $.getJSON('/routes').done(insertDataIntoTable);
</script>

JSON response

GET /routes
Accept: application/json

Response:
[
    {"number": "95", "start": "Place d'Orléans", "end": "Barrhaven Centre"},
    {"number": "96", "start": "Hurdman", "end": "Kanata"},
    {"number": "97", "start": "Bayshore", "end": "Airport/Aéroport"},
    /* etc... */
]

This seems wrong because the two requests are to the same URL/URI, but return different resources (one is an application page whereas the other is data). It would seem more appropriate to serve something like this for Accept: text/html:

GET /routes
Accept: text/html

Response:
<table>
    <thead>
        <tr><th>Number</th><th>Start</th><th>End</th></tr>
    </thead>
    <tr><td>95</td><td>Place d'Orléans</td><td>Barrhaven Centre</td></tr>
    <!-- etc... -->
</table>

(Which I probably wouldn't do as it is not very useful.)

I've thought about several options:

  1. Use the HTTP Accept header as described above
  2. Use a query parameter (e.g. /routes?type=html)
  3. Use a different path for the pages (e.g. /routes for data and /pages/routes for the application)
  4. Use extensions (e.g. /routes for data and /routes.php for the application)

1 and 2 do not seem quite right. I'm not too keen on 3 even though a page is a resource itself, it doesn't exactly represent an entity in the application. Option 4 just looks plain ugly.

I've tried looking at what major sites do and all of them serve data from a different host/subdomain (examples: facebook.com / graph.facebook.com, twitter.com /api.twitter.com) and this isn't an option for me.

Any ideas? This question shouldn't be primarily opinion-based so references would be much appreciated.


Solution

  • Number 4 looks like the best option, since the HTML page is a different type of resource than the resources in the API. It seems like a good idea to separate the pages from the API resources.
    The examples from twitter and Facebook also support this approach.