-
Notifications
You must be signed in to change notification settings - Fork 0
Feature/better middleware #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: development
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // Enforce max buffer | ||
| if w.maxBody > 0 && int64(w.body.Len()+len(p)) > w.maxBody { | ||
| w.tooLarge = true | ||
| // We still buffer up to maxBody, and then ignore the rest (or you can stop buffering entirely) | ||
| remaining := int(w.maxBody - int64(w.body.Len())) | ||
| if remaining > 0 { | ||
| _, _ = w.body.Write(p[:remaining]) | ||
| } | ||
| return len(p), nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid truncating responses beyond MaxBodyBytes
The buffering writer drops any bytes beyond MaxBodyBytes while still returning len(p) and only commits the buffered prefix. Because the response validator later commits w.body instead of the full stream, any handler that writes more than the 2 MiB default will silently return a truncated, corrupt payload even in audit mode instead of simply skipping validation. This breaks large downloads and any endpoint that legitimately returns bodies above the cap.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chatgpt-codex-connector
@copilot
Should we raise a 413 Content Too Large exception here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To use Codex here, create an environment for this repo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR implements OpenAPI validation middleware for the DRS server with both request and response validation capabilities. The implementation uses kin-openapi for validation with configurable audit and enforce modes, allowing safe production rollout. The PR also adds GA4GH DRS-compliant service info and health check endpoints.
- Adds comprehensive OpenAPI request/response validation middleware with buffering support
- Implements
/service-infoendpoint returning GA4GH DRS Service Info metadata - Adds
/healthzhealth check endpoint for monitoring and orchestration systems
Reviewed changes
Copilot reviewed 10 out of 12 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| internal/apigen/go.mod | Updates Go version to 1.24.0 and upgrades golang.org/x dependencies |
| internal/apigen/go.sum | Adds checksums for updated dependencies |
| docs/adr-0001-request-response-validation.md | Comprehensive ADR documenting the OpenAPI validation architecture, configuration, and implementation approach |
| cmd/server/middleware/openapi_validator.go | Enhances request validator with route attachment, security handling, and lenient mode logging |
| cmd/server/middleware/openapi_response_validator.go | Implements response validation middleware with audit/enforce modes and buffering |
| cmd/server/middleware/openapi_response_log.go | Adds detailed logging for OpenAPI validation failures with redaction support |
| cmd/server/middleware/buffering_writer.go | Implements buffering writer for late-commit response validation |
| cmd/server/middleware/logging_middleware.go | Provides request/response logging with auth header redaction |
| cmd/server/handlers/service_info.go | Implements GA4GH DRS Service Info endpoint with static metadata |
| cmd/server/handlers/healthz.go | Adds health check endpoint |
| cmd/server/main.go | Integrates request and response validators into middleware chain |
| cmd/server/service_info.go | Removes old service info implementation (replaced by handlers/service_info.go) |
Comments suppressed due to low confidence (1)
cmd/server/middleware/openapi_validator.go:36
- Empty comment line without any explanation. This should either be removed or have a descriptive comment explaining why the servers are being neutralized. Consider replacing with something like "// Neutralize server URLs to allow matching requests regardless of host/base path".
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "drs_version": "1.3.0", | ||
| "service_url": "https://drs.example.org", | ||
| "maxBulkRequestLength": 1000, // Deprecated | ||
| "timestamp": "2024-01-01T12:00:00.000Z", |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The timestamp "2024-01-01T12:00:00.000Z" appears to be a placeholder or test value from the past. For a production service, this should either be dynamically generated to reflect the actual current time or updated to a more recent date if it represents a static deployment timestamp.
| "createdAt": "2020-01-01T00:00:00.000Z", | ||
| "updatedAt": "2020-01-02T00:00:00.000Z", |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The dates "2020-01-01T00:00:00.000Z" and "2020-01-02T00:00:00.000Z" for createdAt and updatedAt are placeholder values from 5 years ago. For a production service, these should be replaced with actual service deployment dates or removed if they're not meaningful for this implementation.
| // Construct a JSON response using Gin's `H` helper, which is a | ||
| // shorthand for `map[string]any`. The response includes: | ||
| // * `name`: a static identifier for this service. | ||
| // * `version`: the service version read from the SERVICE_VERSION | ||
| // environment variable (may be empty if not set). | ||
| // * `timestamp`: the current UTC time, formatted as an RFC3339Nano string. |
Copilot
AI
Dec 23, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment references outdated handler behavior. The comment mentions "version" being read from SERVICE_VERSION environment variable and "timestamp" being the current UTC time, but the actual implementation now returns static values from the serviceInfoResponse map defined above. This comment should be updated to reflect that the handler returns a static GA4GH DRS Service Info structure.
| // Construct a JSON response using Gin's `H` helper, which is a | |
| // shorthand for `map[string]any`. The response includes: | |
| // * `name`: a static identifier for this service. | |
| // * `version`: the service version read from the SERVICE_VERSION | |
| // environment variable (may be empty if not set). | |
| // * `timestamp`: the current UTC time, formatted as an RFC3339Nano string. | |
| // Return the static GA4GH DRS Service Info structure defined in | |
| // `serviceInfoResponse` above. This includes fields such as: | |
| // * top-level service metadata (e.g. `id`, `name`, `type`, `version`) | |
| // * timestamps (`createdAt`, `updatedAt`, `timestamp`) | |
| // * organization and contact details | |
| // * DRS-specific capabilities and limits under the `drs` key. |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Initial plan * Switch to mkdocs-material theme with Mermaid support Co-authored-by: bwalsh <47808+bwalsh@users.noreply.github.com> * Add SRI integrity hash for Mermaid.js security Co-authored-by: bwalsh <47808+bwalsh@users.noreply.github.com> * Add DOMContentLoaded event listener for Mermaid initialization Co-authored-by: bwalsh <47808+bwalsh@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: bwalsh <47808+bwalsh@users.noreply.github.com>
Context
The DRS server is implemented in Go (Gin) with server scaffolding generated from OpenAPI. Contract correctness matters for interoperability and operational safety. The OpenAPI spec includes deep schemas and recursive references (e.g.,
DrsObject → ContentsObject → DrsObject), making “generator-only correctness” insufficient.We need:
Decision
Implement OpenAPI validation middleware using kin-openapi (
openapi3filter) as the validation engine.Request validation: enforce at runtime by default (reject invalid requests)
Response validation: buffering + late-commit middleware with two modes:
Black-box contract testing complements runtime validation in CI.
Summary
flowchart TB Client[Client] -->|HTTP Request| Gin[gin Engine] subgraph MiddlewareChain[Middleware Chain] LogReq[Request Logging redact auth] --> ReqVal[OpenAPI Request Validation enforce] ReqVal --> Handler[Application Handlers generated] Handler --> RespVal[OpenAPI Response Validation audit or enforce] RespVal --> Commit[Late Commit Writer buffered] end Gin --> MiddlewareChain -->|HTTP Response| Client Spec[OpenAPI Spec local or embedded] --> ReqVal Spec --> RespVal CI[CI Pipeline] --> Contract[Contract Tests] Spec --> Contract Contract --> Report[Fail build on violations]See docs/adr-0001-request-response-validation.md
Changes
GET /service-inforoute incmd/server/service_info.go.id,name,description,organization,contactUrl,documentationUrl,environment, etc.).version,drs_version,service_url).maxBulkRequestLengthretained for backward compatibility.drssection with implementation details (bulk limits, object counts, upload/delete capabilities, validation flags, etc.).http.StatusOKand the staticserviceInfoResponsemap.Motivation
/service-info, and middleware attempts to validate requests and responses for this path.FindRouteand security validation failures were blocking proper validation; this change wires up a concrete implementation of the endpoint.Testing
GET /service-info:200 OKresponse.