<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: João Abreu</title>
    <description>The latest articles on DEV Community by João Abreu (@joao_abreu).</description>
    <link>https://dev.to/joao_abreu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4192775%2F801a8876-dd3e-439c-becd-1e1aa990278a.png</url>
      <title>DEV Community: João Abreu</title>
      <link>https://dev.to/joao_abreu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joao_abreu"/>
    <language>en</language>
    <item>
      <title>Why my GETs worked but every POST got a 403: a CORS bug behind nginx in Docker</title>
      <dc:creator>João Abreu</dc:creator>
      <pubDate>Tue, 20 Oct 2026 18:03:49 +0000</pubDate>
      <link>https://dev.to/joao_abreu/why-my-gets-worked-but-every-post-got-a-403-a-cors-bug-behind-nginx-in-docker-2io</link>
      <guid>https://dev.to/joao_abreu/why-my-gets-worked-but-every-post-got-a-403-a-cors-bug-behind-nginx-in-docker-2io</guid>
      <description>&lt;p&gt;I'm a CS student building a tutoring management system: a Spring Boot REST API, a React frontend and PostgreSQL. While preparing the v1.2 release, I added a Docker Compose setup so anyone could run the whole stack with one command.&lt;/p&gt;

&lt;p&gt;It almost worked. The pages loaded, the lists showed up... and every time I clicked a button that changed something, the API answered:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;403 Forbidden
Invalid CORS request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This post is about why that happened, why only &lt;em&gt;some&lt;/em&gt; requests failed, and the one-line fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;Three containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;        &lt;span class="c1"&gt;# PostgreSQL&lt;/span&gt;
  &lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="c1"&gt;# Spring Boot, port 8080&lt;/span&gt;
  &lt;span class="na"&gt;frontend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# nginx serving the React build, exposed as localhost:3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The frontend doesn't call the API directly. nginx proxies everything under &lt;code&gt;/api/&lt;/code&gt; to the &lt;code&gt;api&lt;/code&gt; container, so from the browser's point of view the frontend and the API live on the &lt;strong&gt;same origin&lt;/strong&gt;, &lt;code&gt;http://localhost:3000&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/api/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://api:8080/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the Spring side, I already had a CORS config for local development, when the frontend runs on Vite's dev server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/**"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;allowedOrigins&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:5173"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;allowedMethods&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"PATCH"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Same origin through the proxy, so CORS shouldn't even matter here. Right?&lt;/p&gt;

&lt;h2&gt;
  
  
  The weird part: only POST and PATCH failed
&lt;/h2&gt;

&lt;p&gt;Listing subjects and sessions (GET) worked fine. Suggesting a subject, joining a session or approving something (POST/PATCH) all returned 403.&lt;/p&gt;

&lt;p&gt;That was the clue. Browsers send the &lt;code&gt;Origin&lt;/code&gt; header on POST and PATCH requests even when they are same-origin, but &lt;strong&gt;not&lt;/strong&gt; on same-origin GETs. Spring only runs its CORS checks when an &lt;code&gt;Origin&lt;/code&gt; header is present. So the GETs never went through the CORS logic at all, and the others did.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Spring decides whether a request is "cross-origin"
&lt;/h2&gt;

&lt;p&gt;When a request has an &lt;code&gt;Origin&lt;/code&gt; header, Spring compares it with the request's own scheme, host and port. Spring builds that from the &lt;code&gt;Host&lt;/code&gt; header it receives. If they match, it's a same-origin request and CORS is skipped. If they don't, it's a CORS request and the origin must be in &lt;code&gt;allowedOrigins&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now look at what each side saw:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Origin&lt;/code&gt; sent by the browser&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http://localhost:3000&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Host&lt;/code&gt; forwarded by nginx with &lt;code&gt;$host&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;localhost&lt;/code&gt; (no port)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What Spring thinks it is&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;http://localhost&lt;/code&gt; (port 80)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;localhost:3000&lt;/code&gt; ≠ &lt;code&gt;localhost:80&lt;/code&gt;, so Spring treated a same-origin request as cross-origin. And since &lt;code&gt;http://localhost:3000&lt;/code&gt; wasn't in my allowed origins (only the Vite one was), it rejected it with &lt;code&gt;Invalid CORS request&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The culprit was &lt;code&gt;$host&lt;/code&gt;. In nginx, &lt;code&gt;$host&lt;/code&gt; is the host name &lt;strong&gt;without the port&lt;/strong&gt;. &lt;code&gt;$http_host&lt;/code&gt; is the &lt;code&gt;Host&lt;/code&gt; header exactly as the browser sent it, &lt;strong&gt;with the port&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&gt;

&lt;p&gt;One variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/api/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://api:8080/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;# $http_host keeps the port (localhost:3000), so Spring sees the same origin as the&lt;/span&gt;
    &lt;span class="c1"&gt;# browser and skips CORS; $host drops it and every POST/PATCH failed with 403.&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$http_host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now Spring sees &lt;code&gt;Host: localhost:3000&lt;/code&gt;, which matches &lt;code&gt;Origin: http://localhost:3000&lt;/code&gt;, and the request is same-origin again. No CORS check, no 403.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I didn't just add localhost:3000 to allowedOrigins
&lt;/h2&gt;

&lt;p&gt;That would also make the error go away, and it's the first answer you find online. But it hides the real problem: the requests &lt;em&gt;are&lt;/em&gt; same-origin, the proxy was just lying to the backend about where they came from. Fixing the header keeps the CORS config meaningful (it only lists origins that are really different, like the Vite dev server) and avoids a whitelist that has to change every time the port changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I took away from it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Only some methods fail" is a strong hint.&lt;/strong&gt; In this case it pointed straight at the &lt;code&gt;Origin&lt;/code&gt; header.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A reverse proxy changes what the backend sees.&lt;/strong&gt; Headers like &lt;code&gt;Host&lt;/code&gt; decide how the app understands the request, so they're worth checking first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fix the cause, not the symptom.&lt;/strong&gt; Widening CORS would have worked, but it would have been the wrong fix.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The project is open source if you want to see the full Docker setup: &lt;a href="https://github.com/jg-abreu/tutoring-management-system" rel="noopener noreferrer"&gt;tutoring-management-system&lt;/a&gt;. The fix is in v1.2.&lt;/p&gt;

&lt;p&gt;Have you ever been bitten by a proxy header? I'd like to hear how you debugged it.&lt;/p&gt;




&lt;h2&gt;
  
  
  🇧🇷 Versão em português
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Por que meus GETs funcionavam, mas todo POST dava 403: um bug de CORS atrás do nginx no Docker&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Sou estudante de Ciência da Computação e estou construindo um sistema de gestão de monitorias: uma API REST em Spring Boot, um frontend em React e PostgreSQL. Preparando a versão 1.2, criei um Docker Compose pra qualquer pessoa rodar o sistema inteiro com um único comando.&lt;/p&gt;

&lt;p&gt;Quase funcionou. As páginas carregavam, as listas apareciam... e toda vez que eu clicava num botão que alterava alguma coisa, a API respondia:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;403 Forbidden
Invalid CORS request
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Este post explica por que isso aconteceu, por que só &lt;em&gt;algumas&lt;/em&gt; requisições falhavam e a correção de uma linha.&lt;/p&gt;

&lt;h2&gt;
  
  
  O cenário
&lt;/h2&gt;

&lt;p&gt;Três containers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;db&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;        &lt;span class="c1"&gt;# PostgreSQL&lt;/span&gt;
  &lt;span class="na"&gt;api&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;       &lt;span class="c1"&gt;# Spring Boot, porta 8080&lt;/span&gt;
  &lt;span class="na"&gt;frontend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# nginx servindo o build do React, exposto em localhost:3000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O frontend não chama a API diretamente. O nginx repassa tudo que está em &lt;code&gt;/api/&lt;/code&gt; para o container &lt;code&gt;api&lt;/code&gt;, então, do ponto de vista do navegador, frontend e API estão na &lt;strong&gt;mesma origem&lt;/strong&gt;, &lt;code&gt;http://localhost:3000&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/api/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://api:8080/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No Spring, eu já tinha uma configuração de CORS para o desenvolvimento local, quando o frontend roda no servidor do Vite:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/**"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;allowedOrigins&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"http://localhost:5173"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;allowedMethods&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"GET"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"POST"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"PATCH"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mesma origem pelo proxy, então o CORS nem deveria importar aqui. Certo?&lt;/p&gt;

&lt;h2&gt;
  
  
  A parte estranha: só POST e PATCH falhavam
&lt;/h2&gt;

&lt;p&gt;Listar matérias e sessões (GET) funcionava. Sugerir uma matéria, entrar numa sessão ou aprovar algo (POST/PATCH) devolvia 403.&lt;/p&gt;

&lt;p&gt;Essa foi a pista. O navegador envia o cabeçalho &lt;code&gt;Origin&lt;/code&gt; em requisições POST e PATCH mesmo quando são da mesma origem, mas &lt;strong&gt;não&lt;/strong&gt; em GETs da mesma origem. E o Spring só roda as verificações de CORS quando existe um cabeçalho &lt;code&gt;Origin&lt;/code&gt;. Ou seja, os GETs nem passavam pela lógica de CORS, e os outros passavam.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como o Spring decide se uma requisição é "cross-origin"
&lt;/h2&gt;

&lt;p&gt;Quando a requisição tem &lt;code&gt;Origin&lt;/code&gt;, o Spring compara esse valor com o esquema, host e porta da própria requisição, que ele monta a partir do cabeçalho &lt;code&gt;Host&lt;/code&gt; que recebe. Se baterem, é mesma origem e o CORS é ignorado. Se não, é uma requisição CORS e a origem precisa estar em &lt;code&gt;allowedOrigins&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Veja o que cada lado enxergava:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Valor&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Origin&lt;/code&gt; enviado pelo navegador&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http://localhost:3000&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Host&lt;/code&gt; repassado pelo nginx com &lt;code&gt;$host&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;localhost&lt;/code&gt; (sem porta)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;O que o Spring acha que é&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;http://localhost&lt;/code&gt; (porta 80)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;localhost:3000&lt;/code&gt; ≠ &lt;code&gt;localhost:80&lt;/code&gt;, então o Spring tratou uma requisição da mesma origem como cross-origin. E como &lt;code&gt;http://localhost:3000&lt;/code&gt; não estava nas origens permitidas (só a do Vite), ele rejeitou com &lt;code&gt;Invalid CORS request&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;O culpado era o &lt;code&gt;$host&lt;/code&gt;. No nginx, &lt;code&gt;$host&lt;/code&gt; é o nome do host &lt;strong&gt;sem a porta&lt;/strong&gt;. Já &lt;code&gt;$http_host&lt;/code&gt; é o cabeçalho &lt;code&gt;Host&lt;/code&gt; exatamente como o navegador enviou, &lt;strong&gt;com a porta&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A correção
&lt;/h2&gt;

&lt;p&gt;Uma variável:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/api/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://api:8080/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$http_host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora o Spring recebe &lt;code&gt;Host: localhost:3000&lt;/code&gt;, que bate com &lt;code&gt;Origin: http://localhost:3000&lt;/code&gt;, e a requisição volta a ser da mesma origem. Sem verificação de CORS, sem 403.&lt;/p&gt;

&lt;h2&gt;
  
  
  Por que não adicionei localhost:3000 no allowedOrigins
&lt;/h2&gt;

&lt;p&gt;Isso também faria o erro sumir, e é a primeira resposta que aparece na internet. Mas esconde o problema real: as requisições &lt;em&gt;são&lt;/em&gt; da mesma origem, o proxy é que estava informando errado ao backend de onde elas vinham. Corrigir o cabeçalho mantém a configuração de CORS com sentido (ela só lista origens realmente diferentes, como o servidor do Vite) e evita uma lista que precisa mudar toda vez que a porta mudar.&lt;/p&gt;

&lt;h2&gt;
  
  
  O que eu levei disso
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Só alguns métodos falham" é uma pista forte.&lt;/strong&gt; Nesse caso, apontou direto para o cabeçalho &lt;code&gt;Origin&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Um proxy reverso muda o que o backend enxerga.&lt;/strong&gt; Cabeçalhos como &lt;code&gt;Host&lt;/code&gt; definem como a aplicação entende a requisição, então vale olhar para eles primeiro.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Corrija a causa, não o sintoma.&lt;/strong&gt; Liberar mais origens no CORS funcionaria, mas seria a correção errada.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;O projeto é open source, se quiser ver o Docker completo: &lt;a href="https://github.com/jg-abreu/tutoring-management-system" rel="noopener noreferrer"&gt;tutoring-management-system&lt;/a&gt;. A correção está na v1.2.&lt;/p&gt;

&lt;p&gt;Já foi pego por um cabeçalho de proxy? Conta como você depurou.&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>docker</category>
      <category>nginx</category>
      <category>cors</category>
    </item>
  </channel>
</rss>
