Chunking HTTP Cookies in ASP.NET Core

By FoxLearn 2/26/2025 3:02:17 AM   130
If you've spent any time in web development, you know that cookies are a fundamental part of how we maintain state in web applications. For today's discussion, we're talking about HTTP cookies, which are simply key-value pairs set by the server via the Set-Cookie header.

A cookie is essentially a key-value pair in the HTTP header set by the server using the Set-Cookie directive, with a format of <name>=<value>. These cookies are stored on the client side and sent back to the server with each subsequent request, enabling persistent state in the otherwise stateless web.

However, cookies have limitations, particularly their 4KB size limit per cookie, which can become a problem in applications that store large amounts of data, such as ASP.NET Core apps that encrypt and encode cookies for session handling.

Why Use or Avoid Cookies?

Cookies provide an easy way to maintain state across HTTP requests. By embedding user data like ID, name, or preferences in cookies, you can simplify your backend logic by reducing the need for frequent database queries. The data travels with each request, allowing the server to easily access it. This ease of use makes debugging straightforward, as you can inspect HTTP headers to view cookies.

However, cookies also come with some disadvantages. They increase the size of each request since cookies are sent along with every HTTP request. This can be especially problematic when the cookies are large or unnecessary for certain requests, such as static content requests.

For example, a request for a small static image might still carry large cookies, resulting in unnecessary data transfer and resource consumption. Furthermore, when cookies are encrypted or chunked, they need to be reassembled and decrypted, adding extra load on the server's CPU and memory.

Setting Cookies in ASP.NET Core

Let’s start by setting a simple cookie in ASP.NET Core.

In this example, we’ll append data to an existing cookie value:

ctx.Response.Cookies.Append("user_info", "user_data");

Now, let's expand on that and create a scenario where we continually append random data to the cookie. This will allow us to simulate a situation where the cookie grows large enough to hit the 4KB limit:

app.MapGet("/add-data", async ctx =>
{
    ctx.Response.Cookies.Append("user_info",
        ctx.Request.Cookies.TryGetValue("user_info", out var cookie)
            ? $"{cookie}, {RandomString()}"
            : $"{RandomString()}");
});

This setup will work until the cookie's size exceeds the 4KB limit, which is when problems start to occur. To fix this, we’ll use cookie chunking.

Enabling Cookie Chunking

First, ensure you have the Microsoft.AspNetCore.Authentication.Cookies NuGet package installed in your project.

Next, we register the ChunkingCookieManager in the dependency injection container as an implementation of ICookieManager:

builder.Services.AddScoped<ICookieManager>(svc => new ChunkingCookieManager
{
    // Set the chunk size to 800 characters for quicker chunking.
    ChunkSize = 800, ThrowForPartialCookies = true
});

Here, we set the ChunkSize to 800 characters. It's important to note that the size is in characters, not kilobytes, so you need to adjust the size based on the data you’re storing.

Let’s now create an API endpoint that handles chunking cookies:

app.MapGet("/chunks", async (HttpContext ctx, ICookieManager cookieManager) =>
{
    var value = cookieManager.GetRequestCookie(ctx, "big_cookie") is { } cookie
        ? $"{cookie}, {RandomString()}"
        : $"{RandomString()}";

    cookieManager.AppendResponseCookie(ctx, "big_cookie", value, new CookieOptions());
});

Key Considerations for Chunking

When using cookie chunking, you must always interact with cookies through the ICookieManager interface. Directly manipulating cookies using HttpContext can result in issues when trying to chunk cookies. The ICookieManager is responsible for chunking and reassembling the cookies, so it’s crucial to use it properly.

Also, the CookieOptions parameter is required but can be left empty. You can use it to set properties such as Expires, Secure, Domain, and other cookie-specific options for the chunks.

How Cookie Chunking Works

Once a cookie exceeds the configured chunk size, ASP.NET Core will split the cookie into smaller pieces. These pieces are sent back to the client as separate cookies.

For example, if a cookie exceeds the chunk size, you might see the following in your browser’s dev tools:

NameValue
big_cookiechunk-3
big_cookieC1First chunk
big_cookieC2Second chunk
big_cookieCNMore chunks

In this case, the cookie big_cookie is split into multiple pieces, each represented by a unique cookie with a suffix (C1, C2, etc.) denoting the chunk.

If you find yourself hitting the cookie size limit, you have a few options to resolve the issue. You can attempt to optimize the data you're storing or use cookie chunking to handle larger cookies without exceeding the limit. While chunking adds a layer of complexity, it can be a useful tool in scenarios where you need to store more data in cookies.