Classroom "rules":
Tell us about yourself:
Online development: Github account
Local development:
Local development (option 2):
A client sends an HTTP request:
GET /index.html HTTP/1.1
Host: www.example.com
The server sends back an HTTP response:
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 208
<!DOCTYPE html>
<html>
<head>
<title>Example Domain</title>
</head>
<body>
<h1>Example Domain</h1>
<p>This domain is to be used for illustrative examples in documents.</p>
</body>
</html>
A client sends an HTTP request:
GET /weather?zip=94530 HTTP/1.1
Host: api.example.com
The server sends back an HTTP response:
HTTP/1.1 200 OK
Content-Type: text/json; charset=UTF-8
Content-Length: 30
{"temperature": 70, "wind": 5}
{"temperature": 70, "wind": 5}
<weather-response>
<temperature>70</temperature>
<wind>5</wind>
</weather-response>
GET: retrieve data from a server.
Often used with query parameters.
GET /weather?zip=94530 HTTP/1.1
Host: api.example.com
POST: send data to a server.
Data is often in JSON or form-encoded.
POST /scores HTTP/1.1
Host: api.example.com
player=pamela&score=50
Try the APIs below, customizing the URLs as suggested, and share any fun findings with classmates.
Some examples:
🔑 Most of the popular APIs require you to sign up for a key so that they can track your usage and limit calls based on your payment level.
import json
import random
from flask import Flask, request
app = Flask(__name__)
@app.route('/v1/generate_name')
def generate_name():
random_name = random.choice(["Minnie", "Margaret", "Myrtle"])
result = {"name": random_name}
return json.dumps(result)
👀 Demo: https://flask-simple-api-67uuyfbgx7tlq-function-app.azurewebsites.net/v1/generate_name
👩🏼💻 Code: https://github.com/pamelafox/simple-flask-api-azure-function/blob/main/api/flask_app.py
import json
import random
from flask import Flask, request
app = Flask(__name__)
@app.route('/v2/generate_name')
def generate_name():
starts_with = request.args.get("starts_with")
names = ["Minnie", "Margaret", "Myrtle", "Noa", "Nadia"]
if starts_with:
names = [n for n in names if n.lower().startswith(starts_with)]
random_name = random.choice(names)
result = {"name": random_name}
return json.dumps(result)
👀 Demo: https://flask-simple-api-67uuyfbgx7tlq-function-app.azurewebsites.net/v2/generate_name
👩🏼💻 Code: https://github.com/pamelafox/simple-flask-api-azure-function/blob/main/api2/flask_app.py
FastAPI is a Python framework designed specifically for building HTTP APIs.
import random
import fastapi
app = fastapi.FastAPI()
@app.get("/generate_name")
async def generate_name(starts_with: str = None):
names = ["Minnie", "Margaret", "Myrtle", "Noa", "Nadia"]
if starts_with:
names = [n for n in names if n.lower().startswith(starts_with)]
random_name = random.choice(names)
return {"name": random_name}
👀 Demo: simple-fastapi-azure-function-qdqlk63tlwxuw-function-app.azurewebsites.net/docs
👩🏼💻 Code: github.com/pamelafox/simple-fastapi-azure-function/blob/main/api/main.py
1. Put code in main.py
2. Install requirements
pip install fastapi
pip install "uvicorn[standard]"
3. Run the server
uvicorn main:app --reload
4. Try the API and docs
http://127.0.0.1:8000/generate_name
http://127.0.0.1:8000/docs
Starting from this repo:
github.com/pamelafox/simple-fastapi-azure-function
ends_with
,
includes
, or length
.
🙋🏼♀️🙋🏾♀️🙋🏽♀️ Let us know if you need any help! 🙋🏻♀️🙋🏽♂️🙋🏿♀️
A parameterized API based on a sklearn
model.
model = joblib.load(f"{os.path.dirname(os.path.realpath(__file__))}/model.pkl")
@app.get("/model_predict")
async def model_predict(
years_code: int,
years_code_pro: int,
ed_level: categories.EdLevel,
main_branch: categories.MainBranch,
country: categories.Country):
X_new = numpy.array([[years_code, years_code_pro, ed_level.value, main_branch.value, country.value]])
result = model.predict(X_new)
return {"prediction": result[0]}
👀 Demo: salary-model2-sibqf23ha7ib2-function-app.azurewebsites.net/docs
Cloud | Azure | |||
---|---|---|---|---|
Environment | Containers | PaaS | ||
Azure Kubernetes Service | Container Management | Azure App Service | Serverless | |
Azure Container Apps | Azure Functions |
For FastAPI, App Service or Functions are good choices.
Using the Azure Dev CLI:
An Azure API Management Policy provides all the additional features of a public API.
Starting from this repo (or your fork):
github.com/pamelafox/simple-fastapi-azure-function
azd up
. If prompted, login to your Azure account.
azd down
to un-deploy the app (so that you don't waste cloud resources unnecessarily).
🙋🏼♀️🙋🏾♀️🙋🏽♀️ Let us know if you need any help! 🙋🏻♀️🙋🏽♂️🙋🏿♀️
def main(req: func.HttpRequest) -> func.HttpResponse:
text = get_param(req, 'text')
size = get_param(req, 'size', 80)
bgcolor = get_param(req, 'bgcolor', 'black')
fontcolor = get_param(req, 'fontcolor', 'white')
if text:
img = write_icon(text, size=size, bgcolor=bgcolor, fontcolor=fontcolor)
img_byte_arr = io.BytesIO()
img.save(img_byte_arr, format='PNG')
img_byte_arr = img_byte_arr.getvalue()
return func.HttpResponse(img_byte_arr, mimetype='image/png')
else:
return func.HttpResponse(
"Text must be specified",
status_code=400
)
👀 Demo: pamelafox.github.io/icon-writer-website/
👩🏼💻 Code: github.com/pamelafox/icon-writer-function/blob/main/IconWriter/__init__.py
If your API needs to support the creation of data, then requests should go over HTTP POST instead.
How POST requests are specified in FastAPI:
from typing import Union
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item
Learn more in FastAPI docs
If your site uses a DB and the Django framework, the Django REST framework can be used to create CRUD APIs.
from django.urls import path, include
from django.contrib.auth.models import User
from rest_framework import routers, serializers, viewsets
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ['url', 'username', 'email', 'is_staff']
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]