Khắc phục yêu cầu tiền kiểm OPTIONS 204 dư thừa khi xử lý CORS trong ASP.NET Core Web API 3.1

Khi phát triển ứng dụng web, vấn đề CORS (Cross-Origin Resource Sharing) là một thách thức phổ biến. Trong ASP.NET Core Web API 3.1, việc cấu hình CORS đôi khi dẫn đến các yêu cầu tiền kiểm (preflight) OPTIONS trả về mã trạng thái 204 (No Content) một cách không cần thiết, gây lãng phí tài nguyên máy chủ.

1. Cấu hình CORS bằng Middleware

Cách tiếp cận ban đầu thường là sử dụng middleware CORS tích hợp sẵn của ASP.NET Core. Điều này bao gồm việc đăng ký dịch vụ CORS và sử dụng middleware trong pipeline xử lý yêu cầu.

Cấu hình dịch vụ:

services.AddCors(options =>
{
    options.AddPolicy("MyCorsPolicy", policy =>
    {
        policy.SetPreflightMaxAge(TimeSpan.FromSeconds(1800)); // Thời gian cache cho preflight
        policy.AllowAnyOrigin()
              .AllowAnyHeader()
              .AllowAnyMethod();
    });
});

Sử dụng middleware trong Startup.cs:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ... các cấu hình khác ...

    app.UseCors("MyCorsPolicy"); // Áp dụng chính sách CORS

    // ... các middleware khác ...
}

2. Vấn đề với yêu cầu OPTIONS 204

Sau khi áp dụng cấu hình trên, vấn đề thường gặp là các trình duyệt sẽ gửi một yêu cầu OPTIONS trước mỗi yêu cầu CORS thực tế. Nếu yêu cầu này thành công, máy chủ sẽ trả về mã 204. Mặc dù `SetPreflightMaxAge` được thiết lập để cache kết quả, nhưng yêu cầu ban đầu vẫn xảy ra và có thể lặp lại nếu cache hết hạn hoặc trình duyệt không hỗ trợ đúng cách, gây ảnh hưởng đến hiệu năng.

3. Giải pháp tùy chỉnh bằng Global Filter

Để khắc phục triệt để vấn đề này và loại bỏ các yêu cầu OPTIONS 204 không cần thiết, chúng ta có thể tự triển khai một bộ lọc hành động (Action Filter) toàn cục.

Tạo Global Filter:

using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Primitives;

public class CustomCorsFilter : IActionFilter
{
    public void OnActionExecuted(ActionExecutedContext context)
    {
        // Thêm các header CORS cần thiết trực tiếp vào phản hồi
        context.HttpContext.Response.Headers.Add("Access-Control-Allow-Origin", "*");
        context.HttpContext.Response.Headers.Add("Access-Control-Allow-Headers", "*");
        context.HttpContext.Response.Headers.Add("Access-Control-Allow-Methods", "*");
        // Cache cho phép trình duyệt không gửi lại preflight request trong 1 ngày
        context.HttpContext.Response.Headers.Add("Access-Control-Max-Age", new StringValues("86400")); 
    }

    public void OnActionExecuting(ActionExecutingContext context)
    {
        // Không cần xử lý trong OnActionExecuting cho giải pháp này
    }
}

4. Đăng ký Global Filter

Tiếp theo, đăng ký bộ lọc này như một dịch vụ và áp dụng nó toàn cục cho các API controller.

Trong Startup.cs:

services.AddControllersWithViews(options =>
{
    options.Filters.Add(typeof(CustomCorsFilter)); // Thêm filter toàn cục
});

Sau khi áp dụng bộ lọc tùy chỉnh này, các yêu cầu tiền kiểm OPTIONS 204 dư thừa sẽ được loại bỏ, giúp cải thiện đáng kể hiệu năng của máy chủ API.

Thẻ: ASP.NET Core Web API CORS middleware Action Filter

Đăng vào ngày 7 tháng 10 lúc 23:45