Skip to content

Add first draft of OEP-13 (API conventions) - #36

Merged
andy-armstrong merged 3 commits into
masterfrom
efagin/oep-13-api-conventions
Jul 25, 2017
Merged

Add first draft of OEP-13 (API conventions)#36
andy-armstrong merged 3 commits into
masterfrom
efagin/oep-13-api-conventions

Conversation

@efagin

@efagin efagin commented Dec 29, 2016

Copy link
Copy Markdown
Contributor

Supercedes https://openedx.atlassian.net/wiki/display/AC/edX+REST+API+Conventions (the content is virtually identical). A Best Practices OEP is a more reasonable home for this content and I'd like changes to our conventions to be captured more formally (i.e. through PRs instead of wiki comment threads).

@nasthagiri, would you mind acting as arbiter for this OEP? I can't imagine there are any issues but you're familiar enough with the original source wiki. Once this gets merged, I'm going to update the original wiki page to just link to the OEP.

@efagin
efagin force-pushed the efagin/oep-13-api-conventions branch from 41871b6 to 6abc23a Compare December 29, 2016 19:54

@andy-armstrong andy-armstrong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@efagin converting this to an OEP was a great idea, thanks. I'm out of the loop on our current thinking around API development so I look forward to hearing how others react. I have a few minor comments that I hope are helpful.

Comment thread oeps/oep-0013.rst Outdated
Motivation
==========

The Open edX platform contains many extension points for third-party developers that wish to integrate with the platform. We wish to approach a standard methodology for API design in order to give developers more consistency in their API client design, and to make our endpoint behaviors more predictable.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: we settled on wrapping lines at 80 characters in OEPs.

From @cpennington:

I tend to prefer wrapped lines in the raw text, simply because it's easier to read in an editor (and in the email summaries that github sends). Github wraps them nicely in the diff, but in this case I lean towards optimizing towards the lowest common denominator.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO it would be helpful to have a description of the API gateway and how (if?) it affects the development of APIs.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I just updated the doc with 80-char line wrapping.

Comment thread oeps/oep-0013.rst Outdated

**Discoverable**

Support `HATEOAS <https://en.wikipedia.org/wiki/HATEOAS>`_ where possible. This allows us to change our URLs without needing to worry about updating the mobile apps if the app discovers its URLs from a base URL.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we using HATEOAS in our newer APIs? I remember that @nasthagiri mentioned there were reasons why mobile doesn't use it. Is this still the recommendation? Does it change with the API gateway?

Comment thread oeps/oep-0013.rst Outdated

*Must*: edX resource identifiers

- Users should be referenced by username

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this where we landed at the last arch lunch?

Comment thread oeps/oep-0013.rst Outdated

- ``expand`` parameter - Allow clients to request including data from other resources using the expand parameter as explained further in the Expansion section.

.. todo: link to expansion section

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't forget to provide this link

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, done.

Comment thread oeps/oep-0013.rst Outdated

Use the appropriate value amongst the following (or document in the code why an exception is needed)

200 - OK

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: this section shows up as quoted on the rendered page:

https://github.com/edx/open-edx-proposals/blob/6abc23aed18fe98f0270934363d744fc3ef2cdec/oeps/oep-0013.rst

I'd probably also bold the status codes themselves.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Comment thread oeps/oep-0013.rst Outdated
{
"error_code": "course_not_started" # a short string that the client can rely upon for handling different errors
"developer_message" : "Verbose, plain language description of the problem for the app developer with hints about how to fix it.",
"user_message":"Pass this message on to the app user if needed.",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: missing a space between the key and value.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

Comment thread oeps/oep-0013.rst Outdated
Documentation
-------------

Work with the Docs team to update the `edX platform API documentation <http://edx-platform-api.readthedocs.org/en/latest/>`_.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this document is still being updated, and it if it is then it is not the docs team that does it.

Comment thread oeps/oep-0013.rst Outdated
- *Must*: Additive changes to the contract of the API, or the results, should not bump the major version, unless those changes are non-optional, and break existing contracts with the API.


**Future considerations**

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe pull this out to its own top level section? I thought there was a standard Future Directions in OEP-1 but I don't see one.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed it entirely, we should keep speculative things out of OEPs and just add content when it's well-formed.

Comment thread oeps/oep-0013.rst Outdated
Authentication
--------------

By convention, our REST APIs support the following two authentication schemes:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be useful to mention JWT tokens here.

Comment thread oeps/oep-0013.rst Outdated
Reference Implementation
========================

There are a number of existing APIs that you can crib from, for example:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to update this to include some of the newer APIs, such as those for course discovery.

Comment thread oeps/oep-0013.rst Outdated
- ``fields`` parameter - Allow clients to specify/filter the fields in the response by supporting a fields parameter as a comma-delimited list. ::

/dogs?fields=name,color,location
/dogs?fields=title,media:group(media:thumbnail)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. I don't think we have implemented the xpathesque type of field filtering that Google has.
  2. If we think we want to use this, for mobile or otherwise, we should choose a solution and duplicate and/or link to docs that provide details. For example, Google's docs (drive api) for partial responses.

Comment thread oeps/oep-0013.rst Outdated

**Format**

Use `Swagger <http://swagger.io/specification/>`_ to generate API documentation where possible.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of our code seems to be using Django REST Swagger for Swagger documentation of DRF. Maybe this should be documented as our best practice, given that REST Framework Docs (which I think is documented below, was deprecated in favor of Django REST Swagger, both by the same creator. This is described on the DRF site for documenting APIs.

@efagin

efagin commented Jan 3, 2017

Copy link
Copy Markdown
Contributor Author

@andy-armstrong @robrap thanks for the early feedback! Many of your comments question the content itself. Since all I did was just port the existing wiki page over here, I'm surprised that there's so much in this document that you feel requires major editing. (This, on its own, is a good reason to move to OEP.)

Do you think we should broaden the scope of this OEP to actually go and revise these best practices? I had started this just figuring I'd do a quick port and merge, and then we could modify later, but if you think we should just do it all now, then I'll allocate more of my time to updating these best practices now.

@andy-armstrong

Copy link
Copy Markdown
Contributor

@efagin IMO it would be great if you could allocate the extra time to revise the recommendations. It seems like a good opportunity to make this up-to-date, and then we can all be on the same page going forward.

@efagin

efagin commented Jan 3, 2017

Copy link
Copy Markdown
Contributor Author

@andy-armstrong OK, I'll do that. This OEP will definitely require more effort before it's ready to merge, and please continue to provide feedback.

Comment thread oeps/oep-0013.rst Outdated
multiple PATCH styles in any given API, should this become desirable, without
breaking existing clients.

URL parameters

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to describe how boolean query parameters should be handled. My preference is that they should be passed as true/false, but I'm open to other options.

I mention this because I dislike using 0/1 for boolean values, which I commented as such on this PR: https://github.com/edx/edx-platform/pull/14204

Comment thread oeps/oep-0013.rst Outdated
Documentation
-------------

Work with the Docs team to update the `edX platform API documentation

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to revisit our documentation approach for APIs given the changes in the doc team. I'm not sure if this OEP is the best place to describe processes, but it would be good to lay out what is expected of documentation for a new API:

  • the API developer should use Swagger to auto-generate documentation (as mentioned below)
  • the developer is in charge of getting this documentation published (but how?)
  • how does an API get to be part of the API Gateway and have its documentation made available there too?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the link on this line is for edx-platform only, and is for a document that does not appear to be actively maintained. Also, this OEP needs to be for the community as a whole, so the language about "Work with the Docs team" doesn't generalize even if there were a docs team to work with.

Comment thread oeps/oep-0013.rst Outdated

The query parameters are as follows:

- ``page`` - the page of results (zero indexed)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why zero-indexed? I can't think of any of our own APIs that implement this. If we want to see this, and the other conventions (e.g. num_pages), implemented we should make it easy to do so by creating a pagination class in https://github.com/edx/edx-drf-extensions.

Comment thread oeps/oep-0013.rst Outdated

- ``page`` - the page of results (zero indexed)
- ``page_size`` - the number of results to return per page
- ``sort_order`` - a string indicating the desired order (no direction

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorting/ordering should be separate from pagination.

I would prefer we advocate ordering on explicit fields as it is clear to the client what is being done. Passing sort_order=asc is quite ambiguous.

Comment thread oeps/oep-0013.rst Outdated
e.g. https://courses.edx.org/api/user/v1/accounts/AndyA

See the `DRF documentation
<http://tomchristie.github.io/rest-framework-2-docs/topics/documenting-your-api>`_

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use DRF 3 everywhere. This is a more relevant URL: http://www.django-rest-framework.org/topics/documenting-your-api/

Comment thread oeps/oep-0013.rst Outdated

GET /api/enrollment/v1/enrollment/{user_id},{course_id}

**Response Values**

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not necessary when using Swagger. Also, docstrings like these tend to grow stale as APIs evolve since I don't necessarily have to touch a view to modify a serializer.

Comment thread oeps/oep-0013.rst Outdated

**Simple**

Keep the top-leveI resources clear and simple - focusing on what the client is

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo on "top-level"

Comment thread oeps/oep-0013.rst Outdated
**Prevent information leakage**

**Must**: Use 404 instead of 403 when the actual existence would be leaking
information that we don't want

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An example or two might be good here.

Comment thread oeps/oep-0013.rst Outdated
The query parameters are as follows:

- ``page`` - the page of results (zero indexed)
- ``page_size`` - the number of results to return per page

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Developers should explicitly set limits on this parameter.

Comment thread oeps/oep-0013.rst Outdated

We use the conventions established by `DRF
<http://www.django-rest-framework.org/api-guide/pagination/#pagenumberpagination>`_,
with some extra fields:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a note here about how certain very large collections (e.g. users, enrollments) cannot be effectively paged through with DRF's default pagination class? The choices then are to either use CursorPagination, a custom pagination class, or to simply cap the result set in some way:

  • "Returning the first 500 results that match your query."
  • "You have to be more specific before I give you any data."
  • "No, you may not crawl our entire enrollment database by making half a million sequential requests, please don't try that."

@efagin

efagin commented Jul 25, 2017

Copy link
Copy Markdown
Contributor Author

I know this has been idle for some time now. Part of the issue is the recurring theme that "best practice" OEPs are difficult to maintain and approve. For now, we've made the conscious decision at edX to keep Best Practice content in the wiki and allow freeform editing as practices evolve. Instead of leaving this open indefinitely, I'm going to withdraw this OEP, remove content, and merge the PR as-is. I will NOT squash commits unless this is desired - might be nice to have the commit history for archival purposes.

@andy-armstrong would you mind acting as Arbiter here?

@andy-armstrong andy-armstrong left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 makes sense to me. As Arbiter, I'll go ahead and merge this now.

@andy-armstrong
andy-armstrong merged commit 4929541 into master Jul 25, 2017
@andy-armstrong
andy-armstrong deleted the efagin/oep-13-api-conventions branch July 25, 2017 20:06
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

Successfully merging this pull request may close these issues.

5 participants