FastAPI library (Python web framework) basic usage guide (1)

FastAPI Overview

Reference documentation:

  • Chinese documentation
  • Easily get started with Python’s web artifact: FastAPI tutorial

Introduction

FastAPI is a modern Python-based web framework designed to quickly build high-performance APIs.

FastAPI key features:

  • Fast: Extremely high performance on par with NodeJS and Go (thanks to Starlette and Pydantic). One of the fastest Python web frameworks.
  • Efficient Coding: Increase feature development speed by approximately 200% to 300%.
  • Fewer bugs: About 40% fewer human (developer) caused bugs.
  • Smart: Excellent editor support. Automatic completion is available everywhere, reducing debugging time.
  • Simple: Designed to be easy to use and learn, it takes less time to read the documentation.
  • Short: Minimize code duplication. Rich functionality is achieved through different parameter declarations. Fewer bugs.
  • Robust: Production-usable level code. There are also automatically generated interactive documents.
  • Standardization: Based on (and fully compatible with) relevant open standards for APIs: OpenAPI (formerly Swagger) and JSON Schema.

Introduction and differences of common Python web frameworks

Performance:

  • Django: is a full-featured framework that provides many built-in functions and extensions. Although it is relatively low in terms of performance, it is very suitable for building large applications.

  • Flask: It is a lightweight framework that pays more attention to simplicity and flexibility. Compared to Django, Flask has better performance, but it has relatively fewer features.

  • FastAPI: It is a high-performance framework based on asynchronous request processing and type annotations. FastAPI is more performant than Django and Flask, and it uses Python’s asyncio library to achieve efficient concurrent request processing.

Development Difficulty:

  • Django: It is a full-featured framework that provides many ready-made functions and components to make development faster and simpler. However, Django can have a relatively steep learning curve for beginners.
  • Flask: It is a concise and flexible framework that focuses more on customization and configuration. Compared with Django, Flask has a gentler learning curve and is suitable for small and simple projects.
  • FastAPI: Uses type annotations and the function of automatically generating documents to make the code more readable and maintainable. It provides standards-based API patterns and powerful verification tools to reduce errors during the development process.

Promotion Level:

  • Django: is one of the most popular and widely used Python web frameworks. It has huge community support and rich documentation resources, making it easy to find relevant tutorials, plug-ins and solutions.

  • Flask: It is a relatively popular framework with a large community and rich extension library. Although it has a relatively small user base, it is very popular for small projects and rapid prototyping.

  • FastAPI: is a relatively new framework, but it is quickly gaining traction among developers. Its high performance and modern features have attracted many developers, and the community is gradually expanding.

    FastAPI is a modern, fast (high-performance) web framework for building APIs using Python 3.6+ and based on standard Python type hints.

Getting Started Example

  • Install FastAPI and uvicorn

    FastAPI uses uvicorn as the default web service. Therefore, you need to install FastAPI and uvicorn

    uvicorn is a lightweight ASGI (Asynchronous Server Gateway Interface) server

    pip install fastapi
    pip install uvicorn
    
  • Sample code

    from fastapi import FastAPI
    import uvicorn
    
    # Create a FastAPI application instance
    app = FastAPI()
    # Define routes (use decorators to bind functions to specific paths and HTTP methods)
    @app.get("/")
    async def root():
        return {<!-- -->"message": "Hello World"}
    
    @app.get("/items/{item_id}")
    def read_item(item_id: int, q: str = None):
        return {<!-- -->"item_id": item_id, "q": q}
    
    # Allow FastAPI applications using uvicorn when launching the program
    uvicorn.run(app)
    #The default ip is 127.0.0.1, and the default port is 8000
    

Start web service

  • Method 1: uvicorn embedded

    Use uvicorn.run(app) in the code to enable the uvicorn server to run the python service, and then use python to start the py module

    import uvicorn
    
    app = FastAPI()
    uvicorn.run(app)
    
  • Method 2: uvicorn external opening

    Enter the command at the command line:

    uvicorn main:app --host 0.0.0.0 --port 80 --reload
    
    • main: py file name to start the service
    • app: service object name
    • –host: ip address
    • –port: port
    • –reload: Automatically restart the service after the code is modified. Only used during development. Do not use this parameter after going online, as it will reduce performance.

Parameters supported by uvicorn.run

  • app: Specifies the application app. Script name: FastAPI instance object’ or FastAPI instance object
  • host: String, allowed to be accessed in the form: locahost, 127.0.0.1, current IP, 0.0.0.0. Default is 127.0.0.1
  • port: Number, application port, default is 8000
  • uds: string, the domain name of the socket service bound to UNIX
  • fd: Number from which this file descriptor is bound to the socket
  • loop: event loop mode. The option list is [auto|asyncio|uvloop], default is auto
  • http: HTTP protocol implementation. The option list is [auto|h11|httptools], the default is auto
  • ws: WebSocket protocol implementation. The option list is [auto|none|websockets|wsproto], the default is auto
  • ws-max-size: Number, WebSocket maximum message size (bytes), default value is 16777216
  • lifespan : Lifecycle implementation. The option list is [auto|on|off], default is auto
  • env-file: PATH, environment configuration file
  • log-config: PATH, log configuration file. Supported formats: .ini, .json, .yaml, the default is fastapi’s default log configuration
  • log-level: Log level. The option list is [critical|error|warning|info|debug|trace], the default is info
  • access-log: boolean, access log switch, default is True
  • use-colors: boolean, color log switch (log-config must be specified), default is None
  • interface : Select ASGI3, ASGI2, or WSGI as the application interface. The option list is [auto|asgi3|asgi2|wsgi], default is auto
  • debug: Whether to use debug mode, default False,
  • reload: boolean, whether to automatically restart when the code is updated, default False,
  • reload_dirs: String, set the reload directory. When this parameter is not passed in real time, the current working directory will be used.
  • reload-delay: float, how often to detect code changes, default 0.25 seconds
  • workers: Number, number of worker processes. Defaults to the WEB_CONCURRENCY environment variable if available or 1. Not valid for –reload.
  • proxy-headers: boolean, enable/disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to fill in remote address information, default is True
  • forwarded-allow-ips : String, comma separated list of IPs to trust proxy header. Defaults to FORWARDED_ALLOW_IPS environment variable (if available), or None. When it is None, 127.0.0.1 is taken in the code.
  • root-path : String that sets the ASGI “root path” for applications installed at the given URL path.
  • limit-concurrency : Number, the maximum number of concurrent connections or tasks allowed before an HTTP503 response is issued. Default is None
  • limit-max-requests: Number, when the number of requests is reached, the process will be terminated. The default is None.
  • backlog: Number, the maximum number of connections waiting to be processed, the default is 2048
  • timeout-keep-alive : Number, if no new data is received within this timeout, the keep-alive connection will be closed, default is 5
  • ssl-keyfile: String, SSL key file, default is None
  • ssl-certfile: String, SSL certificate file, default is None
  • ssl-keyfile-password: String, SSL key file password, default is None
  • ssl-version: Number, SSL version to use (see stdlib SS L module for details), default is 2
  • ssl-cert-reqs: Number, whether a client certificate is required (see stdlib SSL module for details), default is 0
  • ssl-ca-certs: string, CA certificate file
  • ssl-ciphers: string, CA certificate file password to be used (see stdlib SSL module for details), default is TLSv1
  • header: dictionary, custom response header information, in the form of key-value pairs, the default is None

Common API

app=FastAPI(): Create a FastAPI application instance

  • app = FastAPI() is a common practice for creating application instances in FastAPI. This line of code creates a FastAPI application object on which routing, middleware, exception handling, etc. can be defined.

  • The application instance app has many properties and methods for configuring and managing various aspects of the application, such as routing, middleware, exception handling, dependency injection, etc. By creating an app instance, you can define and organize your application’s logic within it.

  • code example

    from fastapi import FastAPI
    
    app = FastAPI()
    
  • Supported parameters (all optional):

    • debug: debug mode, True/False. This property is inherited from starlette, in which the property decorator is used.

    • routes: Route list, default value is None

      This property is inherited from starlette and is a list of BaseRoutes of type startlette. BaseRoute is related to starlette’s base type Scope.

    • title: The title of the API document, default value FastAPI

    • description: Description of the API document, empty by default

    • version: The version number of the API interface

    • openapi_url: OpenAPI file path, default is /opanapi.json

    • openapi_prefix: OpenAPI file path prefix, empty by default

    • default_response_class: Default response type, default is JSONResponse

      This parameter is inherited from startlette’s Response. There are seven types: HTMLResponse, PlainTextResponse, UJSONResponse, RedirectResponse, StreamingResponse, FileResponse and JSONResponse. The starlette.responses module needs to be loaded when using it.

    • docs_url: interactive document path, default is /docs

    • redoc_url: optional document path, default is /redoc

    • swagger_ui_oauth2_redirect_url: OAuth redirect path, the default is /docs/oauth2-redirect

    • swagger_ui_init_oauth: OAuth redirect dictionary, default is None

    • middleware: middleware, empty by default

    • exception_handlers: Exception handling methods, default is None

    • on_startup: List of methods called when the app starts

    • on_shutdown: List of methods called when the app is shut down

    • extra : additional optional parameters

FastAPI() common API examples

get(), post(), etc.: define the routing of HTTP requests

In FastAPI, methods such as app.get() and app.post() are used to define the routing of HTTP requests. These methods accept multiple parameters that specify the route’s path, request handler function, dependencies, etc.

The following are the main parameters:

  • path (required): The path used to specify the route. This is a string that represents a URL path and can contain path parameters and query parameters.
  • response_model: used to specify the response model. A response model is a data structure for response data, typically defined using Pydantic models.
  • summary: A short string describing the purpose or functionality of the route.
  • description: Used to provide more detailed routing instructions.
  • tags: A list of strings used to tag routes in order to categorize and organize them in the document.
  • dependencies: A list specifying the dependencies that need to be injected in the route handler function.
  • response_description: used to specify the description information of the response.
  • deprecated: A Boolean value indicating whether the route has been deprecated.
  • status_code: Specifies the HTTP status code of the response.
  • response_model_include and response_model_exclude: Used to specify fields to include or exclude in the response model.
  • response_model_by_alias: A Boolean value indicating whether to use aliases in the Pydantic model to serialize the response.
  • response_model_exclude_unset: A Boolean value indicating to exclude unset fields in the response.
  • response_model_exclude_defaults: A Boolean value indicating to exclude fields with default values in the response.
  • response_model_exclude_none: A Boolean value indicating that fields with a value of None are excluded from the response.
  • operation_id: A unique identifier that specifies an operation.
  • deprecated: A Boolean value indicating whether the route has been deprecated.
  • callbacks: A dictionary used to specify callback functions.

These parameters can be flexibly configured according to needs. Generally speaking, the path parameter is required, while other parameters are optional as needed.

add_middleware(): Add middleware

  • add_middleware() Function: It is the method used to add middleware in FastAPI.

    Middleware is a function that can perform pre- and post-processing during request and response processing. Middleware can be used to implement various requirements, such as adding global headers, request logging, exception handling, etc.

    Add custom middleware to your application via the app.add_middleware method. When a request arrives, FastAPI will execute the added middleware in sequence, and then call the route processing function. When the response is returned, the middleware’s post-processing logic will be executed in reverse order.

    By adding middleware, you can implement some common functionality during request and response processing without having to write the same code repeatedly in each route. This helps keep your code clean and maintainable.

  • Commonly used parameters:

    • middleware_class (required): A middleware class that you wish to add to the middleware of your application.

      Middleware classes should inherit from fastapi.middleware.base.BaseHTTPMiddleware or a similar base class.

    • **options: This is the configuration option of the middleware. Different parameters can be passed according to the requirements of the middleware. The specific options depend on the middleware class used. In general, any custom parameters related to middleware can be passed for use in the middleware class.

CORSMiddleware

  • FastAPI’s built-in middleware is used to handle cross-origin resource sharing (CORS) issues.

    CORS is a browser security mechanism used to control cross-origin requests. In applications with separate front-end and back-end, when the front-end code (running in the browser) makes a request from one domain to another, the browser performs a cross-domain check to ensure that only trusted domains can access the resource.

    CORSMiddleware helps developers configure FastAPI applications to correctly handle cross-domain requests.

    After configuring the middleware, FastAPI will automatically handle cross-origin requests and add appropriate header information to the response to meet CORS security requirements.

    Please note that CORS configuration involves application security. In a production environment, allow_origins and other parameters should be configured according to actual needs.

  • Common parameters (used to configure cross-domain policies):

    • allow_origins: List of domain names allowed to access the resource.

      It is possible to use ["*"] to allow all domains, but this is generally not recommended.

    • allow_credentials: Whether to allow requests that send credentials (such as cookies, HTTP authentication headers).

      If it is True, you need to ensure that the corresponding configuration is performed on both the client and the server, and allow_origins must be a specific source and cannot be [" *"]

    • allow_methods: List of allowed HTTP methods such as ["GET", "POST"]. The default is ["GET"]

      You can use ["*"] to allow all methods

    • allow_headers: List of allowed HTTP headers, such as ["Content-Type", "Authorization"]. The default is []

      You can use ["*"] to allow all headers

      Note: Accept, Accept-Language, Content-Language and Content-Type are always allowed

  • Code example:

    from fastapi import FastAPI
    from fastapi.middleware.cors import CORSMiddleware
    
    app = FastAPI()
    
    # Add CORS middleware
    app.add_middleware(
        CORSMiddleware,
        allow_origins=["http://localhost", "https://example.com"],
        allow_credentials=True,
        allow_methods=["*"],
        allow_headers=["*"],
    )
    

Custom middleware:

  • Method 1: Customize the middleware class and pass the object of the custom middleware class through the dispatch parameter when adding custom middleware

    from fastapi import FastAPI, Request
    from fastapi.middleware.cors import BaseHTTPMiddleware
    
    # Custom middleware
    class MyMiddleware:
        def __init__(self, some_attribute: str = None):
            # some_attribute is not required, used here to demonstrate passing parameters to custom middleware
            self.some_attribute = some_attribute
    
        async def __call__(self, request: Request, call_next):
            # do something with the request object
            # process the request and get the response
            response = await call_next(request)
            # do something with the response object
            return response
    
    app = FastAPI()
    # Add custom middleware
    app.add_middleware(BaseHTTPMiddleware, dispatch=MyMiddleware())
    
  • Method 2: Custom middleware class inherits BaseHTTPMiddleware class

    # Custom middleware
    class MyMiddleware(BaseHTTPMiddleware):
        def __init__(self, app, some_attribute: str):
            super().__init__(app)
            self.some_attribute = some_attribute
    
        async def dispatch(self, request: Request, call_next):
            # do something with the request object, for example
            content_type = request.headers.get('Content-Type')
            print(content_type)
            
            # process the request and get the response
            response = await call_next(request)
            
            return response
    
    app = FastAPI()
    # Add custom middleware
    app.add_middleware(MyMiddleware)
    
  • Method 3: @app.middleware decorator

    In FastAPI, you can add application-scoped middleware using the @app.middleware decorator.

    That is, middleware added using the @app.middleware decorator applies to the entire FastAPI application and is usually used to perform global operations such as authentication, logging, exception handling, etc. This allows you to share the same middleware logic throughout your application without having to add the same middleware repeatedly for each route.

    This decorator can accept the following two parameters:

    • middleware_type (required): String parameter used to specify the type of middleware.

      In FastAPI, middleware can be divided into the following two types:

      • “http”: HTTP middleware

        This middleware will be executed during the processing of each HTTP request and is suitable for handling HTTP requests and responses.

      • “websocket”: WebSocket middleware

        This middleware will be executed during the processing of a WebSocket connection and is suitable for handling WebSocket requests and responses.

    • priority (optional): Integer parameter used to specify the priority of the middleware.

      If you have multiple middlewares in your application, you can use this parameter to control the order in which they execute.

      A smaller number indicates a higher priority, and middleware will be executed in ascending order of priority.

      If the priority parameter is not specified, the default priority of the middleware is 50.

    app = FastAPI()
    
    # Custom middleware processing function
    @app.middleware("http")
    async def log_requests(request: Request, call_next):
        logger.info(f"Incoming request: {<!-- -->request.method} {<!-- -->request.url}")
        response = await call_next(request)
        logger.info(f"Outgoing response: {<!-- -->response.status_code}")
        return response
    

websocket(): Create WebSocket route

  • websocket() function: Creates a WebSocket route to achieve real-time two-way communication with the client.

    WebSocket is a protocol for full-duplex communication on a single long connection. It is suitable for application scenarios that require real-time update of data, such as chat applications, real-time data display, etc.

    On the client side, you can use the browser’s built-in WebSocket API or other WebSocket client libraries to communicate with FastAPI WebSocket routing.

  • Code example:

    from fastapi import FastAPI, WebSocket
    
    app = FastAPI()
    
    # WebSocket routing
    @app.websocket("/ws")
    async def websocket_endpoint(websocket: WebSocket):
        await websocket.accept()
        while True:
            data = await websocket.receive_text()
            await websocket.send_text(f"You said: {<!-- -->data}")
    
    • A WebSocket route for /ws is created using the app.websocket() method. After the WebSocket connection is established, use the await websocket.accept() method to accept the connection.
    • Then, use the await websocket.receive_text() method in an infinite loop to receive the text message sent by the client, and use the await websocket.send_text() method to return the message to client.

mount(): Install sub-applications (static files)

  • mount() Function: Used to mount another ASGI application as a sub-application of the FastAPI application.

    Using mount to install sub-applications can easily combine multiple applications to achieve a more complex application logic structure. For example, assemble multiple API applications into a gateway application, assemble multiple applications into a single page application, and so on.

    Support parameters:

    • path: Type is string, parameters must be passed, specify the path accessed by url
    • app: The type is ASGIApp, parameters must be passed, and the static file object is mounted.
      • directory: Specifies the static file directory to be mounted.
    • name: Specifies the name used internally by fastapi. Default is None
  • How to access static files: Enter ip:port/path/full file name.suffix directly into the browser.

  • Code example (configuring static file path):

    import uvicorn
    from fastapi import FastAPI
    from fastapi.staticfiles import StaticFiles
    
    app = FastAPI()
    #Configure static file path
    app.mount("/static", StaticFiles(directory="static"), name="static")
    uvicorn.run(app="main:app", host="0.0.0.0", port=8000, reload=True)