FastAPI

  • Un servidor web es pot configurar com un servidor de recursos que s'accedeixen mijançant un conjunt de funcions "externes" o endpoints (API)

    Paràmetres

    FastAPI sap que una element del path és una variable perquè està definit entre claudàtors {}

    Com que la funció “externa” té un argument /{id}, la funció employee()" que implementa la funció “externa” ha de tenir també un argument id de tipus int.

    Aquesta funció pot ser invocada externament amb els paths /employee/1 o /employee/2, on 1 i 2 són l’argument id de la funció.

    $ http -b localhost:8000/employee/1
    {
        "job": "clerk",
        "name": "David"
    }

    Però que passa si passo un paràmetre que no és un int?

    $ http localhost:8000/employee/david
    HTTP/1.1 422 Unprocessable Entity
    content-length: 149
    content-type: application/json
    date: Thu, 29 Aug 2024 13:27:29 GMT
    server: uvicorn
    
    {
        "detail": [
            {
                "input": "david",
                "loc": [
                    "path",
                    "id"
                ],
                "msg": "Input should be a valid integer, unable to parse string as an integer",
                "type": "int_parsing"
            }
        ]
    }

    El servidor torna l’error 422 Unprocessable Entity i un missatge JSON on explica l’error.

    I que passa si passo el id d’un treballador que no existeix?

    $ http localhost:8000/employee/5
    HTTP/1.1 500 Internal Server Error
    content-length: 21
    content-type: text/plain; charset=utf-8
    date: Thu, 29 Aug 2024 13:29:52 GMT
    server: uvicorn
    
    Internal Server Error

    És produeix en error 500 Internal Server Error perquè estem accedint al dic amb l’operador [] sense verificar que existeix una entrada per la id que ens han passat com argument.

    El que hem de fer és modificar el codi per tornar un error 404 Not Found:

    from fastapi import FastAPI, HTTPException
    
    app = FastAPI()
    
    employees = {1: "David", 2: "Dora"}
    
    @app.get("/employee/{id}")
    def employee(id: int):
    
        if id not in employees.keys():
            raise HTTPException(status_code=404, detail="Employee not found")
        
        return {"name": employees[id], "job": "clerk"}

    Pots veure que ara la implementació de la funció “externa” /employee/{id} funciona correctament:

    $ http localhost:8000/employee/5
    HTTP/1.1 404 Not Found
    content-length: 31
    content-type: application/json
    date: Thu, 29 Aug 2024 13:35:19 GMT
    server: uvicorn
    
    {
        "detail": "Employee not found"
    }

    Activitats

    1.- Crea una funció “externa” /capital/{country} que retorni la capital del país.

    {% sol %} TODO {% endsol %}

    Create

    Si vols enviar dades estructurades al servidor per crear un recurs pots utilitzar una sol.licitut POST.

    A continuació tens dos funcions REST (read i update):

    class Item(BaseModel):
        id: int
        name: str
        price: float
    
    
    items = {
        1: Item(id=1, name="iPhone 15", price=699.36),
        2: Item(id=2, name="Samsung S23", price=619.00),
    }
    
    
    @app.get("/items/{id}")
    def read_item(id: int):
    
        if id not in items.keys():
            raise HTTPException(status_code=404, detail="Item not found")
    
        return items[id]
    
    
    @app.post("/items/")
    def create_item(item: Item):
        item.id = max(items) + 1
        items[item.id] = item
        return item

    Crea un nou item:

    http -b POST localhost:8000/items/ id=0 name="Pixel 0" price=899.00
    {
        "id": 3,
        "name": "Pixel 0",
        "price": 899.0
    }

    Pots veure que el servidor torna l’item amb la id que li ha assignat el servidor.

    Si fas una consulta amb aquest id el servidor et torna l’item que has creat:

    $ http -b localhost:8000/items/3
    {
        "id": 3,
        "name": "Pixel 0",
        "price": 899.0
    }

    També pots veure que ara la teva API inclou un {% link “p:/ts/json-schema/” %} per Item:

    Activitat

    1.- Implementa els mètodes “update” i “delete”.

    Query

    Activitat

    3.- Modifica el projecte https://gitlab.com/xtec/python/fastapi-rest

    4.- Crea una imatge i pujala a Docker Hub.