Skip to main content

My Proxy Rabbit Hole

While working on my React class, I was following an example that attempted to HTTP POST to a dummy REST API web site. It wasn’t working and I could see in the dev tools that I was getting errors on the console from the browser about a CORS problem.

CORS, which stands for Cross Origin Resource Sharing, is a security measure built into a browser that causes it to refuse to make calls to an API in a domain that is different from the domain that the web app making the call was loaded from. Thus, if you load an app from someapp.com (localhost, in my case) and try to call an API on someotherdomain.com (the dummy site, in my case) the browser will block it, unless someotherdomain exchanges certain headers with the browser that says it will accept such calls.

In my situation, the dummy site alleged they were providing the correct headers, so I suspected the issues getting them were caused by the site being proxied behind a DDOS protection gateway. That, or I wasn’t doing something correctly.

When I started reading up about the problem on the Web, I started to come across a variety of articles and posts that provided an alternative best practice for making HTTP calls from a web app. Their core idea is to send all calls back to the web app itself, which then proxies them out to other domains. That way, the app, not the browser, is making the calls and thus there are no CORS issues.

The standard way to proxy in a React app, I discovered, is to load and instantiate http-proxy-middleware, and then attach it to the Express app to be used in particular contexts – meaning, for particular URL routes. I was able to get this working up to a point, but then ran into additional problems with the gateway.

The problems were related to my using HTTPS from my app to the gateway and on to the dummy site. The gateway was using Server Name Indication (SNI) as part of the cert negotiation in their TLS handshake, but my proxy middleware was sending localhost, not the dummy site, as the target server name because localhost was the actual target of the original request. Though I searched high and low for an option on the middleware to change this, I couldn’t find anything similar to what the -servername option to the openssl s_client does.

Thus, I went the next deeper step and installed an nginx web server on my machine and got it to successfully reverse proxy GETS from my browser to the dummy site using config like:

location /datasource/ {
    proxy_pass https://example.com/endpoint/;
    proxy_ssl_server_name on;
}

I went back into my React app and removed the proxy middleware for the app and, instead, simply configured the package.json file to proxy all HTTP calls to the nginx server. The nginx server would then proxy those calls out to the gateway, which, in turn, would proxy to the dummy site. QED.

In the end, I decided I liked this approach better compared to the proxy middleware, because I could completely control the proxying and HTTP aspects of my app without needing to change code and rebuild and redeploy. Not to mention that nginx provides far more powerful control than the middleware ever could.

I think my next step to take this to production would be to dockerize my app and the nginx server and then try using docker-compose to bring everything up together.

Plugin DOM manipulation collisions

I have a number of browser plugins and many of them operate by manipulating the DOM for a page before rendering. This morning I noticed that one plugin had added its small, clickable icon right over the top of a different small clickable icon, right justified in a form input text box. The result was that there was no way (that I could figure out…) to get at the underlying icon. I’m not enough of a front end guy to know how difficult this layout glitch is to avoid, but it seems like someone didn’t anticipate there could be other elements in the text box, or they needed to take better care to position relative to any such elements.