Skip to content

Commit

Permalink
Support the FastAPI app being mounted. (#1174)
Browse files Browse the repository at this point in the history
Fixes #1170
  • Loading branch information
nsthorat authored Feb 13, 2024
1 parent 086bc97 commit bef587c
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 29 deletions.
14 changes: 14 additions & 0 deletions integration_tests/fastapi_integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
"""Integration tests where the FastAPI app is mounted."""
import lilac.server
from fastapi import FastAPI

app = FastAPI()


@app.get('/')
def read_main():
"""The main endpoint."""
return {'message': 'Hello World from main app'}


app.mount('/lilac_sub', lilac.server.app)
29 changes: 29 additions & 0 deletions integration_tests/fastapi_mount_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Tests the FastAPI server when it is mounted as a sub-path.

MOUNT_PATH='lilac_sub'

# Find a free port.
PORT=$(python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()');

poetry run uvicorn integration_tests.fastapi_integration:app --port $PORT &
pid="$!"


URL="http://localhost:$PORT/"
start_time="$(date -u +%s)"
TIMEOUT_SEC=15
until curl --fail --silent "$URL" > /dev/null; do
sleep 1
current_time="$(date -u +%s)"
elapsed_seconds=$(($current_time-$start_time))
if [ $elapsed_seconds -gt $TIMEOUT_SEC ]; then
echo "Timeout $TIMEOUT_SEC seconds to reach server."
kill $pid
exit 1
fi
done


curl --fail --silent "http://localhost:$PORT/lilac_sub/api/v1/tasks/"

curl --fail --silent "http://localhost:$PORT/lilac_sub/"
30 changes: 2 additions & 28 deletions integration_tests/run_integration_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,8 @@

set -e # Fail if any of the commands below fail.

# Make sure the CLI succeeds for test_data.
mkdir -p test_data
touch test_data/lilac.yml

# Find a free port.
PORT=$(python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()');


poetry run lilac start ./test_data --port $PORT &
pid="$!"

URL="http://localhost:$PORT/docs"
start_time="$(date -u +%s)"
TIMEOUT_SEC=15
until curl --fail --silent "$URL" > /dev/null; do
sleep 1
current_time="$(date -u +%s)"
elapsed_seconds=$(($current_time-$start_time))
if [ $elapsed_seconds -gt $TIMEOUT_SEC ]; then
echo "Timeout $TIMEOUT_SEC seconds to reach server."
kill $pid
exit 1
fi
done

echo "GET request to $URL succeeded."

kill $pid
./integration_tests/start_server_test.sh
./integration_tests/fastapi_mount_test.sh

echo
echo "CLI integration tests passed."
Expand Down
32 changes: 32 additions & 0 deletions integration_tests/start_server_test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Tests that the lilac server starts from the CLI.

set -e # Fail if any of the commands below fail.

# Make sure the CLI succeeds for test_data.
mkdir -p test_data
touch test_data/lilac.yml

# Find a free port.
PORT=$(python -c 'import socket; s=socket.socket(); s.bind(("", 0)); print(s.getsockname()[1]); s.close()');


poetry run lilac start ./test_data --port $PORT &
pid="$!"

URL="http://localhost:$PORT/docs"
start_time="$(date -u +%s)"
TIMEOUT_SEC=15
until curl --fail --silent "$URL" > /dev/null; do
sleep 1
current_time="$(date -u +%s)"
elapsed_seconds=$(($current_time-$start_time))
if [ $elapsed_seconds -gt $TIMEOUT_SEC ]; then
echo "Timeout $TIMEOUT_SEC seconds to reach server."
kill $pid
exit 1
fi
done

echo "GET request to $URL succeeded."

kill $pid
5 changes: 4 additions & 1 deletion lilac/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,10 @@ def __init__(self, app: ASGIApp) -> None:
async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
"""Redirect trailing slashes to non-trailing slashes."""
url = URL(scope=scope).path
ends_with_slash = url.endswith('/') and url != '/' and not url.startswith('/api')
root_path = scope.get('root_path') or ''
ends_with_slash = (
url.endswith('/') and url != '/' and root_path and not url.startswith(root_path + '/api')
)

if scope['type'] == 'http' and ends_with_slash:
new_url = url.rstrip('/')
Expand Down

0 comments on commit bef587c

Please sign in to comment.