|
@@ -0,0 +1,107 @@
|
|
|
+#! /usr/bin/env python3
|
|
|
+# NOTE: Requires python3.10 or above
|
|
|
+
|
|
|
+from enum import Enum
|
|
|
+from fastapi import FastAPI, Query
|
|
|
+from pydantic import BaseModel
|
|
|
+
|
|
|
+app = FastAPI()
|
|
|
+
|
|
|
+# Root is an example, just returns static stuff
|
|
|
+@app.get("/")
|
|
|
+async def root():
|
|
|
+ return {"message": "Hello World"}
|
|
|
+
|
|
|
+
|
|
|
+# /items is an example, just returns the provided value, but must be an int.
|
|
|
+@app.get("/items/{item_id}")
|
|
|
+async def read_items(item_id: int):
|
|
|
+ return {"item_id": item_id}
|
|
|
+
|
|
|
+
|
|
|
+# /models only allows select values. These are machine learning models.
|
|
|
+class ModelName(str, Enum):
|
|
|
+ alexnet = "alexnet" # FTD: Appears both sides have to match
|
|
|
+ resnet = "resnet"
|
|
|
+ lenet = "lenet"
|
|
|
+
|
|
|
+
|
|
|
+@app.get("/models/{model_name}")
|
|
|
+async def get_model(model_name: ModelName):
|
|
|
+ if model_name is ModelName.alexnet:
|
|
|
+ return {"model_name": model_name, "message": "Deep Learning FTW!"}
|
|
|
+
|
|
|
+ if model_name.value == "lenet":
|
|
|
+ return {"model_name": model_name, "message": "LeCNN all the images."}
|
|
|
+
|
|
|
+ return {"model_name": model_name, "message": "Have some residuals"}
|
|
|
+
|
|
|
+
|
|
|
+# /items/ has query parameters
|
|
|
+fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
|
|
|
+
|
|
|
+
|
|
|
+@app.get("/items/")
|
|
|
+async def read_item(skip: int = 0, limit: int = 10):
|
|
|
+ return fake_items_db[skip : skip + limit] # first value, last value
|
|
|
+
|
|
|
+
|
|
|
+# /items2/ shows how to use an optional parameter
|
|
|
+@app.get("/items2/{item_id}")
|
|
|
+async def read_item2(item_id: str, q: str | None = None):
|
|
|
+ if q:
|
|
|
+ return {"item_id": item_id, "q": q}
|
|
|
+ return {"item_id": item_id}
|
|
|
+
|
|
|
+
|
|
|
+# A POST to /items/, our first example with a body
|
|
|
+class Item(BaseModel):
|
|
|
+ name: str
|
|
|
+ description: str | None = None
|
|
|
+ price: float
|
|
|
+ tax: float | None = None
|
|
|
+
|
|
|
+
|
|
|
+@app.post("/items/")
|
|
|
+async def create_item(item: Item):
|
|
|
+ return item
|
|
|
+
|
|
|
+
|
|
|
+# Validation:
|
|
|
+# max_length: async def read_items(q: str | None = Query(default=None, max_length=50)):
|
|
|
+# default: async def read_items(q: str = Query(default="fixedquery", min_length=3)):
|
|
|
+# Regex: Query(default=None, ..., regex="^fixedquery$"
|
|
|
+# List: async def read_items(q: list[str] | None = Query(default=None)): # call via ?q=foo&q=bar&q=zoo
|
|
|
+# more: https://fastapi.tiangolo.com/tutorial/query-params-str-validations/
|
|
|
+@app.get("/items3/")
|
|
|
+async def read_items(
|
|
|
+ q: list[str] | None = Query(default=None),
|
|
|
+): # call via ?q=foo&q=bar&q=zoo
|
|
|
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
|
|
|
+ if q:
|
|
|
+ results.update({"q": q})
|
|
|
+ return results
|
|
|
+
|
|
|
+
|
|
|
+# More metadata (https://fastapi.tiangolo.com/tutorial/query-params-str-validations/)
|
|
|
+# Big example of lots of metadata
|
|
|
+@app.get("/items4/")
|
|
|
+async def read_items(
|
|
|
+ q: str
|
|
|
+ | None = Query(
|
|
|
+ default=None,
|
|
|
+ alias="item-query",
|
|
|
+ title="Query string",
|
|
|
+ description="Query string for the items to search in the database that have a good match",
|
|
|
+ min_length=3,
|
|
|
+ max_length=50,
|
|
|
+ regex="^fixedquery$",
|
|
|
+ # gt=0, # For numeric types, Won't work here, "greater than"
|
|
|
+ # le=1000, # for numeric types, "less than or equal"
|
|
|
+ deprecated=True,
|
|
|
+ )
|
|
|
+):
|
|
|
+ results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
|
|
|
+ if q:
|
|
|
+ results.update({"q": q})
|
|
|
+ return results
|