Skip to content
Open
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
2 changes: 1 addition & 1 deletion docs/docs/advanced/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ RestSharp allows configuring `RestClient` using client options, as mentioned at
| `PreAuthenticate` | Gets or sets a value that indicates whether the client sends an `Authorization` header with the request. Not supported in browsers. |
| `RemoteCertificateValidationCallback` | Custom function to validate the server certificate. Normally, it's used when the server uses a certificate that isn't trusted by default. |
| `BaseHost` | Value for the `Host` header sent with each request. |
| `CookieContainer` | Custom cookie container that will be shared among all calls made by the client. Normally not required as RestSharp handles cookies without using a client-level cookie container. |
| `CookieContainer` | Custom cookie container that will be shared among all calls made by the client. Normally not required as RestSharp handles cookies without using a client-level cookie container. On iOS and Mac Catalyst, see [iOS / MAUI Cookie Handling](ios-maui-cookies.md) for additional platform-specific setup required to receive `Set-Cookie` headers. |
| `Timeout` | Client-level timeout as `TimeSpan`. Default is 100 seconds. See [Configuring Timeouts](#configuring-timeouts) for details on timeout behavior. |
| `Encoding` | Default request encoding. Override it only if you don't use UTF-8. |
| `ThrowOnDeserializationError` | Forces the client to throw if it fails to deserialize the response. Remember that not all deserialization issues forces the serializer to throw. Default is `false`, so the client will return a `RestResponse` with deserialization exception details. Only relevant for `Execute...` functions. |
Expand Down
52 changes: 52 additions & 0 deletions docs/docs/advanced/ios-maui-cookies.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
title: iOS / MAUI Cookie Handling
---

On iOS and Mac Catalyst, `Set-Cookie` response headers are silently absent from `RestResponse.Cookies` and from raw response headers, even though the same request works correctly on Android, Windows, and Linux.

## Root cause

Apple's networking stack, `NSURLSession`, intercepts `Set-Cookie` headers before they reach .NET's `HttpClient`. The cookies are stored in `NSHTTPCookieStorage` instead of being forwarded as headers, so RestSharp never sees them.

## Fix

Disable `NSURLSession`'s automatic cookie storage by supplying a custom session configuration via [`ConfigureMessageHandler`](configuration.md#using-custom-message-handler):

```csharp
#if IOS || MACCATALYST
using Foundation;

var options = new RestClientOptions(baseUrl) {
ConfigureMessageHandler = _ => {
var config = NSUrlSessionConfiguration.DefaultSessionConfiguration;
config.HttpCookieStorage = null;
config.HttpCookieAcceptPolicy = NSHttpCookieAcceptPolicy.Never;
return new NSUrlSessionHandler(config);
}
Comment thread
qodo-free-for-open-source-projects[bot] marked this conversation as resolved.
};
#endif
```

With this configuration, `NSURLSession` passes `Set-Cookie` headers through to .NET unchanged. RestSharp captures them in `RestResponse.Cookies` as it does on all other platforms.

:::warning This replaces RestSharp's configured handler
Returning a new `NSUrlSessionHandler` from `ConfigureMessageHandler` **replaces** the `HttpClientHandler` that RestSharp already configured from `RestClientOptions` — it does not wrap or extend it. Any handler-level options you set on `RestClientOptions` will **not** apply to the new handler, including:

- `Proxy`
- `Credentials` / `UseDefaultCredentials`
- `AutomaticDecompression`
- `RemoteCertificateValidationCallback`
- `ClientCertificates`

If your app relies on any of these, re-apply the equivalent configuration directly on the `NSUrlSessionHandler` instance (or on the `NSUrlSessionConfiguration`) before returning it.
:::

## Multi-tenant safety

Disabling the system cookie store is the correct approach for API clients that serve multiple users or tenants. When `NSHTTPCookieStorage` is active, cookies from one user's session can leak into a subsequent request made by the same client instance. Opting out gives RestSharp full control: cookies are scoped to the individual request via the per-request [`CookieContainer`](../usage/request.md#cookies), and nothing is persisted outside that scope.

:::warning Anti-pattern: shared CookieContainer with UseCookies = true
Do **not** set `HttpClientHandler.UseCookies = true` with a shared `CookieContainer` on the handler. This pools cookies across every request made by the client, which is unsafe for any multi-tenant scenario on any platform.

RestSharp deliberately avoids this pattern. Cookies are managed at the request level; see [Cookies](../usage/request.md#cookies) for details.
:::
4 changes: 4 additions & 0 deletions docs/docs/usage/request.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,10 @@ There is a `CookieContainer` instance on the request level. You can either assig

If your use case requires sharing cookies between requests made by the client instance, you can use the client-level `CookieContainer`, which you must provide as the options' property. You can add cookies to the container using the container API. No response cookies, however, would be auto-added to the container, but you can do it in code by getting cookies from the `Cookies` property of the response and adding them to the client-level container available via `IRestClient.Options.CookieContainer` property.

:::note iOS and Mac Catalyst
On iOS and Mac Catalyst, `NSURLSession` intercepts `Set-Cookie` headers before .NET can read them, so `RestResponse.Cookies` will be empty even on a successful request. See [iOS / MAUI Cookie Handling](../advanced/ios-maui-cookies.md) for the fix.
:::

## Request Body

RestSharp supports multiple ways to add a request body:
Expand Down