(closing) Fast API for the Python framework - an API framework that performs better than Flask and Tornado - knows

0

Preface


Shared with you 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"}



Authorize Host to access lists (wildcard matching is supported)


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 crawling, which sometimes results in 301,302 Url requests when crawling the whole site.Such a redirection status code, it is possible that the site administrator set the domain name (secondary domain name) is not in the Host access list and made the redirection processing, of course, if you are also the site administrator, you can also do some anti-crawling measures based on the middleware.


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




2

BackgroundTasks

Create an asynchronous task function that calls back-end functions using async or the normal def function.


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"}


It's extremely simple to use, so there's no more fuss. 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=False) as resp:
            if resp.status in [200, 201]:
                data = await resp.text()
                return data
    except Exception as e:
        print(e)
        pass


So it's interesting that this function that gets the Html source determines whether it returns normally based on the Http status code.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


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


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 it for you), you can build a FastAPI image through 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 the Uvicorn/Gunicorn + FastAPI and a website will be ready to go online. In fact, it's okay to use Uvicorn or Gunicorn directly, but Nginx makes your website look more like a website.



Tags: Docker Python Nginx Session

Posted on Thu, 16 Apr 2020 17:58:27 -0700 by pranesh