diff --git a/examples/connect/fastapi/README.md b/examples/connect/fastapi/README.md new file mode 100644 index 00000000..8b5d9df1 --- /dev/null +++ b/examples/connect/fastapi/README.md @@ -0,0 +1,46 @@ +# FastAPI Example + +## Start the app locally + +```bash +# install uvicorn +pip install "uvicorn[standard]" + +# start the app +export DATABRICKS_HOST="" +export DATABRICKS_PATH="" +uvicorn app:app --reload + +# send a request to the rest api +curl -X 'GET' 'http://127.0.0.1:8000/fares' +``` + +## Deploy to Posit Connect + +Validate that `rsconnect-python` is installed: + +```bash +rsconnect version +``` + +Or install it as documented in the [installation](https://docs.posit.co/rsconnect-python/#installation) section of the documentation. + +To publish, make sure `CONNECT_SERVER`, `CONNECT_API_KEY`, `DATABRICKS_HOST`, `DATABRICKS_PATH` have valid values. Then, on a terminal session, enter the following command: + +```bash +rsconnect deploy fastapi . \ + --server "${CONNECT_SERVER}" \ + --api-key "${CONNECT_API_KEY}" \ + --environment DATABRICKS_HOST \ + --environment DATABRICKS_PATH +``` + +Note that the Databricks environment variables do not need to be resolved by the shell, so they do not include the `$` prefix. + +The Databricks environment variables only need to be set once, unless a change needs to be made. If the values have not changed, you don’t need to provide them again when you publish updates to the document. + +``` +rsconnect deploy fastapi . \ + --server "${CONNECT_SERVER}" \ + --api-key "${CONNECT_API_KEY}" +``` diff --git a/examples/connect/fastapi/app.py b/examples/connect/fastapi/app.py new file mode 100644 index 00000000..a0b74bc4 --- /dev/null +++ b/examples/connect/fastapi/app.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# mypy: ignore-errors +import os + +from posit.connect.external.databricks import viewer_credentials_provider + +from databricks import sql + +from typing import Annotated + +from fastapi import FastAPI, Header, Depends +from fastapi.responses import JSONResponse + +DATABRICKS_HOST=os.getenv("DATABRICKS_HOST") +DATABRICKS_HOST_URL = f"https://{DATABRICKS_HOST}" +SQL_HTTP_PATH = os.getenv("DATABRICKS_PATH") + +rows = None +app = FastAPI() + +async def get_token( + posit_connect_user_session_token: Annotated[str | None, Header()] = None +) -> dict | None: + """ + Get the token from the Posit-Connect-User-Session-Token header. + """ + if posit_connect_user_session_token is None: + return None + return posit_connect_user_session_token + +@app.get("/fares") +async def get_fares(session_token=Depends(get_token)) -> JSONResponse: + """ + FastAPI example API that returns the first few rows from + a table hosted in Databricks. + """ + global rows + + credentials_provider = viewer_credentials_provider(user_session_token=session_token) + + if rows is None: + query = "SELECT * FROM samples.nyctaxi.trips LIMIT 10;" + + with sql.connect(server_hostname=DATABRICKS_HOST, + http_path=SQL_HTTP_PATH, + auth_type="databricks-oauth", + credentials_provider=credentials_provider) as connection: + with connection.cursor() as cursor: + cursor.execute(query) + rows = cursor.fetchall() + + return [row.asDict() for row in rows] diff --git a/examples/connect/fastapi/requirements.txt b/examples/connect/fastapi/requirements.txt new file mode 100644 index 00000000..d506dcc6 --- /dev/null +++ b/examples/connect/fastapi/requirements.txt @@ -0,0 +1,4 @@ +databricks-sql-connector==3.0.1 +databricks-sdk==0.20.0 +fastapi==0.110.0 +git+https://github.com/posit-dev/posit-sdk-py.git