Skip to content

Commit 4511fab

Browse files
Restore 2-param AddCookie(name, value) overload (#2351)
* Restore 2-param AddCookie(name, value) overload PR #1966 replaced the simple AddCookie(name, value) with a 4-param overload requiring domain upfront, breaking the public API. This restores the 2-param form by deferring domain resolution to execution time using CookieContainer.Add(Uri, Cookie). - Add _cookies pending list and PendingCookies accessor to RestRequest - Add AddCookie(name, value) extension that stores cookies for deferred resolution alongside the existing 4-param AddCookie overload - Resolve pending cookies at execution time in RestClient.Async.cs using the request URL to infer domain - Update cookie documentation across all doc versions to show both forms - Fix Cookes typo in docs Closes #2284 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Address code review feedback for AddCookie pending cookies - Wrap cookieContainer.Add in try/catch for CookieException, matching the existing pattern in CookieContainerExtensions.AddCookies - Clear pending cookies after transfer to avoid duplicate adds on request retry/reuse - Make PendingCookies public so BeforeRequest interceptors and authenticators can observe cookies added via the 2-param overload - Clarify docs: 4-param AddCookie populates CookieContainer immediately, 2-param stores in PendingCookies until execution Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3831d52 commit 4511fab

8 files changed

Lines changed: 74 additions & 11 deletions

File tree

docs/docs/usage/request.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,11 +227,17 @@ You can add cookies to a request using the `AddCookie` method:
227227
request.AddCookie("foo", "bar");
228228
```
229229

230+
The simple two-parameter form defers domain resolution until execution time — the cookie domain is inferred from the request URL. If you need to specify the path and domain explicitly, use the four-parameter overload:
231+
232+
```csharp
233+
request.AddCookie("foo", "bar", "/path", "example.com");
234+
```
235+
230236
RestSharp will add cookies from the request as cookie headers and then extract the matching cookies from the response. You can observe and extract response cookies using the `RestResponse.Cookies` properties, which has the `CookieCollection` type.
231237

232-
However, the usage of a default URL segment parameter is questionable as you can just include the parameter value to the base URL of the client. There is, however, a `CookieContainer` instance on the request level. You can either assign the pre-populated container to `request.CookieContainer`, or let the container be created by the request when you call `AddCookie`. Still, the container is only used to extract all the cookies from it and create cookie headers for the request instead of using the container directly. It's because the cookie container is normally configured on the `HttpClientHandler` level and cookies are shared between requests made by the same client. In most of the cases this behaviour can be harmful.
238+
There is a `CookieContainer` instance on the request level. You can either assign the pre-populated container to `request.CookieContainer`, or let the container be created automatically at execution time. The four-parameter `AddCookie` overload populates the container immediately, while the two-parameter form stores cookies in `PendingCookies` until the request is executed. The container is used to extract all the cookies from it and create cookie headers for the request instead of using the container directly. It's because the cookie container is normally configured on the `HttpClientHandler` level and cookies are shared between requests made by the same client. In most of the cases this behaviour can be harmful.
233239

234-
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 `Cookes` property of the response and adding them to the client-level container available via `IRestClient.Options.CookieContainer` property.
240+
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.
235241

236242
## Request Body
237243

docs/versioned_docs/version-v110/usage/usage.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,11 +230,17 @@ You can add cookies to a request using the `AddCookie` method:
230230
request.AddCookie("foo", "bar");
231231
```
232232

233+
The simple two-parameter form defers domain resolution until execution time — the cookie domain is inferred from the request URL. If you need to specify the path and domain explicitly, use the four-parameter overload:
234+
235+
```csharp
236+
request.AddCookie("foo", "bar", "/path", "example.com");
237+
```
238+
233239
RestSharp will add cookies from the request as cookie headers and then extract the matching cookies from the response. You can observe and extract response cookies using the `RestResponse.Cookies` properties, which has the `CookieCollection` type.
234240

235-
However, the usage of a default URL segment parameter is questionable as you can just include the parameter value to the base URL of the client. There is, however, a `CookieContainer` instance on the request level. You can either assign the pre-populated container to `request.CookieContainer`, or let the container be created by the request when you call `AddCookie`. Still, the container is only used to extract all the cookies from it and create cookie headers for the request instead of using the container directly. It's because the cookie container is normally configured on the `HttpClientHandler` level and cookies are shared between requests made by the same client. In most of the cases this behaviour can be harmful.
241+
There is a `CookieContainer` instance on the request level. You can either assign the pre-populated container to `request.CookieContainer`, or let the container be created automatically at execution time. The four-parameter `AddCookie` overload populates the container immediately, while the two-parameter form stores cookies in `PendingCookies` until the request is executed. The container is used to extract all the cookies from it and create cookie headers for the request instead of using the container directly. It's because the cookie container is normally configured on the `HttpClientHandler` level and cookies are shared between requests made by the same client. In most of the cases this behaviour can be harmful.
236242

237-
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 `Cookes` property of the response and adding them to the client-level container available via `IRestClient.Options.CookieContainer` property.
243+
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.
238244

239245
### Request Body
240246

docs/versioned_docs/version-v111/usage/request.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,11 +208,17 @@ You can add cookies to a request using the `AddCookie` method:
208208
request.AddCookie("foo", "bar");
209209
```
210210

211+
The simple two-parameter form defers domain resolution until execution time — the cookie domain is inferred from the request URL. If you need to specify the path and domain explicitly, use the four-parameter overload:
212+
213+
```csharp
214+
request.AddCookie("foo", "bar", "/path", "example.com");
215+
```
216+
211217
RestSharp will add cookies from the request as cookie headers and then extract the matching cookies from the response. You can observe and extract response cookies using the `RestResponse.Cookies` properties, which has the `CookieCollection` type.
212218

213-
However, the usage of a default URL segment parameter is questionable as you can just include the parameter value to the base URL of the client. There is, however, a `CookieContainer` instance on the request level. You can either assign the pre-populated container to `request.CookieContainer`, or let the container be created by the request when you call `AddCookie`. Still, the container is only used to extract all the cookies from it and create cookie headers for the request instead of using the container directly. It's because the cookie container is normally configured on the `HttpClientHandler` level and cookies are shared between requests made by the same client. In most of the cases this behaviour can be harmful.
219+
There is a `CookieContainer` instance on the request level. You can either assign the pre-populated container to `request.CookieContainer`, or let the container be created automatically at execution time. The four-parameter `AddCookie` overload populates the container immediately, while the two-parameter form stores cookies in `PendingCookies` until the request is executed. The container is used to extract all the cookies from it and create cookie headers for the request instead of using the container directly. It's because the cookie container is normally configured on the `HttpClientHandler` level and cookies are shared between requests made by the same client. In most of the cases this behaviour can be harmful.
214220

215-
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 `Cookes` property of the response and adding them to the client-level container available via `IRestClient.Options.CookieContainer` property.
221+
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.
216222

217223
## Request Body
218224

docs/versioned_docs/version-v112/usage/request.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,11 +227,17 @@ You can add cookies to a request using the `AddCookie` method:
227227
request.AddCookie("foo", "bar");
228228
```
229229

230+
The simple two-parameter form defers domain resolution until execution time — the cookie domain is inferred from the request URL. If you need to specify the path and domain explicitly, use the four-parameter overload:
231+
232+
```csharp
233+
request.AddCookie("foo", "bar", "/path", "example.com");
234+
```
235+
230236
RestSharp will add cookies from the request as cookie headers and then extract the matching cookies from the response. You can observe and extract response cookies using the `RestResponse.Cookies` properties, which has the `CookieCollection` type.
231237

232-
However, the usage of a default URL segment parameter is questionable as you can just include the parameter value to the base URL of the client. There is, however, a `CookieContainer` instance on the request level. You can either assign the pre-populated container to `request.CookieContainer`, or let the container be created by the request when you call `AddCookie`. Still, the container is only used to extract all the cookies from it and create cookie headers for the request instead of using the container directly. It's because the cookie container is normally configured on the `HttpClientHandler` level and cookies are shared between requests made by the same client. In most of the cases this behaviour can be harmful.
238+
There is a `CookieContainer` instance on the request level. You can either assign the pre-populated container to `request.CookieContainer`, or let the container be created automatically at execution time. The four-parameter `AddCookie` overload populates the container immediately, while the two-parameter form stores cookies in `PendingCookies` until the request is executed. The container is used to extract all the cookies from it and create cookie headers for the request instead of using the container directly. It's because the cookie container is normally configured on the `HttpClientHandler` level and cookies are shared between requests made by the same client. In most of the cases this behaviour can be harmful.
233239

234-
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 `Cookes` property of the response and adding them to the client-level container available via `IRestClient.Options.CookieContainer` property.
240+
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.
235241

236242
## Request Body
237243

docs/versioned_docs/version-v113/usage/request.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,11 +227,17 @@ You can add cookies to a request using the `AddCookie` method:
227227
request.AddCookie("foo", "bar");
228228
```
229229

230+
The simple two-parameter form defers domain resolution until execution time — the cookie domain is inferred from the request URL. If you need to specify the path and domain explicitly, use the four-parameter overload:
231+
232+
```csharp
233+
request.AddCookie("foo", "bar", "/path", "example.com");
234+
```
235+
230236
RestSharp will add cookies from the request as cookie headers and then extract the matching cookies from the response. You can observe and extract response cookies using the `RestResponse.Cookies` properties, which has the `CookieCollection` type.
231237

232-
However, the usage of a default URL segment parameter is questionable as you can just include the parameter value to the base URL of the client. There is, however, a `CookieContainer` instance on the request level. You can either assign the pre-populated container to `request.CookieContainer`, or let the container be created by the request when you call `AddCookie`. Still, the container is only used to extract all the cookies from it and create cookie headers for the request instead of using the container directly. It's because the cookie container is normally configured on the `HttpClientHandler` level and cookies are shared between requests made by the same client. In most of the cases this behaviour can be harmful.
238+
There is a `CookieContainer` instance on the request level. You can either assign the pre-populated container to `request.CookieContainer`, or let the container be created automatically at execution time. The four-parameter `AddCookie` overload populates the container immediately, while the two-parameter form stores cookies in `PendingCookies` until the request is executed. The container is used to extract all the cookies from it and create cookie headers for the request instead of using the container directly. It's because the cookie container is normally configured on the `HttpClientHandler` level and cookies are shared between requests made by the same client. In most of the cases this behaviour can be harmful.
233239

234-
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 `Cookes` property of the response and adding them to the client-level container available via `IRestClient.Options.CookieContainer` property.
240+
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.
235241

236242
## Request Body
237243

src/RestSharp/Request/RestRequest.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ public RestRequest(string? resource, Method method = Method.Get) : this() {
7272
public RestRequest(Uri resource, Method method = Method.Get)
7373
: this(resource.IsAbsoluteUri ? resource.AbsoluteUri : resource.OriginalString, method) { }
7474

75-
readonly List<FileParameter> _files = [];
75+
readonly List<FileParameter> _files = [];
76+
readonly List<Cookie> _cookies = [];
7677

7778
/// <summary>
7879
/// Always send a multipart/form-data request - even when no Files are present.
@@ -263,4 +264,16 @@ public RestRequest RemoveParameter(Parameter parameter) {
263264
}
264265

265266
internal RestRequest AddFile(FileParameter file) => this.With(x => x._files.Add(file));
267+
268+
internal RestRequest AddCookie(Cookie cookie) => this.With(x => x._cookies.Add(cookie));
269+
270+
/// <summary>
271+
/// Cookies added via the 2-param <c>AddCookie(name, value)</c> overload that have not yet been
272+
/// resolved into <see cref="CookieContainer"/>. Domain is inferred from the request URL at
273+
/// execution time. Interceptors can inspect this list in <c>BeforeRequest</c> to see cookies
274+
/// that will be sent.
275+
/// </summary>
276+
public IReadOnlyList<Cookie> PendingCookies => _cookies;
277+
278+
internal void ClearPendingCookies() => _cookies.Clear();
266279
}

src/RestSharp/Request/RestRequestExtensions.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,15 @@ RestRequest RemoveParameter(string? name, ParameterType type) {
124124
return p != null ? request.RemoveParameter(p) : request;
125125
}
126126

127+
/// <summary>
128+
/// Adds a cookie to the request. The cookie domain will be inferred from the request URL at execution time.
129+
/// </summary>
130+
/// <param name="name">Cookie name</param>
131+
/// <param name="value">Cookie value</param>
132+
/// <returns></returns>
133+
public RestRequest AddCookie(string name, string value)
134+
=> request.AddCookie(new Cookie(name, value));
135+
127136
/// <summary>
128137
/// Adds cookie to the <seealso cref="HttpClient"/> cookie container.
129138
/// </summary>

src/RestSharp/RestClient.Async.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,17 @@ async Task<HttpResponse> ExecuteRequestAsync(RestRequest request, CancellationTo
130130
// Make sure we have a cookie container if not provided in the request
131131
var cookieContainer = request.CookieContainer ??= new();
132132

133+
foreach (var cookie in request.PendingCookies) {
134+
try {
135+
cookieContainer.Add(url, cookie);
136+
}
137+
catch (CookieException) {
138+
// Do not fail request if we cannot parse a cookie
139+
}
140+
}
141+
142+
request.ClearPendingCookies();
143+
133144
var headers = new RequestHeaders()
134145
.AddHeaders(request.Parameters)
135146
.AddHeaders(DefaultParameters)

0 commit comments

Comments
 (0)