Skip to content

Commit 625b853

Browse files
committed
code upload from localhost
1 parent 79f847e commit 625b853

File tree

7 files changed

+369
-2
lines changed

7 files changed

+369
-2
lines changed

README.md

+94-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,94 @@
1-
# REST-API-Example-Python-Flask-Swagger-
2-
A simple example of creating REST API using Python-Flask and Swagger.
1+
# RESTFUL API Using Python Flask and Swagger UI
2+
3+
4+
## A Brief Introduction
5+
6+
In last few years REST (REpresentational State Transfer) has been used as an architectural design for web services and web APIs. The REST architecture was originally designed to fit the HTTP protocol that the world wide web uses.
7+
Central to the concept of RESTful web services is the notion of resources. Resources are represented by URIs. The clients send requests to these URIs using the methods defined by the HTTP protocol, and possibly as a result of that the state of the affected resource changes.
8+
9+
Building RESTFUL web services with Flask is quite simple. There are many Flask extensions that help with building RESTful services with Flask. In place of a database we will use a memory structure. it woyld work when the web server that runs our application is single process and single threaded. it is just to be used as example with Flask's own development web server. one must not use this technique on a production web server, proper database either SQL or No-SQL depends on the usage setup must be used instead.
10+
11+
Moreover we have used Swagger UI that allows anyone — be it your development team or your end consumers — to visualize and interact with the API’s resources without having any of the implementation logic in place.
12+
13+
14+
## Pre-requisites
15+
16+
One must have Python installed in his local system for deploying this RESTFUL-API easily. Other than Python one must also have to install Python-Flask and its dependencies as mentioned in the requirements.txt file.
17+
18+
19+
## Running the RESTFUL-API Service
20+
21+
using nohup (no hangup)
22+
```
23+
nohup python server.py &
24+
```
25+
26+
**You can also run the RESTFUL-API via Gunicorn**
27+
28+
```
29+
gunicorn --workers 4 --access-logfile /var/tmp/gunicorn.logs --bind 0.0.0.0:5000 wsgi:app
30+
```
31+
32+
**workers = 4 (The number of worker processes. This number should generally be between 2-4 workers per core in the server.)**
33+
34+
**access-logfile = path of the file, where logs are to be saved**
35+
36+
**bind = Specify a server socket to bind.**
37+
38+
It will deploy the web service, no need of andy manual or human intervention.
39+
40+
41+
## Checking the User Interface
42+
43+
https://localhost:5000/
44+
45+
46+
# FEW ASPECTS RELATED TO RESTFUL-API
47+
48+
## Testing
49+
50+
Something that is untested is broken. Python Flask actually provides a way to test your application by exposing the Werkzeug test Client and handling the context locals for you. One can simply use a module named as PyTest for testing Flask web services and APIs
51+
A little PyTest Flask example is being written here;
52+
53+
```
54+
import pytest
55+
56+
from ex_app import my_app
57+
58+
59+
@pytest.fixture
60+
def app():
61+
app = my_app()
62+
return app
63+
64+
def test_example(client):
65+
response = client.get("/")
66+
assert response.status_code == 200
67+
68+
69+
```
70+
71+
## Security
72+
73+
For security of our RESTFUL API, we can use mulitple options, which are provide by Python-flask like Flask-JWT tokens, Flask OAuth2 libraries, Moreover one can have route authentication and authorization implemented in his web service.
74+
In short vast variety of fruitful solutions are there, it depends on scenario and infrastructure that how one must chose to secure the endpoints and routes present in web service.
75+
76+
## Scalibility
77+
78+
A three tier architecture for scaling REST API to a huge infrastructure must be useful, One must kept database and webserver at two different nodes, and in between them there should be a load balancer that will handle the bulk amount of requests coming to the API. In this all the requests must be successfully handled and your web service can be easily scaled to a bigger infra.
79+
80+
## Limitations
81+
82+
A issue you would probably face is that the server is single-threaded. This means that it will handle each request one at a time, serially. This means that if you are trying to serve more than one request, so the requests will take longer. If any given requests happens to take a long time (say, 20 seconds) then your entire application is unresponsive for that time (20 seconds). This is only the default, of course: you could bump the thread counts (or have requests be handled in other processes), which might alleviate some issues. But once again, it can still be slow under a "high" load. What is considered a "high" load will be dependent on your application and the expectations of a maximum acceptable response time.
83+
84+
Another issue is security: if you are concerned at ALL about security, then you should not use the development server. It is not ready to withstand any sort of attack.
85+
86+
Yes, you could still conceivably use it in production. And yes, I would still recommend using a "real" web server. If you don't like the idea of needing to install something like Apache or Nginx, you can still go with a solution that is still as easy as "run a python script" by using some of the WSGI Standalone servers, which can run a server that is designed to be in production with something just as simple as running python run_app.py in the command line.
87+
88+
## Documentation
89+
90+
This RESTFUL-API is written using Python-Flask, Huge, extensive and detailed documentation for flask is provided (http://flask.pocoo.org/docs/1.0/), Furthermore a very strong support is also there on multiple platform all around the web.
91+
92+
## Deployment
93+
94+
In the current scenario, Python-Flask own development web server is used to run the service. one must not use this technique on a production web server, Mulitple other web servers dedicated for running such type of service are present such as "Gunicorn" is a good example, we can also use "Apache" or "Nginx" for that. Also proper database either SQL or No-SQL depends on the usage setup must be used with the deployment.

people.py

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
from flask import make_response, abort
2+
3+
# JSON Data to serve with our API
4+
PEOPLE = {
5+
"ricky": {
6+
"fname": "ricky",
7+
"lname": "ponting",
8+
"age": "11",
9+
"favorite_color": "pink",
10+
},
11+
"chris": {
12+
"fname": "chris",
13+
"lname": "gayle",
14+
"age": "29",
15+
"favorite_color": "green",
16+
},
17+
"shane": {
18+
"fname": "shane",
19+
"lname": "warne",
20+
"age": "33",
21+
"favorite_color": "white",
22+
},
23+
}
24+
25+
26+
def get_all():
27+
return [PEOPLE[key] for key in sorted(PEOPLE.keys())]
28+
29+
30+
def get_one(fname):
31+
if fname in PEOPLE:
32+
person = PEOPLE.get(fname)
33+
else:
34+
abort(
35+
404, "Person with first name {fname} not found".format(fname=fname)
36+
)
37+
return person
38+
39+
40+
41+
def add(person):
42+
fname = person.get("fname", None)
43+
lname = person.get("lname", None)
44+
age = person.get("age", None)
45+
favorite_color = person.get("favorite_color", None)
46+
47+
if fname not in PEOPLE and fname is not None:
48+
PEOPLE[fname] = {
49+
"fname": fname,
50+
"lname": lname,
51+
"age": age,
52+
"favorite_color": favorite_color
53+
}
54+
return make_response(
55+
"Record {fname} successfully created".format(fname=fname), 201
56+
)
57+
else:
58+
abort(
59+
406,
60+
"Peron with first name {fname} already exists".format(fname=fname),
61+
)
62+
63+
64+
65+
def update(fname, person):
66+
if fname in PEOPLE:
67+
PEOPLE[fname]["fname"] = person.get("fname")
68+
PEOPLE[fname]["lname"] = person.get("lname")
69+
PEOPLE[fname]["age"] = person.get("age")
70+
PEOPLE[fname]["favorite_color"] = person.get("favorite_color")
71+
return PEOPLE[fname]
72+
else:
73+
abort(
74+
404, "Person with first name {fname} not found".format(fname=fname)
75+
)
76+
77+
78+
def delete(fname):
79+
if fname in PEOPLE:
80+
del PEOPLE[fname]
81+
return make_response(
82+
"{fname} successfully deleted".format(fname=fname), 200
83+
)
84+
else:
85+
abort(
86+
404, "Person with first name {fname} not found".format(fname=fname)
87+
)

people.pyc

2.43 KB
Binary file not shown.

server.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from flask import render_template
2+
import connexion
3+
4+
app = connexion.App(__name__, specification_dir="./")
5+
6+
app.add_api("swagger.yml")
7+
8+
@app.route("/")
9+
def home():
10+
return render_template("home.html")
11+
12+
if __name__ == "__main__":
13+
app.run()

swagger.yml

+147
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
swagger: "2.0"
2+
info:
3+
description: This is the swagger yaml file
4+
version: "1.0.0"
5+
title: Swagger REST API
6+
consumes:
7+
- application/json
8+
produces:
9+
- application/json
10+
11+
basePath: /api
12+
13+
paths:
14+
/people:
15+
get:
16+
operationId: people.get_all
17+
tags:
18+
- People
19+
summary: Read the entire list of people
20+
description: Read the list of people
21+
parameters:
22+
- name: length
23+
in: query
24+
type: integer
25+
description: Number of people to get from people
26+
required: false
27+
- name: offset
28+
in: query
29+
type: integer
30+
description: Offset from beginning of list where to start gathering people
31+
required: false
32+
responses:
33+
200:
34+
description: Successfully read people list operation
35+
schema:
36+
type: array
37+
items:
38+
properties:
39+
fname:
40+
type: string
41+
lname:
42+
type: string
43+
age:
44+
type: integer
45+
favorite_color:
46+
type: string
47+
48+
post:
49+
operationId: people.add
50+
tags:
51+
- people
52+
summary: Create a person and add it to the people list
53+
description: Create a new person in the people list
54+
parameters:
55+
- name: person
56+
in: body
57+
description: Person to create
58+
required: True
59+
schema:
60+
type: object
61+
properties:
62+
fname:
63+
type: string
64+
description: First name of person to create
65+
lname:
66+
type: string
67+
description: Last name of person to create
68+
age:
69+
type: integer
70+
description: Age of person to create
71+
favorite_color:
72+
type: string
73+
description: Favourite color of person to create
74+
responses:
75+
201:
76+
description: Successfully created person in list
77+
78+
/people/{fname}:
79+
get:
80+
operationId: people.get_one
81+
tags:
82+
- people
83+
summary: Read one person from the people list
84+
description: Read one person from the people list
85+
parameters:
86+
- name: fname
87+
in: path
88+
description: First name of the person to get from the list
89+
type: string
90+
required: True
91+
responses:
92+
200:
93+
description: Successfully read person from people list operation
94+
schema:
95+
properties:
96+
fname:
97+
type: string
98+
lname:
99+
type: string
100+
age:
101+
type: integer
102+
favorite_color:
103+
type: string
104+
105+
put:
106+
operationId: people.update
107+
tags:
108+
- people
109+
summary: Update a person in the people list
110+
description: Update a person in the people list
111+
parameters:
112+
- name: fname
113+
in: path
114+
description: First name of the person to update in the list
115+
type: string
116+
required: True
117+
- name: person
118+
in: body
119+
schema:
120+
type: object
121+
properties:
122+
fname:
123+
type: string
124+
lname:
125+
type: string
126+
age:
127+
type: integer
128+
favorite_color:
129+
type: string
130+
responses:
131+
200:
132+
description: Successfully updated person in people list
133+
134+
delete:
135+
operationId: people.delete
136+
tags:
137+
- people
138+
summary: Delete a person from the people list
139+
description: Delete a person
140+
parameters:
141+
- name: fname
142+
in: path
143+
type: string
144+
required: True
145+
responses:
146+
200:
147+
description: Successfully deleted a person from people list

templates/home.html

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<title>REST API</title>
6+
<meta charset="UTF-8">
7+
<style>
8+
body,canvas,html{padding:0;margin:0}canvas,div#main{position:absolute}div#main,div.footer{opacity:.95;background-color:#fcfcfa;z-index:10}*{box-sizing:border-box;font-family:Menlo,Monaco,Consolas,'Courier New',monospace;font-weight:300}body,html{background-color:#fcfcfa;color:#333;height:100%;overflow:hidden;width:100%}div#main{border-radius:2px;border:2px solid #4682b4;left:0;margin:auto;padding:0 15px;right:0;top:60px;width:600px}h1,p{padding:0}a{color:#4682b4;text-decoration:none}a:hover{color:#7BE}div.footer{display:block;position:fixed;bottom:0;padding:0 10px}
9+
</style>
10+
</head>
11+
12+
<body>
13+
<div id="main">
14+
15+
<h1>REST API Using Python Flask and Swagger</h1>
16+
17+
<p> >_ Move to <a href="http://localhost:5000/api/ui" target="_blank">Swagger UI</a></p><br>
18+
19+
<p> >_ All End point information on <a href="http://localhost:5000/api/swagger.json" target="_blank">Swagger JSON is here</a></p><br>
20+
21+
</div>
22+
23+
</body>
24+
</html>

wsgi.py

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from server import app
2+
3+
if __name__ == "__main__":
4+
app.run()

0 commit comments

Comments
 (0)