I am serving a static page over HTTPS (https://example.com) that makes requests to a node API on a different domain (example-api.com).
My API is a standard express app using HTTP. Here's my setup code:
var express = require('express');
var app = exports.app = express();
var port = process.env.PORT;
exports.server = require('http').createServer(app).listen(port);
In the requests from my static page, I specify https://example-api.com as the URL. This works most of the time, but every once in a while (10% of the time?) Chrome errors out on the requests with:
net::ERROR_INSECURE_RESPONSE
Other users who've come across this issue (e.g. Failed to load resource: net::ERR_INSECURE_RESPONSE socket.io) seem to solve it by adding a credentials option to their createServer call, e.g.
var server = https.createServer(credentials, app)
So when I tried to implement this I came up with the following:
var fs = require('fs');
var options = {
key: fs.readFileSync('server-key.pem'),
cert: fs.readFileSync('server-cert.pem')
};
var express = require('express');
var app = exports.app = express();
exports.server = require('https').createServer(options, app).listen(port);
However this solution doesn't seem to work for me. When I try it the requests never make it to my app - even logs in app.use middleware don't appear.
What's really confusing is the fact that my setup seems to work most of the time.
Does anyone know how I can reliably make my requests?
Thanks and sorry in advance for my ignorance.
I struggled with this a bit as well. If you are on windows I have a solution that is a bit of a work around, but will allow you to serve your site, and NodeJS app over HTTPS.
In Windows, I created a reverse proxy in IIS to point at the nodeJS RESTful endpoint (i.e. nodeJS RESTful services == website.com:7000). Don't let reverse proxy scare you, its gravy.
To Implement:
Install IIS (if you haven't already)
Create your Self Signed Cert (assuming you know how to do that), or apply your Cert you are using now.
Install Application Request Routing
Open your website configuration, and go to URL Rewrite
For the rewrite stuff:
For Pattern: ^api(.*)
For rewrite: http://www.website.com:7000{R:1}
This basically takes any request from: https://www.website.com/api/someApiAwesomeness, and rewrites it to your nodejs App running at http://www.website.com:7000. Now you have an SSL RESTful app..
Good luck man I hope this helps!
Related
Learning Nodejs for my personal projects. Analysing other developers code examples, watching youtube videos. I noticed one thing that I don't understand completely, why most of nodejs examples I come across have a code part for http server initiation and port listening? But application itself not using any http related things like processing http requests/responses. For example:
const express = require('express')
const path = require('path')
const http = require('http')
const cors = require('cors')
const PORT = process.env.PORT || 5000
const app = express();
const server = http.createServer(app).listen(PORT, () => console.log(`Listening on ${PORT}\n`))
app.use(express.static(path.join(__dirname, 'public')))
app.use(cors({ credentials: true, origin: '*' }))
If my nodejs application is a script that needs to be run on server side that collects some information from other API's and stores in a database, etc., do I need to create and start HTTP server anyway?
why most of nodejs examples I come across have a code part for http server initiation and port listening?
Because that's how people use nodejs most of the time: as a web server. Which doesn't mean it is mandatory or even a good practice.
do I need to create and start HTTP server anyway?
Of course not. Why would you do that if you don't need it? Do not worry about tutorials or examples, these don't know about your case and your needs.
I am building a web app that uses a express and node.js in the backend. In my server.js file, I have the following code
const express = require("express");
const app = express();
const server = require("http").Server(app);
const io = require("socket.io")(server);
I recently discovered that there is http2 available, should I change the line 3 to
const server = require("http2").Server(app); instead?
If I switch to http2, is there anything else I need to specifically change that wasn't present in http1? And is the way of sending HTTP requests such as get or post any different from http1 to http2?
HTTP2 is more efficient and loads faster pages-Differences.
But I suggest you use https since its more secure and most of the browsers mark non https requests as insecure.
similar stack
I am attempting to setup a server with ExpressJS which uses HTTPS and servers a React app. I want any HTTP requests to be redirected to using HTTPS.
Additional constraint: I am using React router, so the server needs to be able to handle that. e.g. if I request localhost:3000/profile, I want React Router to handle that, I just need Express to server up index.html as I had gone to localhost:3000.
Problem: I think I've been able to setup HTTPS (Chrome complains but I don't mind for now), but I cannot get redirection to work.
For comparison, this is my code for how I setup my HTTP-only server for development (before I ever tried to setup HTTPS):
const express = require('express');
const http = require('http');
const path = require('path');
const app = express();
const DIST_DIR = path.resolve('./dist');
app.use(express.static(DIST_DIR));
app.get('*', (req, res) => {
res.sendFile(path.resolve(DIST_DIR, './index.html'));
});
const devServer = http.createServer(app);
devServer.listen(3000);
Next, I started with this guide. I created a self-signed SSL certificate then set up my application. I then looked at some examples of how to redirect, such as this question.
However, it doesn't seem to be working.
Here is my code at present:
app.use(express.static(DIST_DIR));
app.use((req, res, next) => {
if (req.secure) {
next();
} else {
res.redirect(`https://${req.headers.host}${req.url}`);
}
});
app.get('*', (req, res) => {
res.sendFile(path.resolve(DIST_DIR, './index.html'));
});
const httpServer = http.createServer(app);
httpServer.listen(3080);
const privateKey = // uses FS to get my key
const certificate = // uses FS to get my cert
const credentials = { key: privateKey, cert: certificate };
const httpsServer = https.createServer(credentials, app);
httpsServer.listen(3443);
I can access https://localhost:3443 and navigate the app as expected, and Express properly handles refreshes on pages like /profile. Great. Chrome complains that "CA root certificate is not trusted. Install this cert in the trusted root certification authorities store" but I haven't put in the work to solve that, because in a real production environment I'd be provided the certificate and key from a trusted source.
However, when I go to http://localhost:3080, I just end up at http://localhost:3080. Chrome devtools shows I'm not using HTTPS. Furthermore, I can't go directly to /profile, as Chrome gives me the error "This site can’t provide a secure connection".
I've tried other methods listed in that stackoverflow question I linked, but they either have the same behavior or straight up don't work. I'm a bit out of my element here and I'm trying to learn, but I don't understand why this isn't working. Any help would be appreciated. Thanks.
While you can manage this in your application it is often the convention to have a web server like nginix or apache in front of your application that manages the https redirection. Depending on your setup it is also common to manage your certificates at this front server to simplify certificate management. If you are going to deploy onto aws or another cloud provider I would let their infrastructure handle this for you.
I'm using Node.js and Koa to build a web server. However, I'd like to merge it with another server located at 192.168.1.5:80. How can I make it so that all requests to {my web server}:80/api/* are exactly the same as requests to 192.168.1.5:80/api/*.
Thanks in advance!
You could use koa-proxy:
https://www.npmjs.com/package/koa-proxy
Then for the proxy, your code could look like this:
var koa = require('koa');
var proxy = require('koa-proxy');
var app = koa();
app.use(proxy({
host: 'http://192.168.1.5', // proxy to 192.168.1.5:80...
match: /^\/api\// // ...just the /api routes
}));
app.listen(80);
hope that helps ... (not testet)
We have a base domain of http://api.mysite.com. This should serve as the front door for all our APIs. Let's say we have two different APIs accessed with the following url structure:
http://api.mysite.com/launchrockets
http://api.mysite.com/planttrees
These are totally different. With regards running this on Heroku it seems we have two options.
1) Put everything inside one application on Heroku. This feels wrong (very wrong) and could lead to a higher chance of changes in one API inadvertently breaking the other.
2) Have 3 different Heroku apps. The first as a proxy (http://mysite-api-proxy.herokuapp.com) that will look at the incoming request and redirect to http://planttrees.herokuapp.com or http://launchrockets.herokuapp.com using a module like bouncy or http-proxy.
I'm leaning towards option 2 but I am concerned about managing the load on the proxy app. For web frameworks that have a synchronous architecture this approach would be disastrous. Yet with node.js using the cluster module and being asynchronous I think this may scale okay.
I've seen similar questions asked before but most related to synchronous frameworks where option 2 would definitely be a poor choice. This question is specific to node and how it would perform.
Thoughts on best way to architect this?
I implemented simple demo project to achieve multi-app structure.
https://github.com/hitokun-s/node-express-multiapp-demo
With this structure, you can easily set up and maintain each app independently.
I hope this would be a help for you.
Here is a blog post I wrote trying to answer this question. There are many options but you have decide what is right for your app and architecture.
http://www.tehnrd.com/host-multiple-node-js-apps-on-the-same-subdomain-with-heroku/
Similar to #TehNrd, I'm using a proxy. However this approach doesn't require multiple heroku apps, just one:
On your web app:
var express = require('express')
, url = require('url')
, api_app = require('../api/server') //this is your other apps index.js or server.js
, app = express()
, httpProxy = require('http-proxy')
, apiport = parseInt(process.env.PORT)+100 || 5100 //this works!
;
// passes all api requests through the proxy
app.all('/api*', function (req, res, next) {
api_proxy.web(req, res, {
target: 'http://localhost:' + apiport
});
});
On your API server:
var express = require('express');
var app = express();
var port = parseInt(process.env.PORT)+100 || 5100;
...
...
app.listen(port);