8

Our web application has a button that is supposed to send data to a server on the local network that in turn prints something on a printer.

So far it was easy: The button triggered an AJAX POST request to http://printerserver/print.php with a token, that page connected to the web application to verify the token and get the data to print and then printed.

However, we are now delivering our web application via HTTPs (and I would rather not go back to HTTP for this) and newer versions of Chrome and Firefox don't make the request to the HTTP address anymore, they don't even send the request to check CORS headers.

Now, what is a modern alternative to the cross-protocol XHR? Do Websockets suffer from the same problem? (A Google search did not make clear what is the current state here.) Can I use TCP Sockets already? I would rather not switch to GET requests either, because the action is not idempotent and it might have practical implications with preloading and caching.

I can change the application on the printerserver in any way (so I could replace it with NodeJS or something) but I cannot change the users' browsers (to trust a self-signed certificate for printerserver for example).

sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
AndreKR
  • 32,613
  • 18
  • 106
  • 168
  • Just a thought but have you tried using CURL to make your request? Because CURL makes its own session it shouldn't be affected by how the browser behaves. – Mark_1 Nov 05 '14 at 12:40
  • 1
    I thought that would be clear from the question: machine _printerserver_ and user's browser are in one network, the web server is on the internet. – AndreKR Nov 05 '14 at 13:42
  • If I understand correctly, you're trying to call "http://printerserver/print.php" from an HTTPS website. Try running the "http://printerserver/print.php" server at 443 port - to support HTTPS, thus your calls will be on the same protocol. – Yonatan Ayalon Nov 06 '14 at 19:10

4 Answers4

1

You could store the print requests on the webserver in a queue and make the printserver periodically poll for requests to print.

If that isn't possible I would setup a tunnel or VPN between the webserver and printserver networks. That way you can make the print request from the webserver on the server-side instead of the client. If you use curl, there are flags to ignore invalid SSL certificates etc. (I still suspect it's nicer to introduce a queue anyway, so the print requests aren't blocking).

If the webserver can make an ssh connection to something on the network where the printserver is on, you could do something like: ssh params user@host some curl command here.

Third option I can think of, if printserver can bind to for example a subdomain of the webserver domain, like: print.somedomain.com, you may be able to make it trusted by the somedomain.com certificate, IIRC you have to create a CSR (Certificate Signing Request) from the printserver certificate, and sign it with the somedomain.com certificate. Perhaps it doesn't even need to be a subdomain for this per se, but maybe that's a requirement for the browser to do it client-side.

Ray Burgemeestre
  • 1,230
  • 8
  • 13
  • I am already storing those requests and the printerserver already connects to the webserver to get its data. I just need a way for the browser to tell the printerserver to do it, so the printing happens a couple of seconds after the click. Your last paragraph seems interesting, but is too vague for me to comprehend. – AndreKR Nov 06 '14 at 18:41
  • Can't the printserver decide for it's own when to print? If you store everything that needs to be done on the webserver, and the printserver checks every X second(s) with the webserver for any tasks it should do. When it's done printing, it could send a command to remove it from the webserver queue. – Ray Burgemeestre Nov 07 '14 at 08:14
1
  • The server hosting the https webapp can reverse proxy the print server, but since the printer is local to the user, this may not work.
  • The print server should have the correct CORS headers

    Access-Control-Allow-Origin: *
    

    or:

    Access-Control-Allow-Origin: https://www.example.com
    

However there are pitfalls with using the wildcard.

Community
  • 1
  • 1
dnozay
  • 23,846
  • 6
  • 82
  • 104
  • I don't get it, are you talking about server-to-server communication? There is no address at which the webserver of the application could reach the _printerserver_ machine. – AndreKR Nov 06 '14 at 18:39
  • can you please share more info on what your server (the one for your webapp) is? and can you please share what kind of printer/model you have? chances are there are other solutions that may not have to deal with CORS. – dnozay Nov 06 '14 at 19:30
1

The easiest way is to add a route to the webapp that does nothing more than relay the request to the print server. So make your AJAX POST request to https://myapp.com/print, and the server-side code powering that makes a request to http://printerserver/print.php, with the exact same POST content it received itself. As @dnozay said, this is commonly called a reverse proxy. Yes, to do that you'll have to reconfigure your printserver to accept (authenticated) requests from the webserver.

Alternatively, you could switch the printserver to https and directly call it from the client.

Note that an insecure (http) web-socket connection on a secure (https) page probably won't work either. And for good reason: generally it's a bad idea to mislead people by making insecure connections from what appears to them to be a secure page.

Community
  • 1
  • 1
mb21
  • 34,845
  • 8
  • 116
  • 142
  • I don't see how that is possible, given http://stackoverflow.com/questions/26615508/how-can-a-web-page-send-a-message-to-the-local-network/26785482#comment42098819_26615508 – AndreKR Nov 06 '14 at 18:37
0

From what I understand from the question, printserver is not accessible from the web application so the reverse proxy solution won't work here.

You are restricted from making requests from the browser to the printserver by cross-origin-policy.

If wish to communicate with the printserver from an HTTPS page you will need the printserver to expose print.php as HTTPS too.

You could create a DNS A record as a subdomain of your web application that resolves to the internal address of your printserver.

With those steps in place you should be able to update your printserver page to respond with permissive CORS headers which the browser should then respect. I don't think the browser will even issue CORS requests across different protocol schemes (HTTPS vs HTTP) or to internal domains, without a TLD.

Sam Greenhalgh
  • 5,952
  • 21
  • 37