Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .agents/codecs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Content codecs implementation

- Immutable first-match-wins registry.
- JSON, XML, text and binary/raw defaults.
- Opt-in RFC 9457 Problem Details and optional CsvHelper-based `Restling.Csv`.
- Existing request payloads stay JSON unless `UseContentCodec` is enabled.
- Restore/build/tests were initially deferred; on 2026-09-02 the authorized build and all 6 codec tests passed. See `test-verification.md`.
106 changes: 63 additions & 43 deletions .agents/context.md
Original file line number Diff line number Diff line change
@@ -1,57 +1,77 @@
# Documentation context

# Restling development context
## Objective and status

- Objective: update the main Restling README with the current public APIs and quick starts, create a complete GitHub Wiki guide, and enforce the repository's multiline invocation formatting in all documentation examples.
- Status: completed.
- Objective: add extensible codecs, explicit resource ownership, complete MIME multipart support, and centralized HTTP execution with historical-behavior regression tests.
- Status: explicit context and per-request proxy configuration, including all direct-method overloads, is implemented and verified alongside the earlier work. Recovery from request-specific `ResponseEnded` failures is now implemented with a pending regression test; build and test execution for this follow-up were deferred at the user's request.

## Decisions made

- Kept the public documentation in English to match the existing repository language and public API terminology.
- Corrected the installation package ID from `AMDevIT.Restling.Core` to the published `Restling` package.
- Documented the target frameworks currently declared by the library: .NET 8, .NET 9, and .NET 10.
- Kept the README focused on installation, core capabilities, and copyable quick starts.
- Split detailed guidance into topic-specific GitHub Wiki pages and added `_Sidebar.md` for navigation.
- Derived examples and behavioral notes from the current source and tests rather than from the previous README.
- Expanded `AGENTS.md` with an explicit rule for method and constructor calls: the first argument remains beside the opening parenthesis and subsequent arguments align vertically with it. The rule explicitly applies to C# examples in Markdown.
- Reformatted every multiline C# invocation added to the README and wiki to follow that rule.
- Created only this context file, without a separate progress file, as explicitly requested by the user.
- `ContentCodecRegistry` is immutable and first-match-wins; custom codecs are prepended.
- Every `HttpClientContext` receives the four backward-compatible codecs plus the multipart reader.
- Non-JSON request serialization is explicit through `RestRequest<T>.UseContentCodec` to preserve legacy media-type relabeling.
- Problem Details validates RFC 9457 member types and exposes extension members without dereferencing URI references.
- CSV is isolated in `Restling.Csv` so CsvHelper is not a dependency of the core package.
- Clients own contexts they create and borrow externally supplied contexts by default.
- `DisposeContext` remains a compatibility alias for the explicit `ContextOwnership` enum.
- Context ownership uses flags so `HttpClient` and `HttpMessageHandler` disposal can be selected independently.
- Builder-created contexts own their `HttpClient`; supplied handlers are borrowed by default, while internally created handlers are owned.
- Legacy context and handler overloads remain available.
- Multipart writing accepts any MIME subtype and creates each part per execution.
- Buffered multipart responses preserve MIME structure and decode parts through the configured codecs.
- `multipart/x-mixed-replace` uses a separate incremental API rather than the buffered response parser.
- Internal HTTP pipeline centralizes sending, timing, decoding, error results, logging, and response lifetime without taking ownership of shared transport resources.
- Historical serializer precedence, null-payload handling, direct HttpClient version defaults, and result-versus-exception differences remain explicit at the pipeline boundary.
- After separate user approval, the untyped POST/PUT header overloads now send their payload and return an untyped result through the centralized pipeline. Other serializer/overload contracts remain unchanged.
- After explicit approval, cookie binding is centralized for directly supplied/configured native handlers. Explicit containers take precedence; otherwise the handler's existing jar and cookie policy are retained. Redirect and ownership settings remain unchanged.
- AddProxy(string proxyUri, bool allowAutoRedirect) configures directly supported native handlers, enables the context's explicit proxy, and selects HTTP redirect behavior while preserving cookies/ownership. It supports handler registration in either order; later ConfigureHandler changes remain authoritative for that handler. Custom/delegating default handlers are rejected by AddProxy; request-level alternatives use an explicit factory when needed.
- RestRequest.ProxyOptions now selects Default, Direct, or Custom routing per request. Alternative transports are cached by immutable proxy/redirect selection, share the context CookieContainer, copy HttpClient defaults, and are owned by the context. Default builders supply a factory; externally supplied/configured handlers require AddRequestHandlerFactory rather than unsafe cloning.
- All 16 direct GET/POST/PUT/DELETE variants expose RequestProxyOptions before the final CancellationToken. Serializer parameters precede it to avoid ambiguity with existing positional null calls; IRestlingClient default bodies preserve compatibility for external implementations.
- A request-specific transport that fails with `HttpRequestError.ResponseEnded` is evicted and disposed only if it is still the cached instance. The default client remains untouched, and the caller's next retry creates a fresh native handler, connection pool, and SOCKS tunnel.

## Affected files

Main repository:

- `AGENTS.md`
- `README.md`
- `.agents/context.md`

Wiki repository:

- `Home.md`
- `_Sidebar.md`
- `Installation.md`
- `Quick-Start.md`
- `Requests.md`
- `Client-Configuration.md`
- `Headers-and-Authentication.md`
- `Serialization.md`
- `Cookies.md`
- `Responses-and-Errors.md`
- `Security.md`
- Added core codec contracts, registry, implementations, problem model, and integrations.
- Added `AMDevIT.Restling.Csv`, its package README, solution entry, and test reference.
- Added codec models, helper codec, and regression tests.
- Updated the repository and NuGet package READMEs and added `.agents/codecs.md`.
- Added ownership enums, constructor overloads, builder integration, ownership regression tests, documentation, and `.agents/ownership.md`.
- Added multipart request composition, response parsing, models, limits, streaming, regression tests, documentation, and `.agents/multipart.md`.
- Added internal pipeline/streaming lease, integrated all client send paths, added 49 deterministic pipeline regression cases and test helpers, and documented the step in `.agents/http-pipeline.md`.
- Corrected the existing multipart tests' HttpMethod namespace alias.
- Recorded authorized restore/build/test results and remaining verification scope in `.agents/test-verification.md`.
- Updated POST/PUT regression tests, added loopback cookie tests/helper, and recorded the follow-up in `.agents/post-put-cookies.md`.
- Corrected HttpClientContextBuilder cookie binding, added 18 CookieBuilderTests cases, and recorded completion in `.agents/cookie-builder.md`.
- Added AddProxy to the builder/interface, 43 ProxyBuilderTests cases, proxy sections in both READMEs, and `.agents/proxy-builder.md`.
- Added request routing models/pool, integrated transport selection into the centralized buffered/streaming pipeline, added 16 RequestProxyOverrideTests cases, documented usage, and recorded `.agents/request-proxy.md`.
- Added direct proxy overloads to RestlingClient/IRestlingClient and an aggregate test that invokes all 16 signatures and verifies CancellationToken is last.
- Added targeted `ResponseEnded` recovery across the request transport pool and HTTP pipeline, plus a deterministic loopback regression. See `.agents/response-ended-recovery.md`.

## Checks performed

- Compared documented types, overloads, properties, serializer choices, handler behavior, cookie APIs, success codes, and security defaults against the current source files and tests.
- Ran `git diff --check` in both repositories: the edited Markdown files passed; only line-ending conversion warnings were reported.
- Checked all edited Markdown files for balanced fenced code blocks: passed.
- Checked relative links between GitHub Wiki pages and their target files: passed.
- Searched for the obsolete package ID and known example/version mistakes: no remaining matches.
- Checked C# fences in the README and wiki for invocations ending immediately after an opening parenthesis: no matches.
- Checked continuation columns for multiline method and constructor calls: every subsequent argument aligns with the first argument.
- Did not run `dotnet restore`, `dotnet build`, or tests because the user explicitly limited verification to Markdown files.
- Fetched the remote repository; the working branch required no pull or merge.
- Reviewed CsvHelper 33.1.0 public read/write APIs and RFC 9457 member rules.
- Re-fetched before resuming; the branch remained aligned with `origin/main`.
- Parsed all project XML, checked solution entries, Markdown fences, public method comments, codec registrations, and `git diff --check`.
- Performed static ownership checks for constructor defaults, compatibility aliases, disposal flags, and builder handler behavior.
- Reviewed RFC 2046, RFC 7578, RFC 8710, and the IANA multipart registry before defining multipart scope.
- Restore/build/test execution was initially deferred at the user's request, then explicitly authorized and completed on 2026-09-02.
- Fetched again for pipeline completion: HEAD is 3 commits ahead of origin/main, 0 behind; no pull/merge needed.
- Statically compared pipeline behavior against the pre-refactor implementation, verified centralized send call sites, and checked the diff for whitespace errors. These checks do not establish that the new tests pass.
- Authorized verification: restore passed; solution build passed for Core/CSV net8.0, net9.0, net10.0 and tests net10.0 with 0 warnings/errors.
- Runtime verification: 49 pipeline, 6 codec, 7 ownership, 6 multipart, and 6 XML security cases passed (74 total; 0 failed/skipped) on net10.0. TRX reports are under `TestResults/http-pipeline/`.
- Follow-up verification: reproduced the POST/PUT bug with 4 failing tests before fixing it. Latest run has 57 pipeline + 25 existing codec/ownership/multipart/security cases passing; 10/18 cookie cases pass and 8 expose the builder issue. Reports are under `TestResults/post-put-cookies/`.
- Cookie-builder completion: the preceding eight cookie failures are resolved. Targeted cookie tests: 36/36 passed; full selected suite: 118/118 passed, 0 failed/skipped. Solution build passed with 0 warnings/errors. Reports are under `TestResults/cookie-builder/`.
- Proxy completion: fetched Task-NewCodecs (aligned with upstream), restored and built successfully with 0 warnings/errors. All 161 selected local tests passed (118 existing + 43 proxy), including actual loopback proxy redirects/cookie persistence with both native handlers. Reports are under `TestResults/proxy/`; git diff --check passed.
- Per-request proxy completion: after the user pulled two upstream commits, fetch confirmed alignment. Restore succeeded; the final build passed across Core/CSV net8/net9/net10 and tests net10 with 0 warnings/errors. An intermediate test-triggered build emitted one generated MSTest CS8892 warning, absent from the final build. Targeted proxy tests passed 59/59 and the selected regression passed 177/177. Reports are under `TestResults/request-proxy/`; git diff --check passed.
- Direct-overload follow-up: the 60 proxy tests and all 178 selected regression tests passed. Every new signature was exercised through IRestlingClient; reports are in TestResults/request-proxy/.
- Follow-up multi-target build passed with 0 errors; the only warning was the previously observed CS8892 in generated MSTest entry-point code.
- `ResponseEnded` recovery follow-up: fetched the remote and confirmed the clean branch was aligned with its upstream before editing. The resulting targeted diff was inspected. No restore, build, or tests were run at the user's request.

## Open issues and recommended next step

- No documentation blocker remains.
- The wiki repository also contains a staged `.gitignore` outside this task. It was left untouched because the user limited changes to Markdown files; `git diff --cached --check` reports existing trailing whitespace on its line 9.
- Recommended next step: review the rendered README and GitHub Wiki after publishing, then commit and push the two repositories independently.
- No known failures remain in the selected local suites. Opaque custom/delegating-handler cookie processing remains the caller's responsibility; only directly supported native handlers are bound automatically.
- Runtime verification on other target frameworks/platforms and coverage/baseline comparison remain outside this run.
- Integration tests against httpbin remain separate and were not run.
- The new `ResponseEndedInvalidatesAlternativeTransport` regression and related proxy suites remain pending execution.
- POST/PUT payload omission is fixed; general serializer-precedence normalization remains separate.
- Per-request direct/custom proxy selection and convenience overloads are implemented. HTTPS CONNECT/TLS proxy, SOCKS handshakes, real proxy authentication exchanges, other runtime/platform executions, and bounded cache eviction remain untested/out of scope.
41 changes: 41 additions & 0 deletions .agents/cookie-builder.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Cookie builder correction

## Objective and status

The user explicitly approved correcting the cookie builder after the loopback tests exposed eight failures. The correction is implemented and verified: all 118 selected local regression cases pass, including all 36 cookie cases.

## Decisions

- `ResolveCookieContainer` is the single binding point for directly supplied SocketsHttpHandler and HttpClientHandler instances and handlers created through ConfigureHandler.
- An explicit AddCookieContainer selection takes precedence, regardless of whether it precedes or follows AddHandler. It is also available to a newly created ConfigureHandler callback.
- Without an explicit container, the native handler's existing jar is used by the context and by AddCookie/AddCookies. Existing cookie state is not replaced.
- Replacing a handler without an explicit container adopts the replacement handler's jar rather than copying unrelated cookie state.
- Selecting an explicit container enables native cookie handling, matching the previous AddCookieContainer behavior. Build does not subsequently override an intentional UseCookies=false setting made in ConfigureHandler. Without an explicit container, native UseCookies is preserved.
- Container assignments and UseCookies setters are skipped when no change is necessary, allowing repeated Build calls with a previously started borrowed handler.
- A separate fallback container preserves existing custom-handler behavior without turning an implicit fallback into an explicit override for later native handlers.
- Cookie clearing selects a new jar without destroying the old externally owned jar.
- Redirect and resource ownership policies are unchanged. Native handlers continue to enforce response-cookie scope, Secure, and deletion rules; no manual Cookie header forwarding is introduced.
- Opaque custom handlers and delegating-handler chains are not introspected; they remain responsible for their own cookie processing. This change targets the confirmed direct native-handler/container binding defect, not all cookie metadata/API semantics.

## Affected files

- `Sources/AMDevIT.Restling/AMDevIT.Restling.Core/Network/Builders/HttpClientContextBuilder.cs`
- `Sources/AMDevIT.Restling/AMDevIT.Restling.Tests/CookieBuilderTests.cs` (18 new cases)
- Existing `CookiePersistenceTests` (18 cases, previously 8 failing) run unchanged.
- Progressive context and prior follow-up status notes.

## Verification

- Fetch succeeded: HEAD is 4 commits ahead of origin/main, 0 behind; no pull/merge required.
- Restore succeeded with authorized access to NuGet configuration/cache.
- Targeted cookie run: 36 passed, 0 failed/skipped.
- Full solution build: Core/CSV net8.0, net9.0, net10.0 and tests net10.0; 0 warnings and 0 errors.
- Full selected regression run: 118 passed, 0 failed, 0 skipped on net10.0. This includes 57 pipeline, 6 codec, 7 ownership, 6 multipart, 6 XML security, 18 cookie persistence, and 18 cookie builder cases.
- The original eight cookie reproductions are now green, including supplied/configured handlers, AddCookieContainer/AddHandler ordering, consecutive calls, and automatic redirects.
- Loopback tests also cover manual redirects, path/domain/Secure filtering of response cookies, deletion, client recreation, and rebuilding with an active handler.
- `git diff --check` passed.
- Reports: `TestResults/cookie-builder/cookie-builder-targeted.trx` and `TestResults/cookie-builder/cookie-builder-regression.trx`.

## Remaining scope

No known failures remain in the selected local suites. httpbin integration tests, runtime execution on other frameworks/mobile platforms, coverage measurement, and general serializer-precedence normalization remain outside this change.
Loading