Elemar DEV

Negócios, tecnologia e desenvolvimento

CORS Preflight Requests (com ASP.NET Web API)

Olá. Tudo certo?

No post anterior, falei sobre como deixar nossos serviços operantes em domínios diferentes daquele onde estão hospedados. O que apresentei é suficiente para operações de GET e POST mas não é suficiente para operações DELETE e PUT. Nesses casos, é necessário o respeito a um protocolo diferente conhecido como CORS Preflight.

O que é CORS Preflight?

De forma simplificada, o browser identifica requests para operações DELETE e PUT e, então, envia uma espécie de solicitação para o servidor para executar esse request.

Essa solicitação ocorre através de um request com o método OPTIONS para o endereço onde será executado o request original. Esse request é, simplifcadamente, assim:

OPTIONS http://address-of-your-service.com HTTP/1.1
Access-Control-Request-Method: PUT
Origin: http://request-origin.com

A API, então, deve retornar um response autorizando a operação. Algo, mais ou menos, assim:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: PUT

Em seguida, o cliente executará a operação de modificação.

Essa solicitação anterior é conhecida como CORS Preflight Request.

Suportando Preflight Requests com ASP.NET Web API

Agora que você já entende o conceito, sabe que suportar Preflight requests trata apenas de ter resposta apropriada para OPTIONS em seus controllers.

public HttpResponseMessage Options()
{
    var response = new HttpResponseMessage {StatusCode = HttpStatusCode.OK};
    response.Headers.Add("Access-Control-Allow-Origin", "*");
    response.Headers.Add("Access-Control-Allow-Methods", "POST, PUT, GET, DELETE");
    return response;
}

Ou ainda, para evitar duplicação de código, desenvolver um DelegatingHandler.

public class CorsPreflightHandler : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage r, 
        CancellationToken cancellationToken
        )
    {
        var request = new RequestEnvelope(r);
            
        if (!request.IsCorsPreflight) 
            return await base.SendAsync(r, cancellationToken);

        var response = new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
        response.Headers.Add("Access-Control-Allow-Origin", "*");
        const string supportedMethods = "POST, PUT, GET, DELETE";
        response.Headers.Add("Access-Control-Allow-Methods", supportedMethods);
        return response;
    }

    struct RequestEnvelope
    {
        private readonly HttpRequestMessage _request;
        public RequestEnvelope(HttpRequestMessage request) : 
            this()
        {
            _request = request;
        }

        public bool IsCorsPreflight
        {
            get
            {
                return (
                    _request.Headers.Contains("Origin") &&
                    _request.Method == HttpMethod.Options
                    );
            }
        }
    }
}

Sobre o Internet Explorer

Tanto o conteúdo desse post, quanto do post anterior, funcionam apenas no Internet Explorer 10 (ou mais novos).

Era isso.

2 comentários em “CORS Preflight Requests (com ASP.NET Web API)

  1. Cleyton Ferrari
    28/08/2013

    Na moral Elemar tem alguma coisa que você não escreveu neste blog?
    Essa semana é a 3ª vez que bato aqui procurando alguma coisa no google, hahaha

    To o dia todo sofrendo com esse tal cors, vou testar esse código descrito pra ve se agora vai!

  2. Elton Martins
    26/01/2016

    Olá Elemar. Estou tentando fazer um acesso simples cross domain, mas não consigo fazer funcionar.

    Fiz todas as configurações que encontrei aqui, mas quando envio a requisição, o cabeçalho Access-Control-Allow-Origin não está lá.

    Tem alguma dica pra me dar?

    Meu webConfig está assim:

    Minha chamada é assim:
    $.ajax({
    type: “GET”,
    dataType: “json”,
    contentType: contentType,
    cache: false,
    url: “http://67.205.69.111:8091/guiafacil/servicos/3.json”,
    success: function (data) {
    alert(“Data from Server” + JSON.stringify(data));
    },
    });

    To perdendo um tempão com isso…

Deixe um comentário

Informação

Publicado às 14/08/2013 por em Post e marcado .

Estatísticas

  • 921.483 hits