Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/app/api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@
api_router.include_router(config.router)
api_router.include_router(credentials.router)
api_router.include_router(cron.router)
api_router.include_router(documents.router)
api_router.include_router(doc_transformation_job.router)
api_router.include_router(documents.router)
api_router.include_router(auth.router)
api_router.include_router(evaluations.router)
api_router.include_router(languages.router)
Expand Down
4 changes: 2 additions & 2 deletions backend/app/api/routes/api_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@


@router.post(
"/",
"",
response_model=APIResponse[APIKeyCreateResponse],
status_code=201,
dependencies=[Depends(require_permission(Permission.SUPERUSER))],
Expand Down Expand Up @@ -44,7 +44,7 @@ def create_api_key_route(


@router.get(
"/",
"",
response_model=APIResponse[list[APIKeyPublic]],
dependencies=[Depends(require_permission(Permission.REQUIRE_PROJECT))],
description=load_description("api_keys/list.md"),
Expand Down
4 changes: 2 additions & 2 deletions backend/app/api/routes/assistants.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def ingest_assistant_route(


@router.post(
"/",
"",
response_model=APIResponse[Assistant],
status_code=201,
dependencies=[Depends(require_permission(Permission.REQUIRE_PROJECT))],
Expand Down Expand Up @@ -126,7 +126,7 @@ def get_assistant_route(


@router.get(
"/",
"",
response_model=APIResponse[list[Assistant]],
summary="List all assistants in the current project",
dependencies=[Depends(require_permission(Permission.REQUIRE_PROJECT))],
Expand Down
4 changes: 2 additions & 2 deletions backend/app/api/routes/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ def collection_callback_notification(body: APIResponse[CollectionJobPublic]):


@router.get(
"/",
"",
description=load_description("collections/list.md"),
response_model=APIResponse[List[CollectionPublic]],
dependencies=[Depends(require_permission(Permission.REQUIRE_PROJECT))],
Expand All @@ -79,7 +79,7 @@ def list_collections(


@router.post(
"/",
"",
description=load_description("collections/create.md"),
response_model=APIResponse[CollectionJobImmediatePublic],
callbacks=collection_callback_router.routes,
Expand Down
6 changes: 3 additions & 3 deletions backend/app/api/routes/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

from app.api.routes.config import config, version

router = APIRouter(prefix="/configs", tags=["Config Management"])
router = APIRouter(tags=["Config Management"])

router.include_router(config.router)
router.include_router(version.router)
router.include_router(config.router, prefix="/configs")
router.include_router(version.router, prefix="/configs")
Comment thread
nishika26 marked this conversation as resolved.

__all__ = ["router"]
4 changes: 2 additions & 2 deletions backend/app/api/routes/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@


@router.post(
"/",
"",
description=load_description("config/create.md"),
response_model=APIResponse[ConfigWithVersion],
status_code=201,
Expand All @@ -44,7 +44,7 @@ def create_config(


@router.get(
"/",
"",
description=load_description("config/list.md"),
response_model=APIResponse[list[ConfigPublic]],
status_code=200,
Expand Down
8 changes: 4 additions & 4 deletions backend/app/api/routes/credentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@


@router.post(
"/",
"",
response_model=APIResponse[list[CredsPublic]],
description=load_description("credentials/create.md"),
dependencies=[Depends(require_permission(Permission.REQUIRE_PROJECT))],
Expand Down Expand Up @@ -52,7 +52,7 @@ def create_new_credential(


@router.get(
"/",
"",
response_model=APIResponse[list[CredsPublic]],
description=load_description("credentials/list.md"),
dependencies=[Depends(require_permission(Permission.REQUIRE_PROJECT))],
Expand Down Expand Up @@ -103,7 +103,7 @@ def read_provider_credential(


@router.patch(
"/",
"",
response_model=APIResponse[list[CredsPublic]],
description=load_description("credentials/update.md"),
dependencies=[Depends(require_permission(Permission.REQUIRE_PROJECT))],
Expand Down Expand Up @@ -165,7 +165,7 @@ def delete_provider_credential(


@router.delete(
"/",
"",
response_model=APIResponse[dict],
description=load_description("credentials/delete_all.md"),
dependencies=[Depends(require_permission(Permission.REQUIRE_PROJECT))],
Expand Down
2 changes: 1 addition & 1 deletion backend/app/api/routes/doc_transformation_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def get_transformation_job(


@router.get(
"/",
"",
description=load_description("documents/job_list.md"),
response_model=APIResponse[DocTransformationJobsPublic],
dependencies=[Depends(require_permission(Permission.REQUIRE_PROJECT))],
Expand Down
4 changes: 2 additions & 2 deletions backend/app/api/routes/documents.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def doctransformation_callback_notification(


@router.get(
"/",
"",
description=load_description("documents/list.md"),
response_model=APIResponse[list[Union[DocumentPublic, TransformedDocumentPublic]]],
dependencies=[Depends(require_permission(Permission.REQUIRE_PROJECT))],
Expand Down Expand Up @@ -100,7 +100,7 @@ def list_docs(


@router.post(
"/",
"",
description=load_description("documents/upload.md"),
response_model=APIResponse[DocumentUploadResponse],
callbacks=doctransformation_callback_router.routes,
Expand Down
2 changes: 1 addition & 1 deletion backend/app/api/routes/languages.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@


@router.get(
"/",
"",
response_model=APIResponse[LanguagesPublic],
description=load_description("languages/list.md"),
)
Expand Down
2 changes: 1 addition & 1 deletion backend/app/api/routes/login.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def recover_password(email: str, session: SessionDep) -> Message:
return Message(message="Password recovery email sent")


@router.post("/reset-password/", include_in_schema=False)
@router.post("/reset-password", include_in_schema=False)
def reset_password(session: SessionDep, body: NewPassword) -> Message:
"""
Reset password
Expand Down
2 changes: 1 addition & 1 deletion backend/app/api/routes/model_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@


@router.get(
"/",
"",
response_model=APIResponse[ModelConfigListPublic],
description=load_description("model_config/list_models.md"),
)
Expand Down
2 changes: 1 addition & 1 deletion backend/app/api/routes/model_evaluation.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ def run_model_evaluation(


@router.post(
"/evaluate_models/",
"/evaluate_models",
response_model=APIResponse,
description=load_description("model_evaluation/evaluate.md"),
dependencies=[Depends(require_permission(Permission.REQUIRE_PROJECT))],
Expand Down
2 changes: 1 addition & 1 deletion backend/app/api/routes/openai_conversation.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ def get_conversation_by_ancestor_id_route(


@router.get(
"/",
"",
response_model=APIResponse[list[OpenAIConversationPublic]],
summary="List all conversations in the current project",
description=load_description("openai_conversation/list.md"),
Expand Down
4 changes: 2 additions & 2 deletions backend/app/api/routes/organization.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

# Retrieve organizations
@router.get(
"/",
"",
dependencies=[Depends(require_permission(Permission.SUPERUSER))],
response_model=APIResponse[List[OrganizationPublic]],
description=load_description("organization/list.md"),
Expand All @@ -44,7 +44,7 @@ def read_organizations(

# Create a new organization
@router.post(
"/",
"",
dependencies=[Depends(require_permission(Permission.SUPERUSER))],
response_model=APIResponse[OrganizationPublic],
description=load_description("organization/create.md"),
Expand Down
2 changes: 1 addition & 1 deletion backend/app/api/routes/private.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class PrivateUserCreate(BaseModel):
is_verified: bool = False


@router.post("/users/", response_model=UserPublic, include_in_schema=False)
@router.post("/users", response_model=UserPublic, include_in_schema=False)
def create_user(user_in: PrivateUserCreate, session: SessionDep) -> Any:
"""
Create a new user.
Expand Down
4 changes: 2 additions & 2 deletions backend/app/api/routes/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

# Retrieve projects
@router.get(
"/",
"",
dependencies=[Depends(require_permission(Permission.SUPERUSER))],
response_model=APIResponse[List[ProjectPublic]],
description=load_description("projects/list.md"),
Expand All @@ -44,7 +44,7 @@ def read_projects(

# Create a new project
@router.post(
"/",
"",
dependencies=[Depends(require_permission(Permission.SUPERUSER))],
response_model=APIResponse[ProjectPublic],
description=load_description("projects/create.md"),
Expand Down
4 changes: 2 additions & 2 deletions backend/app/api/routes/user_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@


@router.get(
"/",
"",
description=load_description("user_project/list.md"),
response_model=APIResponse[list[UserProjectPublic]],
)
Expand All @@ -47,7 +47,7 @@ def list_project_users(


@router.post(
"/",
"",
dependencies=[Depends(require_permission(Permission.SUPERUSER))],
description=load_description("user_project/add.md"),
response_model=APIResponse[list[UserProjectPublic]],
Expand Down
4 changes: 2 additions & 2 deletions backend/app/api/routes/users.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@


@router.get(
"/",
"",
dependencies=[Depends(require_permission(Permission.SUPERUSER))],
response_model=UsersPublic,
include_in_schema=False,
Expand All @@ -43,7 +43,7 @@ def read_users(session: SessionDep, skip: int = 0, limit: int = 100) -> Any:


@router.post(
"/",
"",
dependencies=[Depends(require_permission(Permission.SUPERUSER))],
response_model=UserPublic,
include_in_schema=False,
Expand Down
4 changes: 2 additions & 2 deletions backend/app/api/routes/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@


@router.post(
"/test-email/",
"/test-email",
dependencies=[Depends(require_permission(Permission.SUPERUSER))],
status_code=201,
include_in_schema=False,
Expand All @@ -27,6 +27,6 @@ def test_email(email_to: EmailStr) -> Message:
return Message(message="Test email sent")


@router.get("/health/", include_in_schema=False)
@router.get("/health", include_in_schema=False)
async def health_check() -> bool:
return True
21 changes: 21 additions & 0 deletions backend/app/core/middleware.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,31 @@
import sentry_sdk
from fastapi import Request, Response
from opentelemetry import trace
from starlette.types import ASGIApp, Receive, Scope, Send

logger = logging.getLogger("http_request_logger")


class StripTrailingSlashMiddleware:
"""
Rewrite '/foo/' to '/foo' before routing so both forms hit the same handler.
"""

def __init__(self, app: ASGIApp) -> None:
self.app = app

async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None:
if scope["type"] == "http":
path = scope["path"]
if len(path) > 1 and path.endswith("/"):
scope = dict(scope)
scope["path"] = path[:-1]
raw_path = scope.get("raw_path")
if raw_path is not None and raw_path.endswith(b"/"):
scope["raw_path"] = raw_path[:-1]
await self.app(scope, receive, send)


def _resolve_http_route(request: Request) -> str:
"""
Resolve the HTTP route for telemetry and logging.
Expand Down
3 changes: 2 additions & 1 deletion backend/app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
from app.core.config import settings
from app.core.exception_handlers import register_exception_handlers
from app.core.logger import configure_logging
from app.core.middleware import http_request_logger
from app.core.middleware import StripTrailingSlashMiddleware, http_request_logger
from app.core.sentry_filters import before_send_transaction_filter
from app.core.telemetry import instrument_app, setup_telemetry

Expand Down Expand Up @@ -91,6 +91,7 @@ def custom_openapi():

app.middleware("http")(http_request_logger)
app.add_middleware(CorrelationIdMiddleware)
app.add_middleware(StripTrailingSlashMiddleware)

app.include_router(api_router, prefix=settings.API_V1_STR)

Expand Down
10 changes: 5 additions & 5 deletions backend/app/tests/api/routes/collections/test_collection_list.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def test_list_collections_returns_api_response(
"""

response = client.get(
f"{settings.API_V1_STR}/collections/",
f"{settings.API_V1_STR}/collections",
headers=user_api_key_header,
)

Expand All @@ -47,15 +47,15 @@ def test_list_collections_includes_assistant_collection(
project = get_project(db, "Dalgo")

response_before = client.get(
f"{settings.API_V1_STR}/collections/",
f"{settings.API_V1_STR}/collections",
headers=user_api_key_header,
)
assert response_before.status_code == 200

collection = get_assistant_collection(db, project)

response_after = client.get(
f"{settings.API_V1_STR}/collections/",
f"{settings.API_V1_STR}/collections",
headers=user_api_key_header,
)
assert response_after.status_code == 200
Expand Down Expand Up @@ -86,7 +86,7 @@ def test_list_collections_includes_vector_store_collection_with_fields(
collection = get_vector_store_collection(db, project)

response = client.get(
f"{settings.API_V1_STR}/collections/",
f"{settings.API_V1_STR}/collections",
headers=user_api_key_header,
)
assert response.status_code == 200
Expand Down Expand Up @@ -119,7 +119,7 @@ def test_list_collections_does_not_error_with_no_collections(
This assumes a clean DB or that there may be zero collections initially.
"""
response = client.get(
f"{settings.API_V1_STR}/collections/",
f"{settings.API_V1_STR}/collections",
headers=user_api_key_header,
)

Expand Down
Loading
Loading