Angular + Node(Express) + SSL integration - javascript

This is my first time deploying ssl. I have express node js module running at localhost:4000. I have generated the self-signed certificate and installed in the server and it is working. Now, I have my angularjs frontend running at localhost:3000(I am using http-server to run the angular code).
To make my point more clearer, here's is the code on the server side:-
// Import node js modules
var https = require('https')
var fs = require('fs')
var express = require('express')
// Load App configuration
var config = require('./config/config')
// Database Integration Here(mongodb)
// Initialize the express app
var app = express()
// App express Configuration
// parse application/json
app.use(bodyParser.json())
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true}))
app.use(cors())
app.set('serverHost', config.server.host)
app.set('serverPort', config.server.port)
app.set('serverUrl', config.server.url)
// Initializing various app modules
// Initialize the components
//Initialize the route(controller)
// Start the app with a given port no and mode
var env = process.env.NODE_ENV || 'development'
var httpsOptions = {
key: fs.readFileSync(__dirname + '/cert/server.key'),
cert: fs.readFileSync(__dirname + '/cert/server.crt')
}
https.createServer(httpsOptions, app).listen(app.get('serverPort'), function () {
// Server and mode info
console.log('The homerungurus backend running on server: '
+ app.get('serverHost')
+ ' and the port is: '
+ app.get('serverPort'))
console.log("The mode is: " + env)
})
As you can see I have installed the certs in the server.
I don't need a http-proxy because i will deploy the angular webserver on the standard port 443.
I am not able to understand few things:-
How to enable and set ssl certificate in my angular module so that
express and angular can communicate over ssl.
How will I display the cert of my backend express node to the browser?
I hope I have made my point more clearer.
Any help is appreciated?

Ok, where do we start...
You have a backend (express node js) running on port 4000, and a frontend (angularjs with http-server) running on port 3000, so you basically have two independent webservers running. When you say you "installed" the ssl certificate on the server, I assume you have it sitting in some directory but not actually installed on one of your servers.
You have several options to deploy your code, together with your SSL certificate. The best approach would be to seperate frontend from backend by urls.
That would mean that your frontend gets served from: https://frontend.example.com
and your backend gets served from https://backend.example.com (you can change the urls to whatever you want, so something like https://example.com or https://www.example.com is fine as well)
As far as I recall, if you have https:// on your frontend, you also need https:// on your backend, otherwise you will have problems with browsers security policies. You might also have to look for same origin policy, and allow on your server that https://frontend.example.com can access https://backend.example.com, but for that open a new ticket if you need it :D
The user would see the green symbol from https://frontend.example.com
I assume you know how you would change the backend url so your angular code would use https://backend.example.com instead of http://localhost:4000
To serve now your existing servers on port 443 (that is the default port for https and is always used if you say https://... but do not specify a port) you need an http proxy.
As http proxy (you can google for reverse proxy) you can take either apache or nginx, both are very common.
There are a couple of tutorials out there, how to setup nginx / apache which are OS specific, but Im sure you will manage. Dont forget to install mod_ssl and mod_http_proxy mod for apache (I dont remember if nginx needs something specifc as well)
A typical config for an apache reverse proxy would look like this:
<VirtualHost *:80>
# this part redirects all traffic from normal http to https
ServerName frontend.example.com
ServerSignature Off
RewriteEngine on
RewriteCond %{HTTPS} !=on
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [NE,R,L]
</VirtualHost>
<virtualhost *:443>
# this is the actual part with some security enhancements
ServerName frontend.example.com
ServerAdmin webmaster#localhost
# be carefull with HSTS, it might break your setup if you
# do not know what you do. If you are not sure, do not
# comment the next line in
# Header always add Strict-Transport-Security "max-age=15768000"
# Enable SSL
SSLEngine on
# only strong encryption ciphers
# for reference https://community.qualys.com/blogs/securitylabs/2013/08/05/configuring-apache-nginx-and-openssl-for-forward-secrecy
# and no RC4 according to https://community.qualys.com/blogs/securitylabs/2013/03/19/rc4-in-tls-is-broken-now-what
SSLProtocol all -SSLv2 -SSLv3
SSLHonorCipherOrder on
SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4"
SSLCompression Off
SSLCertificateFile /path/to/cert.pem
SSLCertificateKeyFile /path/to/privkey.pem
# this next line is not needed if you have a self signed cert
SSLCertificateChainFile /path/to/chain.pem
ServerSignature Off
RequestHeader set X-FORWARDED-PROTOCOL https
RequestHeader set X-Forwarded-Ssl on
ProxyPreserveHost On
# Ensure that encoded slashes are not decoded but left in their encoded state.
# http://doc.gitlab.com/ce/api/projects.html#get-single-project
AllowEncodedSlashes NoDecode
<Location />
# New authorization commands for apache 2.4 and up
# http://httpd.apache.org/docs/2.4/upgrading.html#access
Require all granted
ProxyPassReverse http://127.0.0.1:3000
ProxyPassReverse http://frontend.example.com/
</Location>
#apache equivalent of nginx try files
# http://serverfault.com/questions/290784/what-is-apaches-equivalent-of-nginxs-try-files
# http://stackoverflow.com/questions/10954516/apache2-proxypass-for-rails-app-gitlab
RewriteEngine on
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f
RewriteRule .* http://127.0.0.1:3000%{REQUEST_URI} [P,QSA]
RequestHeader set X_FORWARDED_PROTO 'https'
You will need the exact same twice, for the frontend like shown above and for the backend, where you replace port 3000 with 4000 and frontend.example.com with backend.example.com.
I hope this helps you a bit. Its not as complete as it could, but it should give you a hint how to setup your two http servers behind a http proxy to server your ssl certificate.

The above comment made by #chickahoona is more than enough. My solution is as follows:-
I removed http-server and used nginx for my frontend because i wanted to have html5 mode and for that I needed to have url rewriting.
I have used nginx as a proxy server rather than apache.
That's it and everything else is same as #chickahoona has pointed out.

Related

Apache reverse proxy to Node - Connection refused: AH00957

I am trying to get a brand new cloud based server working with a default version of 20.04 server ubuntu working with apache and node. The node server appears to be running without issues reporting 4006 port is open. However I believe my apache config is not. The request will hang for a very very long time. No errors are displayed in the node terminal. So the fault must lie in my apache config seeing as we are getting the below apache errors and no JS errors.
Request error after some time
502 proxy error
Apache Error Log
[Sun Oct 17 20:58:56.608793 2021] [proxy:error] [pid 1596878] (111)Connection refused: AH00957: HTTP: attempt to connect to [::1]:4006 (localhost) failed
[Sun Oct 17 20:58:56.608909 2021] [proxy_http:error] [pid 1596878] [client 207.46.13.93:27392] AH01114: HTTP: failed to make connection to backend: localhost
vhost
<VirtualHost IP_ADDRESS:80>
ServerName api.aDomain.com
Redirect permanent / https://api.aDomain.com/
</VirtualHost>
<IfModule mod_ssl.c>
<VirtualHost IP_ADDRESS:443>
ServerName api.aDomain.com
ProxyRequests on
LoadModule proxy_module /usr/lib/apache2/modules/mod_proxy.so
LoadModule proxy_http_module /usr/lib/apache2/modules/mod_proxy_http.so
ProxyPass / http://localhost:4006/
ProxyPassReverse / http://localhost:4006/
#certificates SSL
SSLEngine on
SSLCACertificateFile /etc/ssl/api.aDomain.com/apimini.ca
SSLCertificateFile /etc/ssl/api.aDomain.com/apimini.crt
SSLCertificateKeyFile /etc/ssl/api.aDomain.com/apimini.key
ErrorLog ${APACHE_LOG_DIR}/error_api.aDomain.com.log
CustomLog ${APACHE_LOG_DIR}/access_api.aDomain.com.log combined
</VirtualHost>
</IfModule>
terminal output
[nodemon] 1.19.4
[nodemon] to restart at any time, enter `rs`
[nodemon] watching dir(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `babel-node -r dotenv/config --inspect=9229 index.js`
Debugger listening on ws://127.0.0.1:9229/c1fcf271-aea8-47ff-910e-fe5a91fce6d2
For help, see: https://nodejs.org/en/docs/inspector
Browserslist: caniuse-lite is outdated. Please run next command `npm update`
🚀 Server ready at http://localhost:4006
Node server
import cors from 'cors'
import scrape from './src/api/routes/scrape'
const express = require('express')
const { ApolloServer, gql } = require('apollo-server-express')
const { postgraphile } = require('postgraphile')
const ConnectionFilterPlugin = require('postgraphile-plugin-connection-filter')
const dbHost = process.env.DB_HOST
const dbPort = process.env.DB_PORT
const dbName = process.env.DB_NAME
const dbUser = process.env.DB_USER
const dbPwd = process.env.DB_PWD
const dbUrl = dbPwd
? `postgres://${dbUser}:${dbPwd}#${dbHost}:${dbPort}/${dbName}`
: `postgres://${dbHost}:${dbPort}/${dbName}`
var corsOptions = {
origin: '*',
optionsSuccessStatus: 200, // some legacy browsers (IE11, various SmartTVs) choke on 204
}
async function main() {
// Construct a schema, using GraphQL schema language
const typeDefs = gql`
type Query {
hello: String
}
`
// Provide resolver functions for your schema fields
const resolvers = {
Query: {
hello: () => 'Hello world!',
},
}
const server = new ApolloServer({ typeDefs, resolvers })
const app = express()
app.use(cors(corsOptions))
app.use(
postgraphile(process.env.DATABASE_URL || dbUrl, 'public', {
appendPlugins: [ConnectionFilterPlugin],
watchPg: true,
graphiql: true,
enhanceGraphiql: true,
})
)
server.applyMiddleware({ app })
//Scraping Tools
scrape(app)
const port = 4006
await app.listen({ port })
console.log(`🚀 Server ready at http://localhost:${port}`)
}
main().catch(e => {
console.error(e)
process.exit(1)
})
Apache Mods Enabled
/etc/apache2/mods-enabled/proxy.conf
/etc/apache2/mods-enabled/proxy.load
/etc/apache2/mods-enabled/proxy_http.load
Updated Error Logs
[Thu Oct 21 10:59:22.560608 2021] [proxy_http:error] [pid 10273] (70007)The timeout specified has expired: [client 93.115.195.232:8963] AH01102: error reading status line from remote server 127.0.0.1:4006, referer: https://miniatureawards.com/
[Thu Oct 21 10:59:22.560691 2021] [proxy:error] [pid 10273] [client 93.115.195.232:8963] AH00898: Error reading from remote server returned by /graphql, referer: https://miniatureawards.com/
In major situations this is caused by selinux (when you have RHEL or CentOS):
# setsebool -P httpd_can_network_connect 1
link: https://unix.stackexchange.com/questions/8854/how-do-i-configure-selinux-to-allow-outbound-connections-from-a-cgi-script
Also check:
connectivity between the machines
back-end port is open
Use static IP-address (IPv4) or use host-name that are in you /etc/hosts file
I cannot exactly predict what exactly happen it could be NodeJS app crushed and no longer running or there are misconfiguration Apache files. But I strongly believe this scenario will be solved from doing things back from the top.
This step would go through updating unbuntu packages, installing needed application, configuring Apache files and setting up reverse proxy with NodeJS and Apache.
Just don't touch your NodeJS files and other code related application and they will be safe. You may also backup just to make sure. Other running application on that ubuntu server example database application like MySQL as will be just fine and still be running.
1. First we need to update ubuntu packages and install Apache, and NodeJS
$ sudo apt update
$ sudo apt install apache2 npm
2. Run this command to enable us to use Apache as a reverse proxy server
sudo a2enmod proxy proxy_http rewrite headers expires
3. Create an Apache virtual host file.
This command would will let you use ubuntu terminal as your text editor follow the guide and prompt from the terminal to write.
NOTE:
Change the "yourSite.com" with the domain of your site. It isn't really important should be the name of the file. But I think its better to name it after your site domain so you can recognize it.
$ sudo nano /etc/apache2/sites-available/yourSite.com.conf
4. Use the nano editor is to write your Apache config file for your site.
Notice: This part is critical so please pay attention
Change your ServerName and ServerAlias with your site domain name.
The ProxyPass and the ProxyPassReverse this has two parameters.
The first one is a back-slash "/" This an absolute path where your NodeJS should be located and since its single back-slash that means its your home directory.
The second one is the url "http://127.0.0.1:3000/" of your NodeJS application. Pay attentions to its PORT "3000" you may need to replaced it with the PORT you use in your NodeJS app.
<VirtualHost *:80>
ServerName example.com // replace this with site domain name without www at the beginning
ServerAlias www.example.com // replace this with site domain name beginning with www. + yourdomainname + .com
ProxyRequests Off
ProxyPreserveHost On
ProxyVia Full
<Proxy *>
Require all granted
</Proxy>
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:30000/
</VirtualHost>
5. disable the default Apache site and enable the new one.
$ sudo a2dissite 000-default
$ sudo a2ensite example.com.conf
6. Restart your Apache Server to apply the changes
sudo systemctl restart apache2
We could be ready at this point as we done setting up Apache as a reverse proxy, But we also need to install the npm package of your project and then run your NodeJS application.
7. The rest of the step is all related to NodeJS deployment. You may be already know this steps.
// install npm packages
npm install
// for a better experience using NodeJS in production install pm2 globally
npm install -g pm2
// Then run your NodeJS application using pm2 command
pm2 start // you should be at root of your NodeJS project folder when running this command
// run this another pm2 command to make sure your NodeJS app will re-run when it encounter downtime.
$ pm2 save
$ pm2 startup
Your Apache and NodeJS server is up and running now
Try to access your site by typing entering your site domain name in the browsers address bar
e.g http://yourSite.com
If you use a docker for your node server, then it might be set up incorrectly
I'm not an expert on this topic, but I have a similar setup; I use socket.io to serve WebSockets...
From your posts it seems you don't need to proxy WebSockets as well, the one shown in your logs seems to be only for debugging purposes (please correct me if I'm wrong).
Following the core of my Apache configuration:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/socket.io [NC]
RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteRule /(.*) ws://127.0.0.1:4006/$1 [P,L]
<Location />
ProxyPass http://127.0.0.1:4006/ retry=2
ProxyPassReverse http://127.0.0.1:4006/
</Location>
Another couple of suggestions.
Warning
Do not enable proxying with ProxyRequests until you have secured your server. Open proxy servers are dangerous both to your network and to the Internet at large.
Source: https://httpd.apache.org/docs/2.4/mod/mod_proxy.html#proxyrequests
I don't know which is the IPV6 setup on your host, you could try to use 127.0.0.1 rather than localhost in you Apache configuration to try forcing Apache to use IPV4.

Can't establish a connection with javascript to a secure websocket server

My development environment is this:
OS: Microsoft Windows 10
PHP framework: Laravel 8.0
PHP version 7.4
Websocket server: cboden/ratchet 0.4.3
WAMP server 3.2.0 (Apache 2.4.41)
Firefox 91.0.1 (64-bit) / chrome
I created a new Laravel app to implement a Secure Websocket Server and get connected to it using plain javascript on the client side (Laravel blade file).
The websocket server works fine, as far as I can see it running, but the web browser is not able to connect, as seen on this image:
I have tried using different URLs, with and without port number, but to no avail.
I created a SSL certificate and private key files, using openssl.exe tool, and put them in the command folder for testing purposes.
This is my handle code for the Secure Websocket Server:
public function handle()
{
$loop = Factory::create();
$webSock = new SecureServer(
new Server('0.0.0.0:8090', $loop),
$loop,
array(
'local_cert' => 'certificate.crt',
'local_pk' => 'private.key',
'allow_self_signed' => TRUE,
'verify_peer' => FALSE
)
);
// Ratchet magic
$webServer = new IoServer(
new HttpServer(
new WsServer(
new WebSocketController()
)
),
$webSock
);
$loop->run();
}
My virtual host in httpd-ssl.conf file:
<VirtualHost *:443>
ServerName ssa
DocumentRoot "d:/web/app/ssa/public"
SSLEngine on
SSLCertificateFile "${SRVROOT}/conf/certificate.crt"
SSLCertificateKeyFile "${SRVROOT}/conf/private.key"
SSLVerifyClient none
SSLVerifyDepth 10
<Directory "d:/web/app/ssa/public">
Options +Indexes +Includes +FollowSymLinks +MultiViews
AllowOverride All
Require local
</Directory>
ProxyRequests Off
ProxyPass /wss/ ws://ssa:8090
</VirtualHost>
The Apache modules proxy_module, proxy_http_module and proxy_wstunnel_module are loaded.
The web app is running in HTTPS.
Before, it was running over HTTP and WS and everything worked perfectly, but I need to secure this app and I am having issues to connect to the secure websocket server.
Am I missing something?
Is there something wrong with my Websocket server or Apache configuration?
You are surely trying to connect to the wrong destination. It says wss:///ssa/wss/, but probably it should be wss://your.site.domain/ssa/wss/ .
So let's look at front end code and find out what's wrong with it.
Ok, as #apokryfos pointed out, I tried to proxy the websocket server through HTTPS but I was doing it in the wrong way.
I changed my websocket server to a non-secure one and did the following change to my virtual host:
<VirtualHost *:443>
ServerName ssa
DocumentRoot "d:/web/app/ssa/public"
SSLEngine on
SSLCertificateFile "${SRVROOT}/conf/certificate.crt"
SSLCertificateKeyFile "${SRVROOT}/conf/private.key"
SSLVerifyClient none
SSLVerifyDepth 10
<Directory "d:/web/app/ssa/public">
Options +Indexes +Includes +FollowSymLinks +MultiViews
AllowOverride All
Require local
</Directory>
Redirect /wss /wss/
ProxyPass /wss/ ws://127.0.0.1:8090/
ProxyPassReverse /ws/ wss://127.0.0.1:8090/
</VirtualHost>
On the client side, the browser can now contact the backend WS server through the HTTPS port:
// The connection to the WebSocket Server.
var socket = new WebSocket("wss://ssa:443/wss/");
I got this solution from
Apache Config: Websockets Proxy WSS request to WS backend
Now I got my non-secure Websocket server sending/receiving through HTTPS.
This is, for sure, not the solution I expected to apply to my needs but it certainly works.
I still hope to find a formal solution to connecting plain JavaScript client to a Secure Websocket Server (wss://) without using a proxy mechanism.
For not to complicate my first answer with more information, here I provide the answer that really worked for me after all.
I created the Secure Websocket Server as follows:
public function handle() {
$loop = Factory::create();
$webSock = new SecureServer(
new Server('0.0.0.0:8443', $loop),
$loop,
array(
'local_cert' => 'C:/wamp64/bin/apache/apache2.4.41/conf/server.crt',
'local_pk' => 'C:/wamp64/bin/apache/apache2.4.41/conf/server.key',
'allow_self_signed' => TRUE,
'verify_peer' => FALSE
)
);
$webServer = new IoServer(
new HttpServer(
new WsServer(
new WebSocketController()
)
),
$webSock
);
$loop->run();
}
Note I changed the port number to 8443 (I don't think this has something to do) and also changed the certificate and key files for the new ones, generated as follows:
openssl req -config config.conf -new -x509 -out server.crt -days 3650
And the config.conf file is:
[req]
default_bits = 2048
encrypt_key = no
default_md = sha256
default_keyfile = server.key
distinguished_name = req_distinguished_name
prompt = no
[req_distinguished_name]
C = KH
ST = Siem Reap
L = SR
O = AHC
OU = IT
CN = localhost
[bs_section]
CA=false
All the difference lies in the last line CA=false to indicate I did not signed or acted as a Certificate Authority (CA).
This gets rid of the MOZILLA_PKIX_ERROR_CA_CERT_USED_AS_END_ENTITY message.
Then, I got rid of the lines that defined the proxy in my httpd-ssl.conf file:
<VirtualHost *:443>
ServerName ssa
DocumentRoot "d:/web/app/ssa/public"
SSLEngine on
SSLCertificateFile "${SRVROOT}/conf/server.crt"
SSLCertificateKeyFile "${SRVROOT}/conf/server.key"
SSLVerifyClient none
SSLVerifyDepth 10
<Directory "d:/web/app/ssa/public">
Options +Indexes +Includes +FollowSymLinks +MultiViews
AllowOverride All
Require local
</Directory>
#Redirect /wss /wss/
#ProxyPass /wss/ ws://127.0.0.1:8090/
#ProxyPassReverse /ws/ wss://127.0.0.1:8090/
</VirtualHost>
Please notice that for this virtual host I used the same certificate and key files I used for the Secure Websocket Server.
Ok, that was it for my certificate issue.
Now everything works as expected.

NodeJS - use other port than 80 for public access [duplicate]

I am running XAMPP on Windows to host an Apache server on port 80. Now I'm trying to have a NodeJS script running in the background but the problem is that it can only listen on port 80. If it does, everything works as it should but I can't have Apache running at the same time, because Apache takes priority and just serves my website. The NodeJS script doesn't even get to listen.
My question is: how do I switch the listening port of the NodeJS script (the specific port really doesn't matter) so that Apache can still run on port 80 and I can reach the NodeJS script from all around the world.
Part of the NodeJS code:
const http = require('http');
const port = 8080;
const host = '0.0.0.0';
server = http.createServer( function(req, res) {
if (req.method == 'POST') {
var body = '';
req.on('data', function (data) {
body += data;
doStuff(body);
});
res.writeHead(200, {'Content-Type': 'text'});
res.end('received request successfully');
}
else {
res.writeHead(405, {'Content-Type': 'text'});
res.end('not allowed method ' + req.method + ', try again with GET or POST');
}
})
server.listen(port, null, function(error){
if(!!error){
console.log("\x1b[41m%s\x1b[0m", "error while initializing listener on port " + port + ": " + error);
}
else{
console.log("\x1b[32m%s\x1b[0m", "started listener at 'http://" + host + ':' + port + "'");}
});
Additional information is in my other question which got flagged as duplicate.
Looking at your other question, which was marked as duplicate of this one, you've got some additional information there that will probably help to elucidate what you're needing. Specifically, you mention the following:
I want to host multiple http servers with NodeJS, that all get and send http requests. At the same time I want to have Apache running, which occupies port 80. If I disable Apache and let NodeJS run on port 80, it will work but I can't have them running at the same time.
This script will run and receive requests locally at port 8081, but I can't seem to send an AJAX request to it through the Internet, even after forwarding the port with my router:
I think #ankit-agarwal is probably right in that you need a reverse proxy setup to forward traffic to your different backends. Assuming you've got an externally facing IP address, you should be able to access each of your backends using the ports they are listening on. For example, if the exposed public IP address of your machine is 100.120.110.43:
+---------+------+-------------------------------------+
| Backend | Port | Web Address |
+=========+======+=====================================+
| Apache | 80 | 100.120.110.43 or 100.120.110.43:80 |
| Node1 | 8080 | 100.120.110.43:8080 |
| Node2 | 8081 | 100.120.110.43:8081 |
+---------+------+-------------------------------------+
If you want to access each of the backends without specifying the port, you have to have some way to tell your internal network which backend to serve based on the request. One way of doing this is to use path based routing, where you setup your reverse proxy to route the traffic to the different backends based on the path in the url. You didn't post your Apache configuration, but you can use your current Apache server to handle this using the ProxyPass and ProxyPassReverse directives similar to below:
ProxyPass "/node1" "http://100.120.110.43:8080/"
ProxyPassReverse "/node1" "http://100.120.110.43:8080/"
ProxyPass "/node2" "http://100.120.110.43:8081/"
ProxyPassReverse "/node2" "http://100.120.110.43:8081/"
The cool thing about using a reverse proxy is that you don't have to expose your node backends to the public. Let's assume you haven't, and they are only accessible from the internal network at 0.0.0.0:port.
Listen 80
<VirtualHost *:80>
DocumentRoot /www/apache
ServerName www.apachefrontend.com
ProxyRequests off
ProxyPass /node1 http://0.0.0.0:8080/
ProxyPassReverse /node1 http://0.0.0.0:8080/
ProxyPass /node2 http://0.0.0.0:8081/
ProxyPassReverse /node2 http://0.0.0.0:8081/
</VirtualHost>
You could also point to different hosts/ips that only you have access to.
Finally, you can also use VirtualHost and ServerName if you have different DNS records to point to the different backends.
Listen 80
<VirtualHost *:80>
DocumentRoot /www/apache
ServerName www.apachefrontend.com
</VirtualHost>
<VirtualHost *:80>
ServerName www.nodebackend1.com
ProxyRequests off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
<Location />
ProxyPass / http://0.0.0.0:8080/
ProxyPassReverse / http://0.0.0.0:8080/
</Location>
</VirtualHost>
<VirtualHost *:80>
ServerName www.nodebackend2.com
ProxyRequests off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
<Location />
ProxyPass / http://0.0.0.0:8081/
ProxyPassReverse / http://0.0.0.0:8081/
</Location>
</VirtualHost>
For any of the above to work, you need to have mod_proxy and mod_proxy_http enabled in apache.
These probably aren't the most robust examples and I haven't tested them, but they should demonstrate the idea. You can learn more here.
Just change your node.js server port something like:
var server = app.listen(8080, function() {
console.log('Ready on port %d', server.address().port);
});
where 8080 is node.js server' new port.
I haven't really understood what you meant by you're not getting any response, because I ran the same code and it works fine for me.
I only noticed something here (I kept a note for you in the comment)
server = http.createServer( function(req, res) {
if (req.method == 'POST') {
var body = '';
req.on('data', function (data) {
body += data;
doStuff(body); //you haven't defined doStuff so you will end up with a error message on this line, but you sever will still run fine
});
res.writeHead(200, {'Content-Type': 'text'});
res.end('received request successfully');
}
else {
res.writeHead(405, {'Content-Type': 'text'});
res.end('not allowed method ' + req.method + ', try again with GET or POST');
}
})
When running your post request, don't forget to add "" in your body area, select raw then choose JSON(application/json). That should run fine for you, except you might get a reference error as shown below, but you should still get your response of received request successfully.
error
doStuff(body);
^
ReferenceError: doStuff is not defined
Ensure that you're doing the same thing and let us know if your issue it resolved.
Seem something already running on your 8080 port. Simply change to another port. For example 7000
And make sure that all request you call to nodejs app like this
localhost:7000 // Normal we run at port 80 url simply localhost without port
If I want use Apache and Nodejs in same port:
npm http-proxy-middleware
1. Set Apache Port = 81
[apache dir]/conf/httpd.conf
~59: Listen 81
2. Set nodejs APP port = 3050
server.listen(3050);
// on linux ports<1000 require root privilegue
3. Use third proxy APP (http-proxy-middleware)
// https://www.npmjs.com/package/http-proxy-middleware
var express = require('express');
var proxy = require('http-proxy-middleware');
// proxy middleware options
var options = {
target: 'http://localhost:81', // target host ROOT
changeOrigin: true, // needed for virtual hosted sites
ws: true, // proxy websockets
pathRewrite: {
// '^/api/old-path' : '/api/new-path', // rewrite path
// '^/api/remove/path' : '/path' // remove base path
},
router: {
// Examples:
// when request.headers.host == 'dev.localhost:3000',
// override target 'http://www.example.org' to 'http://localhost:8000'
// 'dev.localhost:3000' : 'http://localhost:8000',
// 'localhost:9000': 'localhost:9002/sub',
// '/sub': 'http://localhost:9002',
'localhost': 'http://localhost:81', //Root to Apache
'sub.localhost': 'http://localhost:3050', // internal
'sub.mydomain.com': 'http://localhost:3050', //external
},
};
// create the proxy (without context)
// var proxy_wp = proxy(options_wp);
var proxy_node = proxy(options);
// mount `exampleProxy` in web server
var app = express();
app.use(proxy_node);
app.listen(80);
Then:
localhost:80 - is apache site
sub.localhost:80 - node
localhost:80/sub - node, if you set
for task runner i use npm PM2
This is same scenario as using NodeJs in a Shared Hosting. I have written a blogpost about it here
Let me give an excerpt.
Just run the NodeJS server at let's say 8080 port.
Now, let's say your Apache serves at http://example.com, create a folder in your public_html or www. let's say the name is server. So, your new folder path is http://example.com/server
create a .htaccess file in the server folder
add the following lines,
RewriteEngine On
RewriteRule ^$ http://127.0.0.1:8080/ [P,L] #which is your node server ip:port
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ http://127.0.0.1:8080/$1 [P,L] #same ip:port
This will redirect all the requests from http://example.com/server to your Node server.

How do I get nodejs to run without a port number on a Apache server

I have a nodejs api application running inside a codeigniter environment. Im trying to access the nodejs api's without using a port number in the url
currently you can only hit the node api at
http://wrl.xx.com:8010/api
And I would like to have it accessible through a url like :
http://wrl.xx.com/api/
I tried to run a reverse proxy with no success
<VirtualHost *:80>
ServerName wrl.xx.com
ProxyRequests off
<Proxy *>
Order allow,deny
Allow from all
</Proxy>
ProxyPass / http://localhost:8010/
ProxyPassReverse / http://localhost:8010/
ProxyPreserveHost on
</VirtualHost>
Assuming you intend to differentiate requests looking for the nodejs app from requests seeking the codigniter app by seeing /api as the root path, try:
ProxyPass /api http://localhost:8010/api
ProxyPassReverse /api http://localhost:8010/api
See ProxyPass and ProxyPassReverse for more magic.
Disclaimer: I have no experience with codeigniter, so this may be non relevant, or false.
Your node.js server listen to port 8010, which is non standard, that is why you need to indicate it in the URL.
You seems to imply codeigniter is already listening to the standard port (80).
The way I see, with no knowledge of codeigniter, to go around the issue would be to either host all the node.js url in codeigniter, and redirect them to port 8010:
Client call /node on port 80
CodeIgniter call /node on himself at port 8010
Node get the request and answer
Code igniter gove the answer to the client
Or the reverse, which would be to host any codeigniter URL in node.js, and redirect them to whatever port codeigniter will listen.
Or you will need to configure Apache to redirect the request to port whatever codeigniter on or 8010 depending of the url.

How to configure my node.js application on a dedicated server to put it online?

I've installed node.js on my server(it is a virtual windows server). I am also having the domain. I want to run my node.js application on a port 8001 so that when I open, say http://example.com:8001/ it will open my application.
Actually, I am also having a PHP site running on Apache server on port 80(XAMPP). It is perfectly working fine when I open say, http://example.com.
Thanks
In apache, create a new vhost. You have to proxy all requests through apache to your node app as apache is listening to port 80.
<VirtualHost *:80>
ServerName example.com
ProxyRequests off
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
<Location />
ProxyPass http://localhost:8001/
ProxyPassReverse http://localhost:8001/
</Location>
</VirtualHost>
If you are not on a name-based virtual host environment you can just start your Node.js server and it will be available to the world from the defined port. But if the server IP address runs many services using different domain names and you want your Node.js server to reply only from http://example.com:8001 you can use e.g. the vhost module on your node server to listen to specific domain only:
var express = require('express'),
host = require('vhost');
var app = express();
app.get('/', function(req, res) {
res.send("Hello from vhost");
});
var main = express();
main.use(vhost('example.com', app));
if (!module.parent) {
main.listen(8001);
}
You can also proxy the requests through a web server like Apache or nginx, but to have the service responding from port 8001 you would need to bind the web server to port 8001 in addition to 80 you are already using, and run your Node.js server on some other port.
Generally people prefer using the standard HTTP port and use a web server to reverse proxy traffic to the Node.js server running on a non-privileged port. As you already have the PHP application on your domain name you would then follow advice by #SamT and run your Node.js application from e.g. http://mynodeapp.example.com

Categories