Browse Source

Initial commit of Flask REST api

Charlie Root 7 years ago
commit
ead17aaea1
7 changed files with 154 additions and 0 deletions
  1. 8 0
      .gitignore
  2. 4 0
      FROM.txt
  3. 7 0
      full_gunicorn.sh
  4. 82 0
      full_todo.py
  5. 16 0
      minimal.py
  6. 14 0
      requirements.txt
  7. 23 0
      todo_list.py

+ 8 - 0
.gitignore

@@ -0,0 +1,8 @@
+bin/*
+include/*
+lib/*
+lib64
+__pycache__/*
+*~
+pip-selfcheck.json
+pyvenv.cfg

+ 4 - 0
FROM.txt

@@ -0,0 +1,4 @@
+
+See:
+http://flask-restful.readthedocs.io/en/0.3.5/quickstart.html
+

+ 7 - 0
full_gunicorn.sh

@@ -0,0 +1,7 @@
+#!/bin/bash
+
+gunicorn --bind 127.0.0.1:11022 full_todo:app
+
+# For testing multiple workers
+# gunicorn --workers=5 --bind 127.0.0.1:11022 full_todo:app
+

+ 82 - 0
full_todo.py

@@ -0,0 +1,82 @@
+#!/bin/env python
+
+from flask import Flask
+from flask_restful import reqparse, abort, Api, Resource
+from flask_httpauth import HTTPBasicAuth
+
+auth = HTTPBasicAuth()
+
[email protected]_password
+def get_password(username):
+    if username == 'admin':
+        return '12345'
+    return None
+
[email protected]_handler
+def unauthorized():
+    return abort(401, message='Unauthorized access')
+
+
+app = Flask(__name__)
+api = Api(app)
+
+TODOS = {
+    'todo1': {'task': 'build an API'},
+    'todo2': {'task': '?????'},
+    'todo3': {'task': 'profit!'},
+}
+
+
+def abort_if_todo_doesnt_exist(todo_id):
+    if todo_id not in TODOS:
+        abort(404, message="Todo {} doesn't exist".format(todo_id))
+
+parser = reqparse.RequestParser()
+parser.add_argument('task')
+
+
+# Todo
+# shows a single todo item and lets you delete a todo item
+class Todo(Resource):
+    def get(self, todo_id):
+        abort_if_todo_doesnt_exist(todo_id)
+        return TODOS[todo_id]
+
+    def delete(self, todo_id):
+        abort_if_todo_doesnt_exist(todo_id)
+        del TODOS[todo_id]
+        return '', 204
+
+    @auth.login_required
+    def put(self, todo_id):
+        args = parser.parse_args()
+        t = args['task']
+        if t is None:
+            abort(400, message="I need text for the task. task=...")
+        task = {'task': args['task']}
+        TODOS[todo_id] = task
+        return task, 201
+
+
+# TodoList
+# shows a list of all todos, and lets you POST to add new tasks
+class TodoList(Resource):
+    def get(self):
+        return TODOS
+
+    def post(self):
+        args = parser.parse_args()
+        todo_id = int(max(TODOS.keys()).lstrip('todo')) + 1
+        todo_id = 'todo%i' % todo_id
+        TODOS[todo_id] = {'task': args['task']}
+        return TODOS[todo_id], 201
+
+##
+## Actually setup the Api resource routing here
+##
+api.add_resource(TodoList, '/todos')
+api.add_resource(Todo, '/todos/<todo_id>')
+
+
+if __name__ == '__main__':
+    app.run(port=11022, debug=True)

+ 16 - 0
minimal.py

@@ -0,0 +1,16 @@
+#!/bin/env python
+
+from flask import Flask
+from flask_restful import Resource, Api
+
+app = Flask(__name__)
+api = Api(app)
+
+class HelloWorld(Resource):
+    def get(self):
+        return {'hello': 'world'}
+
+api.add_resource(HelloWorld, '/')
+
+if __name__ == '__main__':
+    app.run(port=11022,debug=True)

+ 14 - 0
requirements.txt

@@ -0,0 +1,14 @@
+aniso8601==1.3.0
+click==6.7
+Flask==0.12.2
+Flask-HTTPAuth==3.2.3
+Flask-RESTful==0.3.6
+gunicorn==19.7.1
+itsdangerous==0.24
+Jinja2==2.10
+MarkupSafe==1.0
+python-dateutil==2.6.1
+pytz==2017.3
+setproctitle==1.1.10
+six==1.11.0
+Werkzeug==0.12.2

+ 23 - 0
todo_list.py

@@ -0,0 +1,23 @@
+#!/bin/env python
+
+from flask import Flask, request
+from flask_restful import Resource, Api
+
+app = Flask(__name__)
+api = Api(app)
+
+# This isn't available when run from gunicorn
+todos = {}
+
+class TodoSimple(Resource):
+    def get(self, todo_id):
+        return {todo_id: todos[todo_id]}
+    def put(self, todo_id):
+        todos[todo_id] = request.form['data']
+        return {todo_id: todos[todo_id]}
+
+api.add_resource(TodoSimple, '/<string:todo_id>')
+
+
+if __name__ == '__main__':
+    app.run(port=11022,debug=True)