Tried this with Firefox (53.0.3) and Chrome (58.0.3029.110) on Windows 7, with NodeJS v7.2.0 and Apache 2.4.23.
We are developing a web app that will communicate with an executable on a Windows 7 machine.
I created a custom URI protocol, call it 'myapp', that will start that executable with some arguments.
A one time token, generated by the server, is required in the arguments for security sake.
To reduce the complexity, I decided to create a route '/app' that will generate the OT token and redirect to the custom URI with the required arguments ready:
router.get('/app', (req, res) => {
// grab some query string from the original request
const dataUid = res.query.datauid;
// do stuff and get a one time token
const otToken = generateOTToken();
const url = `myapp://?datauid=${dataUid}&token=${otToken}`;
res.redirect(302, url);
});
Accessing '/app' redirect to the correct custom URI, but the executable is not started as if the custom URI
command did not trigger.
We already had successfully implemented something similar using Apache in the past, so I added a Redirect rule to my Apache configuration to figure out what was going on:
RewriteEngine On
# custom url scheme
Redirect 302 "/redirectapp" "myapp://"
After accessing the manually forged request to '/redirectapp', I am redirected to the correct custom URI and the executable is started, as it should.
Curious, I then used curl to check the headers of both requests:
Express
$ curl -I "http://localhost:8008/app?datauid=UID" --cookie "idtoken=IDTOKEN"
Date: TODAY
Server: Apache/2.4.23 (Win64) PHP/5.6.25
X-Powered-By: Express
Location: myapp://?datauid=UID&token=OTTOKEN
Vary: Accept
Content-Type: text/plain; charset=utf-8
Content-Length: 1303
Apache
$ curl -I "http://localhost:8008/redirectapp?datauid=UID&idtoken=IDTOKEN"
Date: TODAY
Server: Apache/2.4.23 (Win64) PHP/5.6.25
Location: myapp://?datauid=UID&token=OTTOKEN
Content-Type: text/html; charset=iso-8859-1
While the difference looked minimal to me, I still tried my best to make the Express response match the Apache response as close as possible.
In the end, Express was sending the almost exact same response than Apache - I could not force the content type charset from 'utf-8' to 'iso-8859-1', resulting in a small Content-Length different (about 50 bytes).
To my surprise, the Express redirect at '/app' was still not triggering the custom protocol command.
I even tried to replace the res.redirect(302, url) by res.status(302).location(url).end(), just in case, with no success.
I finally made '/app' redirect to '/redirectapp' in the NodeJS server, which redirected to the correct custom URI and started the executable, as it should.
Can someone explain me what is wrong here, please?
Since Express redirecting to regular http(s) urls works fine when I tested and that the Apache response trigger the custom URI command, I can only see Express and NodeJS as potential culprit.
Thanks - and Express is dope nonetheless.
Hi @GoupilRobin that is very odd -- I can't imagine from your description that Express itself is hindering the redirection. I'm not sure how to setup a custom schema for an app personally, so I'm wondering if you can try some code here that would at least narrow down the issue by completely removing Express from the equation and mirroring the Apache response as much as possible.
Can you take the following code and save it as server.js and run that with Node.js and then try navigating to http://localhost:8008/redirectapp?datauid=UID&idtoken=IDTOKEN ?
var http = require('http')
http.createServer(function (req, res) {
res.statusCode = 302
res.setHeader('Server', 'Apache/2.4.23 (Win64) PHP/5.6.25')
res.setHeader('Location', 'myapp://?datauid=UID&token=OTTOKEN')
res.setHeader('Content-Type', 'text/html; charset=iso-8859-1')
res.end()
}).listen(8008)
Hi @dougwilson, thanks for the help.
I did run your script and curiously it did trigger the custom URI scheme command.
So far, NodeJS don't seem to be the problem.
To setup a custom URI scheme you have to add a bunch of keys in your registry on Windows, for linux I only that there are multiple ways based on your setup, no idea for mac.
PS: you probably meant to navigate to http://localhost:8008, your code already involve setting the parameters ;)
Cool. So let's continue troubleshooting by re-introducing Express, but not sending any response body (that was the another difference I saw between the two headers out displayed above):
var express = require('express')
express().use(function (req, res) {
res.status(302)
res.header('Server', 'Apache/2.4.23 (Win64) PHP/5.6.25')
res.header('Location', 'myapp://?datauid=UID&token=OTTOKEN')
res.header('Content-Type', 'text/html; charset=iso-8859-1')
res.end()
}).listen(8008)
Let me know if that works and we can continue to narrow down what, exactly, is causing the issue.
I will get back to you on Monday if you don't mind - thanks for your reactivity :)
Hi, I got to test your code and it triggered the custom URI scheme command, that's great ^^
I can stick to this for my case, I don't mind 5 lines if it works better than 1, but we can still try to continue to narrow down what's the issue just in case I hit something there.
_Edit_: I replaced the previous res.redirect(302, url) with your 5 lines code to redirect in our server and it works. Thanks for the help.
I am now heavily confused, I Ctrl-Z'ed a few times to check once more that the 5 lines version fixed the issue and (you guess it) the res.redirect() now works.
FYI nothing changed since I did not had time to touch the code until now - sorry for the trouble, I guess a windows restart was the actual fix...
Sorry for the troubles.
FWIW, I am also experiencing the same problem using Google Firebase Functions (which is based upon Express). Following @dougwilson 's suggestion from 5 days ago, I was able to work around this issue.
@baskren Is it possible to explain what you did with regards the Firebase Functions?
Thanks
I must apologize. I've long forgotten about this.
Most helpful comment
Cool. So let's continue troubleshooting by re-introducing Express, but not sending any response body (that was the another difference I saw between the two headers out displayed above):
Let me know if that works and we can continue to narrow down what, exactly, is causing the issue.