HAHAHA I hate CORS

03-22-25

This morning I woke up with sore arms, crusty eyes, and an overall feeling of satisfaction after cobbling together my sticker organizing script yesterday. But then I checked it on neocities and - wow! - it doesn't work... apparently you can't just make a request to get all the files in a private neocities folders without verifying that you should be accessing that folder . So today's work is NOT going to be creating the sticker filtering logic like I thought, but just getting the code to work within neocities.

success is on hold

XMLHttpRequest
  • used to interact with servers
  • can retrieve data from a URL without having to do a full page refresh...
  • code rn fetching from local file system (local server), try updating path to fetch from neocities folder on their server?

On neocities getting 403 response (request forbidden), meaning the request is understood but rejected. Usually 403 forbidden responses indicate that some form of authentication is needed to then allow the request to go through. I see the faults in the logic now from a cyber-security perspective. If my code was to work than anyone could take that script, change the fetch url, and get data from any private folder on neocities.

neocities has an api!

  • REST API
  • query parameters for input
  • returns JSON object
  • uses client side HTTP AUTH to authenticate using user/site name & password for credentials
  • can use cURL in the terminal to test API with HTTP requests
GET /api/list
  • provides list of files from your site
  • provide a path argument to get a list of files for that path

why is it failing?

Testing using cURL... installing cURL & using in terminal was confusing so using gitbash since cURL is built in.

Test works with authentication! Testing call from local server now. Hmm but I need to pass the auth info in the code but keep it a secret. its not a good idea to store secrets/sensitive data in javascript because its client side & once the code is uploaded & hosted on a server someone can inspect the javascript (if it's inline) or the network call & get that data.

client side
part of an application that runs on the users device (laptop, tablet, phones, etc). html, css, & js are all client-side languages

Seems the safest option is to store the info on a different server off neocities or github & fetch it before making the request. If neocities offered a secrets tab in the account settings that would be nice but it doesn't

I did not realize finding somewhere to host secret variables would be this big of a task. I've been researching for an hour and so far the solutions are too complicated for my needs. I dont want to encrypt anything, or build my own server, or install a library. uugh

I found a solution that I dont like, but it'll do for now.

testing

CORS is truly the bane of my existence. I forgot to hate it. Why did I forget to hate it? Every. Single. Request - even those that DONT need authentication fails with a 403!

I try adding Access-Control-Allow-Headers the headers in the request 403!

I try 3 different browser extensions that set the CORS header so I don't have to 403!

I try altering the settings of my local server so that the server can set the CORS header because (as I've learned through furious googling) the header can only be set from server side, but I don't know how to access the server config...


cors sucks

DAMN IT CORS!!

CORS - Cross Origin Resource Sharing
lets a server decide if other origins (domain, port, scheme) can load its resources/data

Sooo the 403 is happening because the neocities server is not sending the Access-Control-Allow-Origin response header that is needed to bypass CORS, so I need to get the neocities server to send it to me after I make the request from my server. I don't know what CORS really is so I'll do some research.

Ok so with CORS if the server that is recieving the request doesn't return Access-Control-Allow-Origin with the value of * (wildcard, meaning any site can access it's resources) or the origin value of the browser making the request, then the request will fail.

Both values have the same scheme, domain, & port. /hi is a page within the domain mydomain.com

The scheme is different between origins. The origin on the left is using http & the origin on the right is using https

ok so wtf is CORS?

Browsers make a "preflight" request to the server hosting the cross-origin resource by sending headers indicating the HTTP method & headers that will be used in the actual request to see if that server will allow the browsers request.

Cross origin resources are the headers
  • Access-Control-Allow-Origin
  • Access-Control-Allow-Methods
  • Access-Control-Allow-Headers
  • Access-Control-Allow-Credentials
i think... honestly not 100% sure.

A preflight request is an OPTIONS request sent before the actual HTTP request. It uses HTTP request headers Access-Control-Request-Method, Origin, and optionally Access-Control-Request-Headers & happens automatically from the browser.

Simple requests like GET, POST, HEAD do NOT trigger the pre-flight request, but the server receiving the request still needs to send the Access-Control-Allow-Origin header to share the response.

Cross-origin HTTP requests initiated from JS scripts are restricted for security reasons

fetch() & XMLHttpRequest follow the same-origin policy, so default behavior fails requests made to other origins other than the one the application was loaded from UNLESS the other origin includes the right CORS headers in the response (which usually is Access-Control-Allow-Origin)


So my current request is coming from a local server, which has a different domain, scheme, & origin than neocities.org, so all requests from my server to their server will fail.

Interestingly the browser will perform a network fetch to the other origin to check for the CORS header, and even if it successfully gets the data it won't let the JS code access the data if the CORS header is missing... so the request could succeed without the response header, but with JS I cannot access that data.

pre-flight requests

I'm still confused about most things but I think I can work with this info. I can't do what I want with my current setup . Using vanilla JS there is no way for me to get around this CORS issue. I'll need a server of some kind to make the requests for me thats able to add the CORS header in the response because neocities won't send it. Its rather disappointing that I can't use the API from client-side JS that's hosted on the neocities servers, but the potential security risks are probably significant enough to warrant not allowing it - I dont understand all the risks tho lol

Looks like lots of people have been asking for CORS response header to be added, but there's no followup after 2020 from the developers. Github Issue Link

I'll try setting up a server I guess. It seems like a good long term solution & I'll learn a new skill which is always fun after several weeks of frustration. Neocities Node Server Doc. In the mean time I'll just add the stickers manually.

what to do now?