standard way to disable X-powered-by header in Passenger? - ruby

I couldn't find any way to disable Passenger's X-Powered-By header:
X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.11
Is it possible to do that without modifying its sources and removing headers on the HTTP server level?

On Apache you can unset headers:
# Hide/Remove the Passenger Headers
Header always unset "X-Powered-By"
Header always unset "X-Runtime"
It will not remove all names (since services such as Plesk will still append their name), but Passenger can be removed this way.
Kudos to John Trupiano:
https://groups.google.com/forum/?fromgroups=#!topic/phusion-passenger/LKAKH0PEyW0

Short answer: YES.
update: 2018
Use proxy_hide_header if downstream, or use more_clear_headers
Original Answer
I leave the fact that I use nginx+passenger .. but you can completely remove them with
remove_header X-Header-Name-To-Remove;
So you can remove both by
server {
...
remove_header X-Powered-By;
remove_header X-Runtime;
...
}
This removes all the headers, it can also be in a location directive instead of server.
..
Here are my common directives, as I leave 'apache prod' equiv on mine.
server {
...
remove_header X-Runtime;
server_tokens off;
passenger_show_version_in_header off;
...
}
Provides a service header like..
Server:nginx + Phusion Passenger
X-Powered-By:Phusion Passenger
This is the closest equiv of apache2 ServerTokens Prod directive that I can do.

Short answer: no.
There is no configuration option in passenger to disable the X-Powered-by, so you need to do one of
filter
edit source
monkeypatch
passenger code:
#RequestHandler::process_request
headers_output = [
STATUS, status.to_i.to_s, CRLF,
X_POWERED_BY, #passenger_header, CRLF
]
#AbstractRequestHandler::initialize
#passenger_header = determine_passenger_header
#AbstractRequestHandler::determine_passenger_header
def determine_passenger_header
header = "Phusion Passenger (mod_rails/mod_rack)"
if #options["show_version_in_header"]
header << " #{VERSION_STRING}"
end
if File.exist?("#{SOURCE_ROOT}/enterprisey.txt") ||
File.exist?("/etc/passenger_enterprisey.txt")
header << ", Enterprise Edition"
end
return header
end

more_clear_headers 'Server' 'X-Powered-By' 'X-Runtime'; works for me as mentioned in http://www.michaelrigart.be/en/blog/nginx-and-passenger-install-in-production-environment.html.

To completely remove X-Powered-By and Server headers from Nginx+Passenger and not just hide versions, add this to your http block in nginx.conf:
server_tokens off;
more_clear_headers Server;
more_clear_headers X-Powered-By;
You could also set your own:
more_set_headers "Server: ACME";
This will work even if passenger_show_version_in_header off; is not set, but it might be smart to add it as well in case.
Remember to restart the server for these to take affect. You should test your config before restart though: sudo nginx -t.
Information via calvin.my

Related

Api-platform: corsAllowOrigin doesn't set *

Oke so back to https://api-platform.com :)
So I currently have corsAllowOrigin: "*" #to allow all origins in my helm values file (as per docs). To make sure that the propper headers are bieng set on return values.
Now I would expect (as per docs) that the Access-Control-Allow-Origin: would now go to "*" however it goes to Access-Control-Allow-Origin: null. That's of course a bit annoying because it prevent react native apps of accessing the API.
Question here, is this a bug? Am I using the wrong values? Or overlooking something?
Sets .env file with:
###> nelmio/cors-bundle ###
CORS_ALLOW_ORIGIN=['*']
###< nelmio/cors-bundle ###
By default, API Platform uses nelmio cors and the default config use the environment variable CORS_ALLOW_ORIGIN.
With that you can allow any url with this config in your .env (or .env.local) with CORS_ALLOW_ORIGIN=^https?://.*?$
As the others have said, CORS is handled by nelmio/cors-bundle. If you don't wish to modify env files, the actual package configuration for it is documented on its GitHub page https://github.com/nelmio/NelmioCorsBundle.
The configuration you'd want to modify is the allow_origin configuration, which can have a default value or can be configured based on the path of the current request. Pretty neat.
In config/packages/nelmio_cors.yaml:
nelmio_cors:
defaults:
...
allow_origin: []
...
paths:
'^/api/':
...
allow_origin: ['*']
...
'^/':
...
allow_origin: ['^http://localhost:[0-9]+']
...

Does my Sinatra API application need a class declaration?

Someone developed an API application for me that works well. Unfortunately, it doesn't log anywhere and there are no logs at all. The app runs with the "rackup" command and sits behind an nginx web server. The Sinatra errors are not logged to the nginx logs.
The app.rb file looks something like this:
require './libs'
require 'sinatra'
require 'sinatra/namespace'
set :bind, '::1'
before do
content_type :json
headers 'Access-Control-Allow-Origin' => '*', 'Access-Control-Allow-Methods' => ['OPTIONS', 'GET', 'POST']
end
namespace '/api/v1' do
namespace '/getit/:thingtoget' do
helpers do
def myhelper1
<stuff>
end
def myhelper1
<stuff>
end
end
before do
myhelper1
myhelper2
end
get '/info' do
WidgetDomain::get_info(#va1, #var2).to_json
end
<more API paths here>
end
Now this is working fine. But now I want to introduce logging. So I looked at the Sinatra README and it said I could enable logging like so:
class MyApp < Sinatra::Base
configure :production, :development do
enable :logging
end
end
Do I put that above the namespace stuff? If I declare an app like that, does my namespace stuff need to be inside that app code somehow? I don't have a grasp of how this works at all.
It almost looks like it's trying to log in the nginx log, but here's what an error line looks like there:
2018/12/30 19:53:15 [error] 6615#0: *21522 connect() failed (111: Connection refused) while connecting to upstream, client: <someip>, server: api.example.com, request: "GET /api/v1/getit/thingtoget1/stuff/var1/var2/var3 HTTP/1.1", upstream: "http://[::1]:9292/api/v1/getit/thingtoget/stuff/var1/var2/var3", host: "api.example.com", referrer: "an HTML page from the nginx server"
It's almost like it's trying to connect back to the server to retrieve a message or something. But in case the logging has something to do with the way I've declared the server in the nginx configuration, here it is:
server {
listen 443;
listen [::]:443;
server_name api.myapp.com;
ssl on;
ssl_certificate /etc/nginx/ssl/myapp_com.pem;
ssl_certificate_key /etc/nginx/ssl/star_myapp_com.key;
location / {
proxy_pass http://localhost:9292;
}
}
Have a look at Sinatra's README in the Logging section but I tend to set up a logger outside of the Sinatra app in case other bits get bolted on or several apps are used together and I can use the same logger for all of them. Simplest way is a global variable (one of the few places they're acceptable, but it's not the only way) :
require 'mono_logger' # because it's thread safe
require 'pathname' # because paths aren't strings :)
log_path = Pathname(__dir__).join("logs/app.log")
$logger = MonoLogger.new(log_path)
$logger.level = MonoLogger::INFO
Then in a route or wherever:
get '/' do
$logger.info "here"
In my terminal:
$ cat logs/app.log
I, [2019-01-07T13:03:52.989415 #64378] INFO -- : here
As to configuration blocks, you don't need to worry about putting them within a class declaration unless you're using a modular app (see Modular vs. Classic Style in the README) and yours is in the classic style.
Configuration blocks aren't namespaced (Sinatra::Namespace handles things that take a route as an argument, like get and before) so follow convention and stick it near the top of the file.
Hope that helps.

Nginx Echo Subrequest not working

I am new to Nginx.
My requirement is I need to make a service call but along with proxy passing that request, I need to make call to another service/servlet. For this I decided to use Echo module to use the echo_subrequest_async option.
However the subrequest is not working and even simple echo print is not working. Where does echo "hello" supposed to go? to the client side (my guess)
Below is my configuration (some notes):
Both the servers are java servers which are running on my local box
my os is mac osx version 10.9.5
3, I compile nginx 1.6.2 from source and with modules pcre and http echo
nginx version: nginx/1.6.2
built by clang 5.1 (clang-503.0.40) (based on LLVM 3.4svn)
configure arguments: --with-pcre=/Users/xxxx/project/pcre-8.35 --add-module=/Users/xxxx/project/echo-nginx-module-0.57 --with-cc-opt=-Wno-deprecated-declarations
nginx config I have used is as follows
http {
server {
listen 80;
server_name localhost;
# this will handle the initial request
location /messaging-service {
default_type "text/plain";
echo "in the messaging service call";
echo_flush;
echo_subrequest_async GET '/mywebapp/second';
proxy_pass http://localhost:8090/messaging-service/;
}
# this is where the sub request should go,note its different service
location /mywebapp/second {
echo "Going to make another call on different server !!";
echo_flush;
proxy_pass http://localhost:8080/mywebapp/second/;
}
}
}

nginx Windows: setting up sites-available configs

I'm trying to set up Nginx on my Windows development environment. I can't find how to create something similar to "sites-enabled" on Linux where Nginx would look for (links to) active virtual host configurations.
Is there a way to do something similar with a directory with shortcuts to the actual configuration files and Nginx scanning that directory? Or is there another way to hook up a virtual host configuration other than copying the host configuration to nginx.conf?
In windows you have to give full path of the directory where the config files are located. There are two files to update: nginx.conf, which tells nginx where to find web sites, and localhost.conf, which is the configuration for a web site.
It is assumed that nginx is installed in C:\nginx. If the installation directory is at another path, you will have to update that path accordingly, wherever it appears in the following two configuration files.
nginx.conf
Location: C:\nginx\conf
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#to read external configuration.
include "C:/nginx/conf/sites-enabled/*.conf";
}
localhost.conf
Location: C:\nginx\conf\sites-enabled
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
The "sites-enabled" approach as used by some Linux packages of nginx utilize include directive, which understands shell wildcards, see http://nginx.org/r/include. You may use it in your own config as well, e.g.
http {
...
include /path/to/sites/*.conf;
}
Note though that such approach might be very confusing (in particular, it would be hard to tell which server{} is the default one unless you use default_server explicitly).
The following worked for me but only AFTER I moved my main nginx exe folder from c:/Program Files (x86)/nginx-1.7.0 to c:/nginx-1.7.0 (because I think it doesn't handle spaces in file paths well):
http {
...
include "f:/code/mysite/dev-ops/nginx/dev/mysite.conf";
}
Till the time of writing this answer (7 Jan 2022) non of the other answers fully answer this question.
Wildcards (include a/*.b) just include a list of vhosts which cannot be disabled/enabled. sites-enabled and sites-available is about being able to disable a vhost without deleting the corresponding config file.
Nginx has only one config file (nginx.conf), which in turn includes other files. The ability to include files is what led to enabled/available design.
So the directory structure goes as follows:
conf // or whatever
|__nginx.conf
|__sites-enabled
|____default // symlink to sites-available/default.conf
|__sites-available
|____default.conf // You can omit the extension but I just like it
|____whatever.conf
|____some vhost.conf
|____another vhost.conf
|____disabled vhost.conf
|____other config files ...
# nginx.conf
http {
# ...
include path/to/sites-enabled/*; # include the enabled ones
}
In windows (cmd) you do:
mklink Link Target
# for example
mklink default X:/path/to/nginx/conf/sites-available/default.conf
Many think that windows doesn't have symlinks, it does :-)
I use a slightly more complex config directory structure, for development:
conf/
|__nginx.conf
|__sites-enabled/
|____some-site // sites-available/some-site/{env} where {env} is either dev or prod
|__sites-available/
|____some-site/
|______prod.conf
|______dev.conf
|______dev/
|________www.conf // vhost (server {}) for the www subdomain
|________api.conf // same as above but for the api subdomain
|________root.conf // vhost for the top level domain (e.g example.com without any subdomain prefix)
|______prod/
|________www.conf
|________api.conf
|________root.conf
|______snippets/
|________http.conf // listen on ipv4 80/ipv6 80 and redirect http to https
|________https.conf // listen on ipv4 443 ssl/ipv6 443 ssl and `include`s ssl.conf
|________ssl.conf // ssl config, pay attention to permission
You can include your config with a relative path in your nginx.config (the relative path is just the path of the config file itself in contrast to the logs path for example):
http {
include mime.types;
default_type application/octet-stream;
include ../sites-enabled/*.conf;
...
}

HTML 5 Cache manifest gets cached itself

I have a problem of that it seems that the cache.manifest file gets cached itself. Meaning every changes to the file are not being noted by (Mobile) Safari, so it will never update and always show the last cached files.
I tried to avoid it using an .htaccess file in the same directory as the cache.manifest file:
ExpiresActive On
ExpiresDefault "access"
That didn't help so I changed cache.manifest in a php file that contains the following headers:
header("Expires: Mon, 26 Jul 1990 05:00:00 GMT");
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header('Content-Type: text/cache-manifest');
Anyone have other ideas of how I can make sure the cache file itself will get retrieved if possible?
Works on: Safari (Desktop), Chrome (Samsung Galaxy Tab v10.1), Firefox
Fails on: Chrome, Safari (iOS)
Renamed the cache.manifest.php back to cache.manifest and added the following lines to the .htaccess
<IfModule mod_expires.c>
Header set Cache-Control "public"
ExpiresActive on
# cache.manifest needs re-requests in FF 3.6 (thx Remy ~Introducing HTML5)
ExpiresByType text/cache-manifest "access plus 0 seconds"
</IfModule>
If I change the revision comment within the cache.manifest and refresh it on Safari (iOS) it still shows me the old file. I am clueless.
According to the HTML5 documentation, if an application cache manifest file is byte-for-byte the same as a previous one, regardless of HTTP cache headers for expiry/etc, it is considered to not require an update.
At the bottom of your cache manifest file, you need to include a comment at the bottom of the file with the timestamp of the most recently modified file, e.g.:
# last modified: Thu, 30 Jun 2011 01:19:46 GMT
This will break up the byte-for-byte identicalness, even if the list of files remains the same but a few are updated.
As alluded to in other answers, cache manifests are a real pain to deal with.
I've tweaked a PHP manifest "build" script for my HTML5 notepad app.
Tested and working on Chrome, Firefox, IE8+, Android and iOS.
It's open source and available here: https://github.com/JasonHanley/note5/blob/master/build.php
I also use the ExpiresByType text/cache-manifest "access plus 0 seconds" in my .htaccess and I believe that is necessary in addition to generated manifest timestamps.
I've just stumbled onto this one myself, and in a similar vein to SimpleCoders suggestion I'd suggest that if you are using Apache you can generate the cache.manifest using Server Side Includes, eg:
CACHE MANIFEST
# <!--#flastmod file="index.html"-->
# <!--#flastmod file="whatever.js"-->
# <!--#flastmod file="whatever.css"-->
whatever.js
whatever.css
That way, whenever any of those files are updated, the manifest will change automatically. You may also need to enable includes for that file and disable caching, eg: Apache config something like:
Alias /whatever /var/www/whatever
<Directory /var/www/whatever>
Options +Includes
AddHandler server-parsed .manifest
</Directory>
CacheDisable /whatever/ihealth.manifest
Check your server logs to make sure you're returning the file with a "200 Okay" rather than a "304 Not Modified".
The cache manifest is a terrible piece of technology.
The browser is not caching the manifest; instead, it's just failing to recognize that it has changed which is what you are observing. Try adding a random comment or two to your manifest (prepend comments with #) and then see if it works.
Just modifying files that the manifest references won't trigger the browser to redownload the manifest. If this is what you were hoping for, then try this: Use a PHP file to generate your manifest. Of course, use header to set the proper MIME type. After you have echoed out all of your resources, echo out the hash of the timestamp of all of those resources. That way, if one of them is modified, the manifest file changes. This is what I'm using:
// Collect a list of resources we need to check (customize to your needs)
$files = array(
"/scripts/script1.js",
"/scripts/script2.js",
"/scripts/script3.js",
"/scripts/script4.js",
"/css/style.css"
);
$filetime = 0;
foreach ($files as $file) {
$filetime += filemtime($file);
}
// This echoes out the hash of the filetimes as a comment
echo "#" . sha1($filetime);

Resources