Skip to content

    Chapter 3, Basic

    Routes and GET requests

    A route links a path and a verb to a function. When the request arrives, the function runs, and what it returns becomes the JSON response.

    Multiple routes

    Each decorator (@app.get, @app.post...) registers a route. The path is the part of the URL after the server address:

    basico/cap03_rotas_get.pylinhas 10 a 34
    from fastapi import FastAPI
    from fastapi.testclient import TestClient
    
    app = FastAPI()
    
    
    @app.get("/")
    def home():
        return {"mensagem": "Bem-vindo ao FastAPI"}
    
    
    @app.get("/sobre")
    def sobre():
        return {"mensagem": "Esta é a página sobre"}
    
    
    @app.get("/usuarios")
    def usuarios():
        return {"usuarios": ["Mohit", "Rohit", "Amit"]}
    
    
    cliente = TestClient(app)
    for caminho in ("/", "/sobre", "/usuarios"):
        resposta = cliente.get(caminho)
        print(caminho, resposta.status_code, resposta.json())
    
    Output
    / 200 {'mensagem': 'Bem-vindo ao FastAPI'}
    /sobre 200 {'mensagem': 'Esta é a página sobre'}
    /usuarios 200 {'usuarios': ['Mohit', 'Rohit', 'Amit']}
    

    The GET only reads: it should not change anything on the server. That’s why the browser can repeat a request GET without danger, and that’s why it can be cached.

    What the browser shows

    When you open /usuarios in the browser, you see the raw JSON, and not a pretty page. An API returns data, and the frontend designs the screen. The response header indicates this:

    basico/cap03_rotas_get.pylinhas 39 a 40
    resposta = cliente.get("/usuarios")
    print(resposta.headers["content-type"])
    
    Output
    application/json
    

    Non-existent route and wrong verb

    Calling a path that does not exist returns 404. Calling a path that exists with the wrong verb returns 405:

    basico/cap03_rotas_get.pylinhas 45 a 47
    print(cliente.get("/nao-existe").status_code)
    resposta = cliente.post("/sobre")
    print(resposta.status_code, resposta.json())
    
    Output
    404
    405 {'detail': 'Method Not Allowed'}
    

    What FastAPI logged

    In addition to its three routes, FastAPI added documentation pages. You can list everything that is registered:

    basico/cap03_rotas_get.pylinha 52
    print([rota.path for rota in app.routes])
    
    Output
    ['/openapi.json', '/docs', '/docs/oauth2-redirect', '/redoc', '/', '/sobre', '/usuarios']
    

    Documenting the routes

    The parameters of the decorator and the function's docstring become text in the documentation. tags groups the routes, summary gives a short title and the docstring provides the long description:

    basico/cap03_rotas_get.pylinhas 57 a 65
    @app.get("/produtos", tags=["Produtos"], summary="Lista os produtos")
    def produtos():
        """Devolve todos os produtos disponíveis no catálogo."""
        return []
    
    
    operacao = app.openapi()["paths"]["/produtos"]["get"]
    print(operacao["tags"], operacao["summary"])
    print(operacao["description"])
    
    Output
    ['Produtos'] Lista os produtos
    Devolve todos os produtos disponíveis no catálogo.
    

    Testing in Swagger

    In /docs, click on the route, then on Try it out and on Execute. The page shows the called address, the response body, and the status code. Routes GET can also be tested directly in the browser. The routes POST, PUT and DELETE cannot: the browser only sends GET when you type an address, and for the other verbs, you use Swagger, the curl or a tool like Postman.

    Why JSON?

    The purpose of an API is to exchange data between programs. JSON is lightweight, readable, and understood by almost every language, which is why it is the standard format for FastAPI. What your function returns (dictionaries, lists, Pydantic models) is automatically converted to JSON.

    Exercise 1

    A products route

    Add GET /categorias, which returns the list ["livros", "jogos", "música"], and check the status and content.