Since I’m working on an application using an OAuth 2.0 workflow I need to verify user identity. I’ve recently collapsed the webpack generation into the primary application server for static assets. Overall this has dratsically cut our CORS problems, something I don’t particularly wish to tackle at this time. However this gives rise to a new problem: once the browser application loads the react-router will intercept any change to the browser location on the host it was loaded from via the history API. This is great for most things, but definitely a problem when we want the browser to hit the server for things like redirects.

I’ve set aside 30 minutes to find out how to ‘fall through’ to the backing host. Time to start diggin through the source of react-router. I was really excited to see their auth-flow example only to find out in auth.js no request are actually delegated to a server. There was an interesting function in app.js named withExampleBasename which might warrent additional attention as it looks to be the mechanism to separate the examples on a single host and set the root uri of the browser application. The function is imported from withExampleBasename.js a directory higher in the tree. Following the rabbit hole, I need to track down the path history/lib/useBasename. Ah, no wonder a search couldn’t get any results! The history component of the path is actually referring to a depended upon module.

The history module doesn’t make sense with the reference to lib/useBasename. There isn’t a file that exists there. Searches show up refs in the documentation for version 1.13.0 but the actual function doesn’t exist anywhere I could find. Ah, looking at the wrong branch. react-router currently uses ^3.0.0 which should resolve to 3.2.1 instaed of 4.5.0. Interesting enough, the useBasename function decorates the passed create history function, returning the decorated object at the bottom. It doesn’t seem to filter, at least not in any way I’m can see right now. After searching through the code, I couldn’t find any reasonable method to attack this problem through this vector.

I have two directions I could apporach this with:

Move the web user interface to something like /wui. A reasonable approach for keeping the WUI state from the application and not mixing assets.

Modify the methods which redirect to respond with the target URL.

For right now, just to keep things moving without having to deal with redirects and such, I think I’m going with the second option. Overall it’s less work though it does feel like I’m hacking around the browser applciation instead of resolving it’s inability to correct allow fall through URI routing. I’m not convinced option 1 is less hacky though.

Accept header to the rescue! I’m glad Sinatra has sucked the algorithms for dealing with parsing that into the core. The API is a little funk: the request.accept is an array of objects that masquerade as a string when printed. Slightly confusing. To make matters worse all unknown methods are delegated to the string representation of the value. So effectively the negotiation goes something like the following:

	get '/some-resource' do
		target = "http://somehost.test/example"
		desired_media = request.accept[0].to_str

		if desired_media == "application/json"
			json { :redirect => target }
		else
			redirect to(target)
		end
	end

You could get more fancy with a dictionary look and a fallback, like many Rails clones do; sometimes it’s a little much though. So the request is hitting it, but my usage of the fetch API isn’t sending the cookies resulting in an incorrect state.