Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 10, 2026

Currently only the last request is stored, making it unusable for parallel test runs where multiple requests need to be captured and inspected.

Changes

  • app.py: New Flask app that stores all requests in a memory-capped deque
    • /__all_requests__ (GET) - Returns all captured requests
    • /__find_request__ (GET) - Find specific requests by header/body values
    • /__clear__ (POST/DELETE) - Clears request history for test isolation
    • /__last_request__ - Preserved for backward compatibility
    • Uses collections.deque with configurable maxlen to prevent unbounded memory growth
  • Dockerfile: Copies local app.py over upstream version
  • README.md: Documents new API endpoints and environment variables
  • test_app.py: Comprehensive test suite with 28 tests covering all API routes
  • .github/workflows/tests.yml: GitHub Actions workflow to run tests on push/PR

Environment Variables

Variable Default Description
MAX_REQUEST_HISTORY 1000 Maximum number of requests to store in history. Older requests are automatically removed when this limit is exceeded.

Usage

# Make some requests
curl http://localhost:5000/webhook -d '{"event": "test1"}'
curl http://localhost:5000/webhook -d '{"event": "test2"}'

# Get all captured requests
curl http://localhost:5000/__all_requests__

# Find specific request by header value
curl "http://localhost:5000/__find_request__?header_X-Custom-Id=abc123"

# Find specific request by body content
curl "http://localhost:5000/__find_request__?body=test-event"

# Combine multiple filters
curl "http://localhost:5000/__find_request__?method=POST&header_Content-Type=application/json"

# Clear between test runs
curl -X POST http://localhost:5000/__clear__

Testing

Tests cover:

  • Catch-all endpoint (GET, POST, PUT, DELETE, PATCH, custom headers)
  • /__last_request__ endpoint
  • /__all_requests__ endpoint
  • /__find_request__ endpoint (method, body, header, URL filters)
  • /__clear__ endpoint
  • Request capture (timestamp, URL, body)
  • Deque max length configuration
Original prompt

This project currently has a limitation in that you can only get the LAST request that was made. Add the ability to capture ALL requests, to support using in parallel test runs.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Summary by CodeRabbit

  • New Features

    • Implemented an HTTP request capturing service that logs all incoming requests with detailed metadata and provides query endpoints to retrieve the latest request, all requests, search by headers/body/method, and clear the request history.
  • Documentation

    • Added API Endpoints documentation describing available endpoints with practical usage examples.
  • Chores

    • Updated Docker and project configuration files.

✏️ Tip: You can customize this high-level summary in your review settings.

Copilot AI self-assigned this Jan 10, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 10, 2026

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This pull request introduces a new HTTP Request Catcher service built with Flask. The implementation includes a Flask application (app.py) that captures and provides access to HTTP requests through in-memory storage and multiple query endpoints. Supporting changes include Docker configuration to copy the app.py file into the container, README documentation describing the available API endpoints, and .gitignore patterns for Python cache files.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main objective of the PR: adding Flask-based request capture functionality with support for storing and retrieving all requests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

Copilot AI and others added 2 commits January 10, 2026 14:13
Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
Copilot AI changed the title [WIP] Add ability to capture all requests for parallel testing Add support for capturing all requests Jan 10, 2026
Copilot AI requested a review from abnegate January 10, 2026 14:16
@abnegate
Copy link
Member

@copilot Need the ability to fetch a specific request based on it's header/body values

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 10, 2026

@copilot Need the ability to fetch a specific request based on it's header/body values

Added /__find_request__ endpoint in commit 20067e9. You can now search requests by:

  • Header value: ?header_X-Custom-Id=abc123
  • Body content: ?body=test-event
  • HTTP method: ?method=POST
  • URL content: ?url=/webhook

Multiple filters can be combined: ?method=POST&header_Content-Type=application/json

@abnegate abnegate marked this pull request as ready for review January 12, 2026 08:27
@abnegate
Copy link
Member

@coderabbitai full review

@coderabbitai
Copy link

coderabbitai bot commented Jan 12, 2026

✅ Actions performed

Full review triggered.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
Dockerfile (2)

2-2: Python 3.6 reached end-of-life in December 2021 and no longer receives security updates.

The base image uses Python 3.6, which is unsupported. Upgrade to a currently maintained version (Python 3.11 or later for support through 2027+, or at minimum Python 3.10 for support through October 2026) along with a newer Alpine version.


17-17: Upgrade Flask — CVE-2023-30861 vulnerability present.

Flask 1.1.2 (released April 2020) is affected by CVE-2023-30861, a cache-poisoning and session cookie handling vulnerability. This version is no longer actively supported. Upgrade to Flask 2.2.5, 2.3.2, or later.

🤖 Fix all issues with AI agents
In @app.py:
- Around line 7-8: The global all_requests list can grow without bound; replace
it with a collections.deque configured with a maxlen pulled from configuration
(or an environment variable) to cap memory, e.g. all_requests =
deque(maxlen=MAX_REQUEST_HISTORY), keep last_request as-is, and update
clear_requests() to call all_requests.clear() and update find_request() to
iterate over the deque (iteration semantics are identical to a list); ensure
MAX_REQUEST_HISTORY is documented and defaulted to a reasonable value and that
any code that assumed list-specific methods is adjusted to deque-compatible
calls.
🧹 Nitpick comments (3)
app.py (3)

3-3: Unused import: environ

The environ import from os is not used anywhere in the file.

Proposed fix
-from os import environ

70-72: Unused path parameter is intentional.

The path parameter is required by Flask's routing mechanism for the catch-all pattern but doesn't need to be used in the function body. The static analysis warning can be safely ignored, or you can prefix it with an underscore to indicate it's intentionally unused.

Optional: prefix with underscore
-def catch(path):
+def catch(_path):

36-54: Header normalization is repeated for each filter check.

The lowercase header dictionary is rebuilt on every request in the loop. Consider extracting it once per request for efficiency.

Proposed optimization
     for req in all_requests:
         match = True
+        req_headers_lower = {k.lower(): v for k, v in req['headers'].items()}
         
         for key, value in request.args.items():
             if key.startswith('header_'):
                 header_name = key[7:]  # Remove 'header_' prefix
-                req_headers = {k.lower(): v for k, v in req['headers'].items()}
-                if req_headers.get(header_name.lower()) != value:
+                if req_headers_lower.get(header_name.lower()) != value:
                     match = False
                     break
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a611aa7 and 20067e9.

📒 Files selected for processing (4)
  • .gitignore
  • Dockerfile
  • README.md
  • app.py
🧰 Additional context used
🪛 Ruff (0.14.10)
app.py

72-72: Unused function argument: path

(ARG001)


88-88: Possible binding to all interfaces

(S104)

🔇 Additional comments (4)
.gitignore (1)

1-3: LGTM!

Standard Python bytecode ignore patterns appropriate for the Flask application.

Dockerfile (1)

27-28: Intentional override of upstream app.py is clear.

The ordering ensures the local app.py replaces the upstream version. This approach works correctly for the intended behavior.

app.py (1)

87-88: Binding to all interfaces is appropriate for Docker.

The static analysis warning about binding to 0.0.0.0 is a false positive in this context—it's required for the container to accept external connections.

README.md (1)

31-75: Documentation is comprehensive and aligns with implementation.

The API endpoint documentation is clear, includes practical examples, and accurately reflects the functionality implemented in app.py.

@abnegate
Copy link
Member

@copilot In @app.py around lines 7 - 8, The global all_requests list can grow without
bound; replace it with a collections.deque configured with a maxlen pulled from
configuration (or an environment variable) to cap memory, e.g. all_requests =
deque(maxlen=MAX_REQUEST_HISTORY), keep last_request as-is, and update
clear_requests() to call all_requests.clear() and update find_request() to
iterate over the deque (iteration semantics are identical to a list); ensure
MAX_REQUEST_HISTORY is documented and defaulted to a reasonable value and that
any code that assumed list-specific methods is adjusted to deque-compatible
calls.

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 12, 2026

@copilot In @app.py around lines 7 - 8, The global all_requests list can grow without
bound; replace it with a collections.deque configured with a maxlen pulled from
configuration (or an environment...

Implemented in commit 34ca91a. Changed all_requests from list to collections.deque with configurable maxlen. The MAX_REQUEST_HISTORY environment variable controls the limit (default: 1000). Updated clear_requests() to use .clear() and get_all_requests() to convert to list for JSON serialization.

@abnegate
Copy link
Member

@copilot Add tests covering all API routes and a github workflow that runs them

Co-authored-by: abnegate <5857008+abnegate@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jan 12, 2026

@copilot Add tests covering all API routes and a github workflow that runs them

Added in commit ef1f96f:

Tests (test_app.py) - 28 tests covering:

  • Catch endpoint (GET, POST, PUT, DELETE, PATCH, headers)
  • /__last_request__ endpoint
  • /__all_requests__ endpoint
  • /__find_request__ endpoint (method, body, header, URL filters)
  • /__clear__ endpoint (POST and DELETE)
  • Request capture (timestamp, URL, body)
  • Deque max length configuration

GitHub Workflow (.github/workflows/tests.yml) - Runs on push/PR to main/master branches using Python 3.11 and pytest.

@abnegate abnegate merged commit acb4078 into main Jan 12, 2026
2 checks passed
@abnegate abnegate deleted the copilot/add-support-for-all-requests branch January 12, 2026 13:48
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.

2 participants