Skip to content

Instantly share code, notes, and snippets.

@euclio
Last active August 29, 2015 13:57
Show Gist options
  • Save euclio/9774349 to your computer and use it in GitHub Desktop.
Save euclio/9774349 to your computer and use it in GitHub Desktop.
Overview of the backend design for StudyJam

StudyJam Flask API Design

I intend this document to clarify some of the aspects of designing the backend API for StudyJam. The API design is simple (and probably incomplete). There is also no notion of authentication, which should definitely be a concern.

API Overview

A GET request to each URL will return JSON appropriate to the information requested.

Request:

GET /api/user/<int:id> HTTP/1.1

Result:

{
    "name": "Andy",
    "study_level": 3,
}

Request:

GET /api/user/<int:id>/location HTTP/1.1

Result:

{
    "latitude": 34.097890,
    "longitude": -117.712412,
}

Request:

GET /api/user/<int:id>/friends HTTP/1.1

Result:

{
    "friends": [
        {
            "id": 123,
            "name": "Mauricio",
        },
        {
            "id": 456,
            "name": "Parth",
        }
    ]
}

POSTing to any of these URLs will instead modify the data on the server.

API Implementation

To send new information to the server, we can write a simple HTML form that POSTs to the URL. Sending a POST from the phone will work the same way, so we can use the same code for each. Here's a form (Flask template) that should do the trick. Ensure that you pass in a user_id when you render the form.

<html>
<body>
  <form name="location" action="{{ url_for('get_user_location', user_id ) }}" method="post">
    <div>
      <label for="latitude">Latitude:</label>
      <input required type="text" name="latitude">
    </div>
    <div>
      <label for="longitude">Longitude:</label>
      <input required type="text" name="longitude">
    </div>
    <input type="submit" value="POST">
  </form>
</body>
</html>

When the submit button is clicked, the browser will send a post request to the appropriate URL, with the form information encoded in the request.

Request:

POST /api/user/<int:user_id>/location HTTP/1.1

latitude=34.101826&longitude=-117.712648

Result:

The server will store the new location in the user with id user_id.

What's great about Flask is that you don't have to parse any of the requests yourself. Implementing get_user_location() might look like this:

from flask import request # etc...
import json

@app.route('/api/user/<int:user_id>/location', methods=['GET', 'POST'])
def get_user_location(user_id):
    if request.method == 'POST':
        # Pull the info we need out of the request
        latitude = request.form['latitude']
        longitude = request.form['longitude']

        if latitude and longitude:
            # Now we create the part of the object that needs to be updated
            new_location = { 'latitude': latitude, 'longitude': longitude }
            # update_user_location() modifies the information in the document in storage
            update_user_location(user_id, new_location)

    # get_user_location() returns a user location object from storage
    return json.dumps(get_user_location(user_id))

Note that we can send both GET and POST requests to this URL.

Note that the <form> element has a method="post" attribute. This makes the browser encode the form information into the request. We can also make the form have method="get" instead. This will make the browser encode the information into the URL. That is, the request would look like this:

GET /api/user/<int:user_id>/location#latitude=34.101826&longitude=-117.712648 HTTP/1.1

You can access these URL parameters in Flask like so:

# Use None as a default in case there are parameters missing
latitude = request.args.get('latitude', None)
longitude = request.args.get('longitude', None)

The convention is to use POST when changing state on the server, and to use GET when you are only reading state.

Conclusion

Hopefully this helps! Let me know if if anything is unclear.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment