Tags: NpgsqlRest/NpgsqlRest
Tags
feat(proxy): forward all automatic parameters to proxy upstream consi… …stently (v3.18.1) When an endpoint is a proxy, all server-filled parameters now forward to the upstream through one unified path: user claims, IP address, HTTP Custom Type fields, and resolved-parameter expressions. Placement mirrors the endpoint's own signature, NOT the HTTP verb: - a @body_parameter_name param carries the raw request body; - otherwise RequestParamType decides — QueryString appends to the proxy query string, BodyJson merges into the proxy JSON body (typed: numbers / booleans / embedded json / strings) when the method carries a body. Additive: the verbatim incoming request is still forwarded; the automatic params are added on top so the upstream receives the same parameter set the routine would. The previous claim/IP-only query append in BuildTargetUrl is removed and folded into the unified mechanism. Behavior change: claims/IP now follow RequestParamType (unchanged for GET/QueryString — still query; for BodyJson endpoints they now go to the body). Notes: body merge only for JSON content types (multipart/non-JSON forwarded verbatim); only expanded per-field HTTP-type params forwarded. Tests cover GET-query, POST-body (typed), param_type-query on POST, and resolved-param forwarding; existing claim/IP proxy tests pass unchanged. Full suite green (2288). See changelog/v3.18.1.md.
feat(mcp): add a JSON body to 401/403 tool-authorization challenges
The MCP server signalled an unauthorized/forbidden tools/call with the
spec-required 401/403 + WWW-Authenticate challenge but an empty body. That is
valid (the challenge lives in the header), but clients that surface the
response body — MCP Inspector, curl — showed only a blank/truncated transport
error with no hint of what failed.
WriteUnauthorized/WriteForbidden now also write a small RFC 6750-shaped JSON
body (error + error_description) via a shared WriteChallengeBodyAsync. Status
code and the WWW-Authenticate header are unchanged, so OAuth clients behave
identically; only the human/diagnostic detail improves.
401 -> {"error":"invalid_token","error_description":"This tool requires authentication. …"}
403 -> {"error":"insufficient_scope","error_description":"This tool requires a role …"}
Extended the existing 401 gate and 403 role tests to assert the content type
and exact body. Full suite green (2262); AOT publish clean.
feat: v3.16.1 — cache stampede protection for cached routine responses Make stampede protection actually fire for cached endpoints. The previous IRoutineCache probe model (Get/AddOrUpdate) could not carry SQL execution as the cache factory, so a burst of identical cold-cache requests executed the query N times and could exhaust the Postgres connection pool. - IRoutineCache.GetOrCreateAsync added as an additive default interface method, so existing custom backends keep working unchanged. - Memory and Redis backends coalesce concurrent factory invocations via an in-flight Lazy<Task>; HybridCache delegates to its built-in GetOrCreateAsync. - Scalar and passthrough proxy paths route through the factory, with the connection opened inside it so coalesced waiters never touch the DB. - Records/sets streaming path uses a per-key execution gate, since it streams rows and disables caching above MaxCacheableRows; the gate serializes the over-limit case instead of coalescing. - Tests assert execution counts on the memory backend (50->1, warm->+0, distinct keys, set within/over limit) against a live Postgres. See changelog/v3.16.1.md for honest test-coverage notes and known limitations.
feat: TryParseDate accepts Z- and offset-bearing strings DateOnly.TryParse rejects any ISO string carrying a Z suffix or numeric offset (e.g. "2026-05-20T03:00:00Z") outright, returning false. That left callers who send full ISO timestamps to a date parameter with a flat parse failure — they had to strip the time portion client-side or the request died before reaching Postgres. TryParseDate now keeps DateOnly.TryParse as the fast path (unchanged behavior for naked dates and naive date-time strings) and falls back to DateTime.TryParse + DateOnly.FromDateTime for Z- and offset-bearing inputs. The fallback honors JsonTimestampsAreUtc: when true it uses AssumeUniversal | AdjustToUniversal so the extracted date is the UTC calendar day; when false it uses bare DateTime.TryParse so the date matches the host's local calendar day. Strictly broader accepted-input set, zero change for inputs that already worked. Five new tests in HostTimeZoneIndependenceTests cover: bare date, naive date-time, Z-suffix early UTC, +02:00 offset crossing midnight, and a Z-suffix late-evening case that the legacy parser would have rejected entirely. Companion echo function host_tz_echo_date added to Database setup. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
fix: v3.15.2 — validate Policies/Profiles/Rules by shape, not by name Finishes the config-validator fix started in 3.15.1 for the two "name-keyed open dictionary" sections that share Auth:Schemes's shape: - RateLimiterOptions:Policies is now validated against a per-Type schema (FixedWindow / SlidingWindow / TokenBucket / Concurrency). User-chosen policy names no longer fail `ValidateConfigKeys: "Error"` startup, and typos / cross-type keys inside a policy now surface. - CacheOptions:Profiles uses a single flat schema (Memory / Redis / Hybrid all share the same key set). Custom profile names validate; typos like `Expirashun` now surface. - ValidationOptions:Rules moved off the open-dict whitelist into a flat schema, so typos like `Patrn` inside a rule no longer pass silently. 15 new ConfigValidationTests; 84/84 targeted tests pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PreviousNext