10 - Resolvendo o Problema de CORS na API

Quando tentamos conectar a nossa API a uma aplicação Front-end (como React, Angular, Vue ou até mesmo um arquivo HTML simples rodando localmente), o navegador costuma bloquear a comunicação por motivos de segurança, gerando um erro clássico no console. Hoje vamos entender o que é o CORS e como resolvê-lo de forma nativa no Go.

O que é CORS?

CORS significa Cross-Origin Resource Sharing (Compartilhamento de Recursos de Origem Cruzada). Trata-se de um mecanismo de segurança dos navegadores que impede que um site hospedado em uma origem (ex: http://localhost:5500) acesse os dados de uma API que está rodando em outra origem diferente (ex: http://localhost:8080), a menos que a API diga explicitamente que confia e permite esse acesso.

Para liberar o acesso, precisamos criar uma engrenagem que intercepta todas as requisições que chegam e adiciona cabeçalhos especiais de segurança informando que a nossa API está aberta para receber conexões externas. Chamamos essa engrenagem de Middleware.

Passo 1: Criando a função Middleware do CORS

Adicione a função abaixo no seu arquivo main.go (pode ser logo acima ou abaixo da sua função main). Ela interceptará os pedidos, injetará as permissões necessárias para o navegador e tratará de forma segura as requisições do tipo OPTIONS (conhecidas como Preflight):

// Middleware de CORS adaptado para o Gin
func corsMiddleware() gin.HandlerFunc {
	// Retorno
	return func(c *gin.Context) {

		// Configurações
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Credentials", "true")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization, accept, origin, Cache-Control, X-Requested-With")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "POST, OPTIONS, GET, PUT, DELETE")

		// Options
		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(http.StatusNoContent)
			return
		}

		// Next
		c.Next()
	}
}

Passo 2: Atualizando a inicialização do Servidor

Agora precisamos referenciar essa função, use o comando r.Use(corsMiddleware()) abaixo do roteador. Abaixo compartilho a estrutura atualizada da função principal:

// Função principal
func main() {

	// Roteador
	r := gin.Default()

	// Configurar CORS
	r.Use(corsMiddleware()) // <- Adicionada essa linha

	// Rotas
	r.GET("/", helloWorld)
	r.GET("/produtos", listarProdutos)
	r.POST("/produtos", cadastrarProduto)
	r.PUT("/produtos/:codigo", alterarProduto)
	r.DELETE("/produtos/:codigo", removerProduto)

	// Configurar o servidor
	r.Run(":8080")

}

Passo 3: Testando a Integração com o Front-end

Para testar se o CORS foi resolvido com sucesso, crie um arquivo HTML local no seu computador para simular um sistema Front-end realizando uma busca de dados (fetch) na sua API e exibindo os alunos cadastrados no terminal do navegador através de uma tabela.

Para facilitar os seus testes, você pode fazer o download do arquivo HTML pronto clicando no link abaixo:

Baixar Arquivo HTML de Testes

(Caso prefira criar o arquivo manualmente, utilize a estrutura de código abaixo):

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Testar API</title>

    <!-- Script -->
    <script>
        // Realizar requisição para o nosso endpoint de listagem
        fetch("http://localhost:8080/produtos")
        .then(retornoAPI => retornoAPI.json())
        .then(produtos => console.table(produtos)) // Exibe os dados formatados em tabela no console do navegador
        .catch(erro => console.error("Erro ao conectar na API:", erro))
    </script>


    <h1>Abra o Console do Navegador (F12) para ver o resultado do teste!</h1>

Abra o arquivo HTML no seu navegador e pressione a tecla F12 para acessar a aba Console. Se o CORS estiver funcionando perfeitamente, você verá a tabela de alunos renderizada com sucesso, sem nenhuma mensagem vermelha de bloqueio!