Skip to content

Add CORSLoggingMiddleware and verify Cloud Run origins#34

Open
KnellBalm wants to merge 2 commits intomainfrom
fix-cors-logging-middleware-1671057333786473719
Open

Add CORSLoggingMiddleware and verify Cloud Run origins#34
KnellBalm wants to merge 2 commits intomainfrom
fix-cors-logging-middleware-1671057333786473719

Conversation

@KnellBalm
Copy link
Copy Markdown
Owner

@KnellBalm KnellBalm commented Feb 10, 2026

This PR addresses a reported CORS issue in the production environment.
It introduces a CORSLoggingMiddleware to provide visibility into CORS failures by logging whether the Access-Control-Allow-Origin header is present in the response.
It also refactors backend/main.py to explicitly define the allowed origins list and ensures the middleware is registered in the correct order to capture headers.
Tests were added to verify the fix and logging behavior.


PR created automatically by Jules for task 1671057333786473719 started by @KnellBalm

Summary by Sourcery

Add middleware to log CORS behavior and ensure production CORS configuration correctly recognizes Cloud Run origins.

New Features:

  • Introduce CORSLoggingMiddleware to record CORS successes and failures based on presence of Access-Control-Allow-Origin headers.

Bug Fixes:

  • Ensure Cloud Run frontend origins are explicitly configured and CORS middleware ordering allows responses to include appropriate CORS headers in production.

Tests:

  • Add integration-style tests verifying CORS headers and corresponding log messages for allowed and disallowed origins in production mode.

- Added `CORSLoggingMiddleware` to `backend/common/middleware.py` to log CORS success/failure.
- Updated `backend/main.py` to register `CORSLoggingMiddleware` as the outermost middleware (so it sees headers added by inner middlewares like `CORSMiddleware`).
- Explicitly defined and cleaned `cloud_origins` list in `backend/main.py` to ensure the problematic origin is correctly included.
- Added `tests/test_cors_logging.py` to verify CORS behavior and logging.

Co-authored-by: KnellBalm <90038472+KnellBalm@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Feb 10, 2026

Reviewer's Guide

Introduces a CORSLoggingMiddleware to log CORS success/failure, refactors CORS origin configuration in backend/main.py so Cloud Run origins are defined before app creation and ensures middleware ordering, and adds tests to validate allowed/disallowed origins and logging behavior in production mode.

Sequence diagram for CORSLoggingMiddleware around CORSMiddleware

sequenceDiagram
    actor Browser
    participant FastAPIApp
    participant CORSLoggingMiddleware
    participant ExceptionHandlingMiddleware
    participant CORSMiddleware
    participant Endpoint

    Browser->>FastAPIApp: HTTP request with Origin header
    FastAPIApp->>CORSLoggingMiddleware: dispatch(request)
    CORSLoggingMiddleware->>ExceptionHandlingMiddleware: call_next(request)
    ExceptionHandlingMiddleware->>CORSMiddleware: call_next(request)
    CORSMiddleware->>Endpoint: call_next(request)
    Endpoint-->>CORSMiddleware: response
    CORSMiddleware-->>ExceptionHandlingMiddleware: response with ACAO header
    ExceptionHandlingMiddleware-->>CORSLoggingMiddleware: response

    CORSLoggingMiddleware->>CORSLoggingMiddleware: read origin and ACAO header
    alt ACAO present
        CORSLoggingMiddleware->>Logger: info CORS Success
    else ACAO missing
        CORSLoggingMiddleware->>Logger: warning CORS Failed
    end

    CORSLoggingMiddleware-->>FastAPIApp: response
    FastAPIApp-->>Browser: response with CORS headers
Loading

Class diagram for new CORSLoggingMiddleware and related middleware

classDiagram
    class BaseHTTPMiddleware {
        <<abstract>>
        +dispatch(request, call_next) async
    }

    class ExceptionHandlingMiddleware {
        +dispatch(request, call_next) async
    }

    class CORSLoggingMiddleware {
        +dispatch(request, call_next) async
        -log_cors_success(origin, acao)
        -log_cors_failure(origin, status_code)
    }

    BaseHTTPMiddleware <|-- ExceptionHandlingMiddleware
    BaseHTTPMiddleware <|-- CORSLoggingMiddleware

    class FastAPIApp {
        +add_middleware(middleware_class)
        +middleware_stack
    }

    FastAPIApp ..> ExceptionHandlingMiddleware : uses
    FastAPIApp ..> CORSLoggingMiddleware : uses

    class CORSMiddleware {
        +dispatch(request, call_next) async
        +allow_origins
        +allow_origin_regex
        +allow_credentials
        +allow_methods
        +allow_headers
    }

    FastAPIApp ..> CORSMiddleware : uses

    class CORSConfig {
        +cloud_origins : list
        +cloud_origin_regex : str
    }

    CORSConfig ..> CORSMiddleware : configures
    CORSLoggingMiddleware ..> Logger : logs

    class Logger {
        +info(message)
        +warning(message)
    }
Loading

File-Level Changes

Change Details Files
Add CORSLoggingMiddleware to log presence of CORS headers for requests with an Origin.
  • Implement a BaseHTTPMiddleware subclass that reads the Origin request header and inspects the access-control-allow-origin response header.
  • Log a CORS Success message at INFO level when ACAO is present, including origin and header value.
  • Log a CORS Failed message at WARNING level when ACAO is missing, including origin and response status.
  • Use the backend.common.logging.get_logger helper to obtain a namespaced logger for CORS logging.
backend/common/middleware.py
Refactor CORS configuration in the FastAPI app and register the CORS logging middleware as the outermost middleware.
  • Move Cloud Run CORS origin list and regex definitions above the lifespan context so they are available early and clearly separated from environment conditionals.
  • Ensure production and non‑production CORS middlewares still use the shared cloud_origins and cloud_origin_regex definitions.
  • Add CORSLoggingMiddleware after all other middlewares so it wraps CORSMiddleware and can observe final CORS headers on the response.
backend/main.py
Add tests to verify CORS behavior and logging for allowed and disallowed origins in production configuration.
  • Set ENV=production and mock database initialization and postgres_connection so the FastAPI app can start in tests.
  • Use TestClient to call the /health endpoint with allowed and disallowed Origin headers and assert CORS headers presence/absence.
  • Capture logs with caplog and assert that CORS Success is logged for allowed origins and CORS Failed is logged for disallowed origins.
tests/test_cors_logging.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've left some high level feedback:

  • In CORSLoggingMiddleware, get_logger is called on every request; consider instantiating the logger once at module or class level to avoid repeated lookups on the hot path.
  • Logging every successful CORS request at INFO may generate a lot of noise in production; consider downgrading success logs to DEBUG or adding sampling/feature flags so that high-volume paths remain manageable.
  • The cloud_origin_regex is defined near the top of backend/main.py; ensure it is actually wired into the CORSMiddleware configuration (e.g., via allow_origin_regex) or remove it to avoid confusion about unused CORS rules.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `CORSLoggingMiddleware`, `get_logger` is called on every request; consider instantiating the logger once at module or class level to avoid repeated lookups on the hot path.
- Logging every successful CORS request at INFO may generate a lot of noise in production; consider downgrading success logs to DEBUG or adding sampling/feature flags so that high-volume paths remain manageable.
- The `cloud_origin_regex` is defined near the top of `backend/main.py`; ensure it is actually wired into the `CORSMiddleware` configuration (e.g., via `allow_origin_regex`) or remove it to avoid confusion about unused CORS rules.

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

- Updated `tests/test_cors_logging.py` to use `mock.patch.dict` and `importlib.reload` instead of setting `os.environ` globally, preventing environment pollution.
- Updated `tests/test_integration.py` to defensively set `ENV='development'` using `mock.patch.dict` for tests that check config loading, ensuring they don't fail if `ENV` was previously set to `production`.

Co-authored-by: KnellBalm <90038472+KnellBalm@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant