Conversation
|
Claude finished @alukach's task in 3m 18s —— View job Claude finished reviewing this PR
❌ Changes requested — see findings below.
No other correctness or security issues found in the diff. The core change itself is sound:
Simplify (ponytail) Nothing to cut — 💰 Estimated review cost: $0.97 · 3m17s · 36 turns |
|
📖 Docs preview deployed to https://multistore-docs-pr-152.development-seed.workers.dev
|
… infallibly `with_user_agent` stored an unchecked `String` and every forwarded request ran `self.user_agent.parse().unwrap()`, so a value with a control character panicked on the first request instead of failing at startup. The setter now takes `impl TryInto<HeaderValue>` and returns `Result`, and the gateway stores a `HeaderValue`. Constant content-type headers use `HeaderValue::from_static`, and the five hand-built XML responses (ListBuckets, list, delete result, error response, SlowDown in metering and the Workers rate limiter) go through the existing `ProxyResult::xml` constructor. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
`S3RequestSigner::sign_request` and `sign_s3_request` inserted runtime strings (date, payload hash, session token, host, authorization) with `parse().unwrap()`. A configured session token containing a control character would panic mid-request. A small `header_value` helper maps an invalid value to `ProxyError::Internal` without echoing the value, since it may be a credential. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
cbe67b7 to
200a41b
Compare
|
🚀 Latest commit deployed to https://multistore-proxy-pr-152.development-seed.workers.dev
|
…#154) * refactor: document every public item and remove production unwraps Preparation for enabling `missing_docs` and `clippy::unwrap_used` at the workspace level. Adds doc comments to the ~90 public fields, variants, and functions that lacked them, and a `# Panics` section on `Router::route`. Remaining `unwrap()` calls outside tests become either a recoverable path (`JwksCache` mutex guards recover from poisoning; the Workers response builder falls back to a 500) or an `expect` whose message states the invariant (response builders fed already-valid status and headers). `OidcBackendAuth::handle` takes the bucket config out of the context instead of re-unwrapping it inside an `if let`. Integration-test crates under `tests/` opt out of the unwrap lint at the crate level; clippy's `allow-unwrap-in-tests` covers only `#[test]` fns and `#[cfg(test)]` modules. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> * chore: adopt workspace lints, declare MSRV, lint the Workers crates in CI Adds `[workspace.lints]` with `missing_docs` and `clippy::unwrap_used` at warn (CI already runs clippy with `-D warnings`), opted into by every crate with `[lints] workspace = true`. `clippy.toml` exempts tests from the unwrap lint. Declares `rust-version = "1.89"`, the floor imposed by the dependency tree, verified with `cargo +1.89 check`. The Cloudflare crates are excluded from `default-members`, so the native clippy job never linted them. The wasm CI job now runs clippy on them, with a matching `make clippy-wasm` target and a CONTRIBUTING note. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
What I'm changing
ProxyGateway::with_user_agentaccepted any string and stored it unchecked. Every forwarded request then ranself.user_agent.parse().unwrap(), so a value containing a control character (a stray newline from an env var, say) panicked on the first backend request rather than failing when the gateway was configured. The sameparse().unwrap()pattern appeared on 10 constantcontent-typeheaders and on the runtime-built SigV4 headers in the outbound request signer, where a configured session token with a bad byte would also panic mid-request.This PR moves validation to configuration time, uses
HeaderValue::from_staticfor constants, and makes the signer's header construction return an error instead of panicking.Stacked on #151 so the new test lands in
proxy/tests.rs.How I did it
ProxyGateway(crates/core/src/proxy.rs): theuser_agentfield is now aHeaderValue.with_user_agenttakesimpl TryInto<HeaderValue>and returnsResult<Self, ProxyError>, mapping an invalid value toConfigError. The five per-request insert sites becameself.user_agent.clone(). This is a signature change for integrators: add?after the call (docs updated indocs/architecture/request-lifecycle.md).ProxyResult::xml/json(route_handler.rs):HeaderValue::from_static. The hand-built XML responses inproxy.rs(ListBuckets, list, DeleteObjects result,error_response) and the SlowDown responses incrates/meteringandexamples/cf-workers/src/rate_limit.rsnow callProxyResult::xmlinstead of assembling the header map themselves.S3RequestSigner::sign_requestandsign_s3_request(backend/request_signer.rs,backend/multipart.rs): apub(crate) fn header_value(name, value)mapsHeaderValue::from_strfailures toProxyError::Internal. The message names the header but deliberately omits the value, since it may be a credential. The canonical-headers loop drops itsheaders.get(k).unwrap()in favor ofand_then(to_str).unwrap_or("").examples/cf-workers/src/lib.rs: one-lineredundant_closurefix thatcargo clippy --fixapplied on the wasm target while I was in there.Test written first (
invalid_user_agent_is_rejected_at_configuration), confirmed it did not compile against the old API, then fixed.Test plan
cargo test— 159 core unit tests pass, all other crates greencargo clippy -- -D warningscargo check -p multistore-cf-workers --target wasm32-unknown-unknowncargo check -p multistore-cf-workers-example --target wasm32-unknown-unknowncargo fmt --check🤖 Generated with Claude Code