Apache, Node, .htaccess - node.js

I have an apache webserver listening on port 80. With apache, a PHP/MySQL system based on Zend framework. And I also have a node server listening on port 3000.
When a client sends a request, always on port 80, it's therefore first handled by apache. I would like to apply the following rules before treating the request:
if content-type is "application/json" then
use apache web server
else if content-type is "application/zend" then
use apache web server
else
use node server
Here content-type is sent in the request headers. Content-type "application/zend" is a custom content-type to say that, for this type of particular request, we don't want to use node server (I need this for some reasons).
I've tried to modify httpd-vhosts.conf with
ProxyPreserveHost on
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
But that's of course not enough as not everything should be handled by the node server (listening on port 3000). Hence some rules should be added. But I'm unsure where/how. I also tried to change the .htaccess file, but not sure how either.
Any help would be great! Thanks!

This should work (in .conf file):
RewriteEngine on
RewriteCond %{HTTP:Content-type} !=application/json
RewriteCond %{HTTP:Content-type} !=application/zend
RewriteRule ^ http://%{HTTP_HOST}:3000%{REQUEST_URI} [P]
Keep in mind that this might carry a performance penalty, and if most of your requests end on node, we should perhaps search for better solution.

Related

POST becomes GET after ProxyPass

I have a nodejs app running inside a docker container on port 3050. If I allow the port through the firewall then everything works fine. But if I try to ProxyPass it then the app seems to receive GET instead of POST.
ProxyPass / http://localhost:3050/
When I look at the access log apache receives the request as a POST. But logging the req.method in expressjs results in GET. I have also tried loads of other settings
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://localhost:3050/
ProxyPassReverse / http://localhost:3050/
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"
The strangest thing is that I am Proxying lots of other services like gitlab and keycloak without any problem.
Could it be something to do with HTTP 1.1 or HTTP 2? Or does my httpd server have some setting messed up?
I was only testing with postman...obviously in future I should try curl or something as well. Turns out that postman has a setting "Redirect with the original HTTP method instead of the default behavior of redirecting with GET." which is turned off by default. I don't know whether the browser will behave like this but at least now it seems to be working
update:
Actually it wasn't even that setting. it was because i had not prefixed the url with https:// due to a training course which excluded the protocol because we weren't working with secure. so the httpd server proxied port 80 to 443 and postman didn't handle it correct. as i would be hitting directly https in production it shouldn't be a problem

apache and node express with node rewrites

I have the following problem:
I have an apache serving files under url.com/ and url.com/a
I also have a node-express server listening on port 3000, which is not publicly accessable.
Now, I would like to be able to access the node server for any url like url.com/b/.
My hosting company and google referred me to using .htaccess rewrites like so under url.com/, but it does not work:
RewriteEngine on
RewriteRule ^(.*)b(.*)$ https://url.com:3000/b/$1
Does the port need to be publicly accessable for the mod_rewrite approach to work?
What is the proper way to set something like this up?
Many thanks!
Try mod_proxy:
<Location /b>
ProxyPass http://localhost:3000/
ProxyPassReverse http://localhost:3000/
</Location>
unfortunately, since i deployed on a managed virtual server, i wasnt able to use Elvis' solution, modifying the httpd.conf file.
I ended up using this solution, modifying the .htaccess file in the folder public_html/b:
RewriteEngine on
RewriteRule ^(.*) http://localhost:3000/$1 [P]

Apache , NodeJs, Server Sent Events

First of all, I know (Putting Node under Apache) this is not the approach to go but due to time constraint I cannot experiment.
I am trying to use Server Sent events for a mobile application. After reading all over Net, I figured out that Nodejs is the server to go for. My 80/443 port is occupied by Apache Web server, so I want Node To run behind Apache.
The Problems which I am facing are:-1. I am not able to get the close/end events on refreshing browser or closing browser rather I get after a fixed certain amount of delay, so not able to maintain when the client shuts down connection in Nodejs.
req.on("close", function() {
removeConnection(res);
console.log('Connection closed');
});
2. Apache is sending Keep-Alive:timeout=5, max=100 which I dont want as I want client to be connected forever till anyone closes connection, due to this Browser automatically closes connection and I start getting net::ERR_INCOMPLETE_CHUNKED_ENCODING. How Can I modify this value only for Node Proxy Requests.I have added ProxyPass /events http://localhost:5000/events
ProxyPassReverse /events http://localhost:5000/eventsResponse Headers
Access-Control-Allow-Headers:key,origin, x-requested-with, content- type,Accept,Content-Type
Access-Control-Allow-Methods:PUT, GET, POST, DELETE, OPTIONS
Access-Control-Allow-Origin:*
Connection:Keep-Alive
Content-Type:text/event-stream; charset=utf-8
custom:header
Date:Wed, 13 Jan 2016 18:12:48 GMT
Keep-Alive:timeout=5, max=100
Server:Apache/2.4.7 (Ubuntu)
Transfer-Encoding:chunked
X-Powered-By:Express
Note:- All this is happening when I am using Apache to proxy to Node, else if I directly hit Node (which I cannot in prod due to blocked port) everything works fine.
The KeepAlive settings by default allowed only in server or virtual host configuration.
But during the request processing, apache2 use environment variables (based on apache configuration) to determine the current settings.
Fortunately with mod_rewrite, you can alter apache environment variables on request basis, so you can disable keepalive on specific request.
For example:
#Load rewrite module
LoadModule rewrite_module modules/mod_rewrite.so
#Enable mod_rewrite functionality
RewriteEngine On
#rewrite rule inside locationmatch
<LocationMatch ".*\/sse\/.*">
#This is not required, used only for debug purposes
Header set X-Intelligence "KEEPALIVEOFF"
#Here goes the mod rewrite environment variable trick
RewriteRule .* - [E=nokeepalive:1]
</LocationMatch>

Redirect based on port number?

Is it possible to redirect domain.com:88 to domain.com:8080 using htaccess & mod_rewrite?
And example please?
If htaccess can't do it, waht are other options?
If you get requests on different ports you need to have servers listening on those ports. Inside those servers you can certainly configure rewriting rules, you don't even have to check the port, since it is implicitly given inside the servers logic.
Note that you can configure several virtual servers inside an apache http server.
You can also configure a single server to listen on several ports. Check for documentation about the Listen configuration option inside the http server configuration. Then indeed you have to test for the port. You can do that inside the rewriting module by using the RewriteCond command together with the SERVER_PORT variable. So something like:
RewriteEngine on
RewriteCond ${SERVER_PORT} 88
RewriteRule ^(.*)$ http://some.server.addr:8080/$1 [QSA,L]

Pointing my domain to my node.js instance

I own a server running whm / cpanel, and I have recently been experimenting with node.js. I have a little node test server running and i would like to point a domain at it. Up till now, I have been using whm to create accounts and deal with domains, but this is a different scenario, and I have little knowledge about how to make a domain point to something on my server when there are multiple other domains pointing to other different things on my server at the same time.
Thanks
Ok, I have never tried this, but you could use a rewrite rule in a .htaccess file and rewrite everything to goto to port 8000 where you have your node.js server running.
So first, set up your node.js server to listen to port 8000.
Then, create your domain like normal in cpanel, and in the doc root add a .htaccess file with this rewrite:
RewriteRule ^ "\ http: \ / \ / 127.0.0.1 \:% (8000) REQUEST_URI" [P, QSA, L]
That should just forward everything internally to port 8000 where node.js will take care of it. But I don't know how persistent connections / websockets will work with this strategy. It may be better to skip apache in those cases by going directly to the port 8000 on your server.
Source: http://es.w3support.net/index.php?db=sf&id=59994
This is a little bit tricky, since cpanel is going to use apache to configure the domains, and apache has already taken port 80 without a doubt, so you can't share port 80 between apache and node.js. You will not be able to configure this through cpanel.
You could just point the domain to your server and have node listen to another port such as 8000.
Then go to http://mydomain.com:8000/
So apache/cpanel handles requests to ports 80 and 443, and node handles requests to port 8000.
It is very possible to run multiple web servers on one box, but they each need their own port(s)
I managed to do it like that:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteCond %{SERVER_PORT} !^3000$
RewriteRule ^ http://%{HTTP_HOST}:3000%{REQUEST_URI} [P,QSA,L]
</IfModule>
Anything else didn't worked for me :(
Here I check if the port is not 3000 and if the protocol is not https then I point the domain to port 3000 (you can put the port you use with node.js) you can remove the RewriteCond %{HTTPS} !=on in case you don't care to check for the protocol.
I do some R&D locally but in production I believe I will use nginx + node instead of apache.

Resources