(closing) Python Framework FastAPI: A better API framework than Flask and Tornada

Keywords: Python Docker Nginx Session

0

Preface


Shared them separately the other day (Introduction) A brief analysis of the Python web framework FastAPI - an API framework with higher performance than Flask and Tornada and (Advanced) Python web Framework FastAPI - A better API framework than Flask and Tornada .Today, we welcome you to the end of the FastAPI series, which is a supplement to and expansion of the previous articles.

Of course, these functions also play an extremely important role in the actual development.




1

Use of Middleware


Flask has hook functions that decorate certain methods and add specific functionality in some global or non-global situations.


There is also something like the hook function in the FastAPI, the middleware Middleware.



Calculate callback time


# -*- coding: UTF-8 -*-
import time
from fastapi import FastAPI
from starlette.requests import Request

app = FastAPI()


@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    start_time = time.time()
    response = await call_next(request)
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    print(response.headers)
    return response


@app.get("/")
async def main():
    return {"message""Hello World"}


if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)



Request redirection Middleware


from fastapi import FastAPI
from starlette.middleware.httpsredirect import HTTPSRedirectMiddleware

app = FastAPI()

app.add_middleware(HTTPSRedirectMiddleware)

# Redirected to 301
@app.get("/")
async def main():
    return {"message""Hello World"}



Authorization allows Host access to the list (supports wildcard matching)


from fastapi import FastAPI
from starlette.middleware.trustedhost import TrustedHostMiddleware

app = FastAPI()

app.add_middleware(
    TrustedHostMiddleware, allowed_hosts=["example.com""*.example.com"]
)


@app.get("/")
async def main():
    return {"message""Hello World"}



Cross-domain Resource Sharing


from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware

app = FastAPI()

#List of domain names that allow cross-domain requests (inconsistent ports are also considered different domain names)
origins = [
    "https://gzky.live",
    "https://google.com",
    "http://localhost:5000",
    "http://localhost:8000",
]

# Wildcard matching, allowing domain names and methods
app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,   
    allow_credentials=True, 
    allow_methods=["*"],   
    allow_headers=["*"],   
)


In front-end ajax requests, cross-domain issues should be considered when external links occur. If cross-domain is not allowed, the browser will automatically error and cross-domain resource security issues will occur.


So middleware is still used in a wide range of scenarios, such as crawls, which sometimes result in 301,302 Url requests when crawling the whole site.A redirection status code like this might be the redirection that the site administrator made when he set up the domain name (secondary domain name) not in the Host Access List. Of course, if you are also the site administrator, you can also do some anti-crawling based on the middleware.


More middleware references https://fastapi.tiangolo.com/advanced/middleware




2

BackgroundTasks

Create asynchronous task functions and use the async or normal def functions to call back-end functions.


send message


# -*- coding: UTF-8 -*-
from fastapi import BackgroundTasks, Depends, FastAPI

app = FastAPI()


def write_log(message: str):
    with open("log.txt", mode="a"as log:
        log.write(message)


def get_query(background_tasks: BackgroundTasks, q: str = None):
    if q:
        message = f"found query: {q}\n"
        background_tasks.add_task(write_log, message)
    return q


@app.post("/send-notification/{email}")
async def send_notification(
    email: str, background_tasks: BackgroundTasks, q: str = Depends(get_query)
)
:

    message = f"message to {email}\n"
    background_tasks.add_task(write_log, message)
    return {"message""Message sent"}


The method is extremely simple, and there's no more bullshit. write_log is called as a task method, first the method name, then the parameter.



3

Custom Response Status Code


In some special scenarios we need to define the return status code ourselves


from fastapi import FastAPI
from starlette import status

app = FastAPI()

# 201
@app.get("/201/", status_code=status.HTTP_201_CREATED)
async def item201():
    return {"httpStatus"201}

# 302
@app.get("/302/", status_code=status.HTTP_302_FOUND)
async def items302():
    return {"httpStatus"302}

# 404
@app.get("/404/", status_code=status.HTTP_404_NOT_FOUND)
async def items404():
    return {"httpStatus"404}

# 500
@app.get("/500/", status_code=status.HTTP_500_INTERNAL_SERVER_ERROR)
async def items500():
    return {"httpStatus"500}


if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)



That's interesting, imagine someone wrote this code


async def getHtml(self, url, session):
    
try:
        
async with session.get(url, headers=self.headers, timeout=60, verify_ssl=Falseas resp:
            
if resp.status in [200201]:
                data = 
await resp.text()
                
return data
    
except Exception as e:
        print(e)

        
pass


Interestingly, then, this function to get the Html source code will use the Http status code to determine if it is returning normally.So if, according to the above writing, I return a status code of 404 or 304 directly, but the response data is normal, won't the crawler be able to crawl anything?So hey hey you understand!!



4

About deployment


Deploying FastAPI applications is relatively easy


Uvicorn 


FastAPI documentation recommends using Uvicorn to deploy applications (followed by hypercorn), which is a lightweight and efficient Web server framework based on asyncio (only supports Python versions 3.5.3 and above)



install


pip install uvicorn


Startup mode


uvicorn main:app --reload --host 0.0.0.0 --port 8000



Gunicorn


If you still like to deploy your project with Gunicorn, see below


install


pip install gunicorn


Startup mode


gunicorn -w 4 -b 0.0.0.0:5000  manage:app -D



Docker Deployment


The advantage of deploying an application with Docker is that you don't need to set up a specific running environment (in fact, the docker is pulling for you), you can build a FastAPI mirror through the Dockerfile, launch the Docker container, and easily access the application you deploy through port mapping.


Nginx

Hang up a layer of Nginx services based on Uvicorn/Gunicorn + FastAPI and a website will be ready to go online. In fact, using Uvicorn or Gunicorn directly is also OK, but Nginx can make your website look more like a website.



Posted by stezz on Thu, 16 Apr 2020 11:21:32 -0700