Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Serve a HATEOAS-friendly root #4

Open
erik-stephens opened this issue Jun 11, 2013 · 10 comments
Open

Serve a HATEOAS-friendly root #4

erik-stephens opened this issue Jun 11, 2013 · 10 comments

Comments

@erik-stephens
Copy link

Summary

As a consumer of an API, I would like an entry point to jump into, so that I can easily get a survey of the kinds of resources & relationships that are available.

Notes

  • This is related to issue Support OPTIONS requests #3.  Where Support OPTIONS requests #3 is more about the metadata for the API, this is more about the content of the service.
  • A feature like this baked into the API could allow for generic clients - think wget or curl for API's.

Acceptance Criteria

  • A request to the root returns a HATEOAS-friendly response. The response body will include links to all available resource collections.

  • For clients requesting json content, return a list of the following form:

    [ {"name": , "url": }, ...]

  • For clients requesting html content, return a page with hyperlinks instead.

  • GET requests against collections requesting html content will return a page with a table that:

    • includes a row for each entity in the collection
    • lists each attribute as a table column
    • renders related entity as a hyperlink to the entity's url
    • renders related collections as a hyperlink to collection's url

References

@yocontra
Copy link
Member

Already on the TODO:

  • DBRefs should be changed to a {_id:"123", url:"/users/123"} format

I'm iffy on returning html content. Do you have any examples of large APIs doing this? In NodeJS I'm not sure what the performance would be converting a ~100K length JSON array to XML. Content negotiation might be better off as a plugin

Are there any standards for what should be returned on the root?

@erik-stephens
Copy link
Author

I don't know of any api's that do this. When in doubt, I think about traditional web pages & browsers. I wouldn't prioritize this. It might be cool to say your api honors HATEOAS, but probably won't make much difference at the end of the day. And I guess it would be cool if I could dive into the content of an api, but there's already decent tooling for develpers to do that.

I do think the "wget for api's" might have some merit some day. I can imagine a consumer wanting a data dump. Instead of requesting a huge payload, they could crawl the api this way which might become a standard. With proper ETag headers, it might be a more efficient way of accomplishing that.

@erik-stephens
Copy link
Author

Forgot to reply about the performance. Would paging the results alleviate your concerns?

@yocontra
Copy link
Member

How would this work with the population? Nested tables?

@erik-stephens
Copy link
Author

Not sure I understand. You referring to the optional populate request params? I was assuming that none of the generated url's would include those and that those would be discoverable via the links to the related entities and collections.

@yocontra
Copy link
Member

GET /users?populate=boss

Content-Type: text/html

How does the response look?

@yocontra
Copy link
Member

{
   "collections":[
      {
         "name":"users",
         "routes":[
            {
               "type":"collection",
               "methods":[
                  "post",
                  "get"
               ],
               "url":"/users"
            },
            {
               "type":"collection-static-method",
               "methods":[
                  "post",
                  "get"
               ],
               "url":"/users/search"
            },
            {
               "type":"single",
               "methods":[
                  "get",
                  "put",
                  "patch",
                  "delete"
               ],
               "url":"/users/:userId"
            },
            {
               "type":"single-instance-method",
               "methods":[
                  "post",
                  "get"
               ],
               "url":"/users/:userId/findWithSameName"
            },
            {
               "type":"single-with-populate",
               "methods":[
                  "get"
               ],
               "url":"/users/:userId/bestFriend"
            },
            {
               "type":"single-with-populate",
               "methods":[
                  "get"
               ],
               "url":"/users/:userId/friends"
            },
            {
               "type":"single-with-populate-many",
               "methods":[
                  "post"
               ],
               "url":"/users/:userId/friends"
            }
         ]
      }
   ]
}

How does this look for the JSON meta info for GET / and OPTIONS /? This data comes from the User model in test/fixtures/UserModel

@erik-stephens
Copy link
Author

About the HTML details, I was assuming things like populate would not be used. All those auxilliary definitions and relationships can be discovered from the entity's page. The collections page would only show the columns/attributes. Entitiy IDs would be rendered as hyperlinks to the entity page. I think this strikes a good balance between useful while not getting overly complicated to implement.

@erik-stephens
Copy link
Author

For the JSON details, I think that's looking good, although I would recommend publishing those details from the collection url (eg /users). The root can be as simple as a link to all the available collections.

@yocontra
Copy link
Member

@erik-stephens Yeah I'll split each routes meta out next for GET /:collName/_meta and OPTIONS /:collName

Top-level has a list of routes/collections and each route will have the same info as well as the schema information

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants