4

I am building a (RESTful) api (using HTTP) that I want to use with javascript.

I find my self writing stuff in javascript like

function getPost(id)
{
    $.getJSON("/api/post/" + id, function(data){
        // Success!
    });
}

There must be a smarter way than hardcoding the api in javascript, maybe something like querying the api itself for how the getPost url should look like?

function getApiPostUrl()
{
    $.getJSON("/api/getpost/");
}

returning something like

url: "/api/post/:id"

Which can be parsed by javascript to obtain the url for actually getting the post with id=:id. I like this approach.

Is a standard way of doing this? I am looking for a good approach so I don't have to invent it all, if there already exists a good solution.

kasperhj
  • 10,052
  • 21
  • 63
  • 106

3 Answers3

2

Well, per definition, a RESTful API shall contain the full URI - a Resource Identifier, and not only the resource's path. Thus your question is more a question on how you're designing your whole API.

So, for example, your API could contain a http://fqdn/api/posts that contains a list of all the posts within your site, e.g.:

[ "http://fqdn/api/posts/1",
  "http://fqdn/api/posts/2",
  "http://fqdn/api/posts/3" ]

and then your javascript only iterates over the values within the list, never needing to craft the path for each resource. You only need to have one known entry point. This is the HATEOAS concept, that uses hyperlinks as API to identifies states of an application.

All in all, it's a good idea to thoroughly think your application (you can use UML tools like the state machine or sequence diagrams..) so that you can cover all your use cases with a simple yet efficient set of sequences defining your API. Then for each sequence, it's a good idea to have a single first state, and you can have a single first step linking to all the sequences.

zmo
  • 24,463
  • 4
  • 54
  • 90
  • 1
    Or you can fetch the posts on server side in a different representation. Does not really matter... What matters, that you should never build IRIs on client side. – inf3rno Sep 02 '14 at 09:28
  • I understand, but wouldn't it be a good idea to have a layer on top of the actual API, that can be queried for resource identifier such that the top layer APIcan be implemented in javascript and doesn't have to change if the underlying RESTful API changes? – kasperhj Sep 02 '14 at 09:49
  • well, you can always create a javascript library that implements the API in a more traditional procedural way which would then work as that encapsulation layer. But that does not change the fact that it's a better idea to follow the RESTful recommendation when building an API. – zmo Sep 02 '14 at 09:52
  • @zmo I see. Can you recommend some good resources for RESTful API designing? – kasperhj Sep 02 '14 at 10:07
  • sadly, I don't have some "good" resources for REST APIs. Though, if you can find an access to ACM, you can refer yourself to the [research article](http://dl.acm.org/citation.cfm?doid=514183.514185) that set ground for it. If you google for *RESTful Design tutorial*, you'll also find plenty of articles on the matter, and the wikipedia page is not bad at all. Though, if you find good articles, don't hesitate to share them as comments, I'll update the article, or I could even consider changing it to community wiki. – zmo Sep 03 '14 at 09:24
1

Yes, there are quite a few standard ways of doing this. What you want to look for is "hypermedia APIs" - that is, APIs with embedded hypermedia elements such as link templates like yours, but also plain links and even more advanced actions (forms for APIs).

Here is an example representation using Mason to embed a link template in a response:

{
  id: 1234,
  title: "This is issue no. 1",
  "@link-templates": {
    "is:issue-query": {
      "template": "http://issue-tracker.org/mason-demo/issues-query?text={text}&severity={severity}&project={pid}",
      "title": "Search for issues",
      "description": "This is a simple search that do not check attachments.",
      "parameters": [
        {
          "name": "text",
          "description": "Substring search for text in title and description"
        },
        {
          "name": "severity",
          "description": "Issue severity (exact value, 1..5)"
        },
        {
          "name": "pid",
          "description": "Project ID"
        }
      ]
    }
  }
}

The URL template format is standardized in RFC 6570.

Mason is not the only available media type for hypermedia APIs. There is also HAL, Sirene, Collection-JSON and Hydra.

And here is a discussion about the benefits of hypermedia.

Community
  • 1
  • 1
Jørn Wildt
  • 4,274
  • 1
  • 21
  • 31
  • This is indeed a solution, but it's not a RESTful one ;-) – zmo Sep 03 '14 at 09:30
  • And what do you base that argument on? – Jørn Wildt Sep 03 '14 at 09:51
  • because, the fact that you're giving a behavior within a resource deceives the purpose of the resource-orientation of the REST. I'm *not* saying this is bad API or bad design, I'm just saying this is not REST. – zmo Sep 03 '14 at 09:58
  • Then please read the REST dissertation from Fielding and this one too: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven. REST is very much about embedding behavior (hypermedia) in responses. – Jørn Wildt Sep 03 '14 at 10:41
1

Your code clearly violates the self-descriptive messages and the hypermedia as the engine of application state (abbr. HATEOAS) of the uniform interface constraint of REST.

According to HATEOAS you should send back hyperlinks, and the client should follow them, so it won't break by changes of the API. A hyperlink does not equal with an URL. It contains an URL, a HTTP method, maybe the content-type of the body, possibly input fields, etc...

According to self-descriptive messages you should add semantics to the data, the links, the input fields, etc... The client should understand that semantics and behave accordingly. So for example you can add a "create-post" API specific link relation to your hyperlink so the client will understand that it is for creation of posts. Your client should always use these kind of semantics instead of parsing the URLs.

URLs are always API specific, semantics not necessarily, so these constraints decouple the client from the API. After that the client won't break by URL changes or not even data structure changes, because it will use a standard hypermedia format (for example HAL, JSON-LD, ATOM or even HTML) and semantics (probably RDF) to parse the response body.

inf3rno
  • 24,976
  • 11
  • 115
  • 197