Hoe los je een CORS error op bij het uploaden van bestanden met PHP?

Gisteren kwam ik tijdens het maken van een image saver in PHP, bij de frontend een CORS error tegen, ik doorloop samen met jou de stappen die ik ondernomen heb om het probleem op te lossen en wat de uiteindelijke oorzaak was.

De image saver ontvangt via een POST request een bestand welke opgeslagen dient te worden in een lokale folder. Dit bestand was in mijn geval afkomstig van een ander PHP script, welke gehost staat op een andere server, een CORS error tegenkomen tijdens het POSTen naar de image saver was dus niet zo vreemd.


"POST https://eenlink.net/ - Access to 'https://eenlink.net/' from origin 'https://uwlink2.net' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."

Headers

De eerste reflex was om de headers te bekijken die image saver geretourneerd had, buiten enkele standaard headers van Cloudflare waren hier geen headers te zien.


CORS staat voor Cross-Origin Resource sharing en is een header mechanisme dat bepaalt welke andere origine's (servers / domeinen) behalve zichzelf toelating hebben om bronnen te laden.
Het is in eerste instantie dus aangewezen om er voor te zorgen dat de server die de request behandelt de juiste headers terugstuurt.

Volgende headers werden toegevoegd:

  • Access-Control-Allow-Origin: *
    • Deze header is het belangrijkst op het vlak van CORS, het laat namelijk weten aan de verzender van het verzoek dat het open staat voor verzoeken van andere servers.
      Er is gebruik gemaakt van de wildcard *, welke betekent dat verzoeken internationaal mogelijk zijn,
       indien je dat liever niet hebt kan je hier je IP adres of domeinnaam invoeren van waar je verzoeken wenst te maken.

  • Access-Control-Allow-Methods: POST, GET
    • Deze laat de verzoeker toe om zowel POST als GET verzoeken te versturen.

  • Content-type: application/json
    • Deze laat de verzoeker weten dat je json zal retourneren na dat je script het verzoek verwerkt heeft. Pas dit aan naargelang hetgeen je wenst te retourneren, in mijn geval is dit een permalink naar de geüploade bestand, verwerkt in een json object.

  • Access-Control-Allow-Headers: Content-Type
    • Deze header geeft aan welke headers gebruikt kunnen worden bij de daadwerkelijke request, deze header is enkel van toepassing indien er sprake is van een "preflight request" waarbij de verzoeker eerst nagaat of het gewenste verzoek mag, en kan, uitgevoerd worden.
      Aangezien ik aan de kant van de verzoeker gebruik maak van de Fetch API en er mogelijk sprake was van een preflight verzoek is deze header toegevoegd.

Na toevoeging van deze headers probeerde ik opnieuw bestanden te uploaden, deze keer viel me op dat sommige, kleinere bestanden probleemloos geüpload konden worden terwijl dat bij grotere bestanden niet lukte.

PHP.ini

Nu dat er aanleiding is om de parameters omtrent maximale upload groottes te controleren begaf ik mij naar de configuratie-file van PHP, namelijk PHP.ini

In deze file wordt gespecifieerd wat de maximale toegelaten grootte is van bestanden die geüpload worden, dit staat standaard op een lage waarde (2 megabytes), wat al snel bereikt is.

Ik koos er voor om de maximale upload grootte in te stellen op 40 megabytes.

Afhankelijk van de versie van de PHP applicatie zal dit configuratie bestand elders terug te vinden zijn, in mijn geval een Linux machine met PHP 7.4:



Eenmaal je dit bestand geopend hebt zoek je naar de parameter upload_max_filesize en kies je voor een nieuwe waarde.


Sla het bestand op en herstart PHP.



Cloudflare cache

Na het herstarten van PHP met de nieuwe limiet en de headers toegevoegd te hebben bleef het gedrag van de server onveranderd.

Op dit moment dacht ik aan Cloudflare, welke diverse vormen van caching toepast.
Na het lezen van een artikel over CORS gepubliceerd door Cloudflare heb ik de cache van de image saver gepurged.



Nginx.conf

Na nogmaals een serie bestanden geüpload te hebben merkte ik op dat de kleinere bestanden nu wel de headers bevatten die ik toegevoegd heb, maar de grotere bestanden niet.

Aangezien het probleem niet meer bij PHP kan liggen aangezien de maximale grootte daar reeds aangepast werd, en niet aan de headers kan liggen rest er nog 1 intermediair: Nginx.

Nginx verbreekt elke verbinding die de ingestelde configuraties 'overtreed' en sinds het zich tussen de verzoeker en de behandeling van PHP bevind zal PHP nooit uitgevoerd worden, welke resulteert in het niet reageren met de juiste headers.

Dit uitte zich in de browser als een CORS error, enigzins misleidend aangezien het probleem niet meer aan het script van de verzoeker of de ontvanger ligt.

Net zoals bij PHP zal dus de maximale grootte aangepast moeten worden, de standaard waarde voor client_max_body_size is slechts 1 megabyte.



Nu dat het bestand geopend is dien je een nieuwe lijn toe te voegen bij de http { } blok als volgt, laat overige configuraties staan:



Herstart vervolgens nginx:



Na het herstarten van de Nginx server was het probleem opgelost, vanaf nu kunnen afbeeldingen tot 40 megabyte geüpload worden en is er van een CORS error geen sprake meer.



Popular posts from this blog

Ensuring verifiable communication between nyzo node operators by designing and deploying an authentication protocol