rails application display blank html - ruby-on-rails

Ruby 1.92
Rails 3.1.1
Nginx 1.1.6
Passenger 3.0.7
My rails application works fine on my laptop, but it does not work on amazon server. I open it in chrome, browser display nothing, HTTP header like below:
HTTP/1.1 200
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
Status: 302
X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.7
If I run rails server, it does work, I can get correct html. Nginx cannot generate correct content-length?
nginx config
server {
listen 8000;
server_name xxxx;
root /xxx/xxx/public;
passenger_enabled on;
rails_env development;
location = /favicon.ico {
expires max;
add_header Cache-Control public;
}
location ~* \.(png|gif|jpg|jpeg|css|js|swf|ico)(\?[0-9]+)?$ {
access_log off;
expires max;
add_header Cache-Control public;
}
}
http raw message is below
total 3496 bytes return, content-length is wrong,so browser do read rest html
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Content-Length: 0
Connection: keep-alive
Status: 200
X-Powered-By: Phusion Passenger (mod_rails/mod_rack) 3.0.7
X-UA-Compatible: IE=Edge
ETag: "12aa68a45bf774886311f827d2149cbe"
Cache-Control: max-age=0, private, must-revalidate
X-Runtime: 0.499998
Server: nginx/1.1.6 + Phusion Passenger 3.0.7 (mod_rails/mod_rack)
<!DOCTYPE html>
<html>
<head>
<title>xxxx</title>
......

A HTTP status of 302 is usually a redirect. Are there any other headers or body content? I'd expect a location header telling the browser where to redirect to.

Related

How to verify HSTS is working as expected in Rails application?

Most of the documentation talks about adding config.force_ssl = true which provides HSTS to Rails application. Well, how can I make sure its working as expected? How can I test HSTS header is added for every request? Any help is much appreciated.
Use curl -I https://your_website.domain or browser developer tools to view response headers. You're interested in the Strict-Transport-Security header:
curl -I https://www.ssllabs.com/
HTTP/2 200
date: Fri, 23 Apr 2021 15:25:17 GMT
server: Apache
x-content-type-options: nosniff
x-xss-protection: 1; mode=block
strict-transport-security: max-age=31536000 <-- this one
cache-control: no-cache, no-store, max-age=0, must-revalidate
pragma: no-cache
expires: 0
x-frame-options: DENY
content-type: text/html;charset=ISO-8859-1
content-language: en-US
content-length: 6587
set-cookie: ...
content-security-policy: ...

Nginx X-Frame-Options

i use nginx 1.8.0 under centOS 6.7 which serving Ruby On Rails 4.2.3 application.
The Problem:
I need to enable iframe options for all domains so tried this:
X-Frame-Options: *
then when i check headers i see it twice 1 time with SAMEORIGIN and one time with *, here is the response:
HTTP/1.1 200 OK
Server: nginx/1.8.0
Date: Sun, 01 Nov 2015 15:48:32 GMT
Content-Type: text/html; charset=utf-8
Connection: keep-alive
Status: 200 OK
Strict-Transport-Security: max-age=31536000
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
ETag: W/"d14b3de05fb18ebe4a94774c8f209e7f"
Cache-Control: max-age=0, private, must-revalidate
Set-Cookie: guess_locale=en; path=/; secure
Set-Cookie: _admin_numgames_com_session=Y3N0QjR2NXY0VFlZMlVnMHJLZC9WbUVraldZYjhpeHo0UG41akpaZE1rb0tQWS9YeGpkcklTRmViUU5aVmJpUElCcWpMaFJWQmpIWHRSazI4TE9QdTgvQ2VVRGYrSW9VcjA4eWVCMVlsUHJRejR1WmNoQWZoL2hGeVA1ZHp5YWxPdFZ4S25ydEtTamVnbFlZMEhJRDdXalQ2MU93T24vWnR6b28wM0NvYS82Nm1XMGV2Njh4djIzR1RNb2w3WTVHUDM3cVl3NnVrQnJ1WTMyU3I4dVBjY3RORWRQSlk2VmhNVnRVelZRbHRVWT0tLU9DYVBIZUxoUXlLN2VmZ01VNEhab3c9PQ%3D%3D--fa2a9d6817b5464b82a2babd784ed098f2526eeb; path=/; secure; HttpOnly
X-Request-Id: 4762503a-a9a8-41ce-b1a7-26269b7e9184
X-Runtime: 0.963198
X-Frame-Options: *
there is only 1 time declare this option so why i see it twice? and how do i remove this option so any one will be able to use my domain with iFrame?
OK so i found the solution and Rails was the problem he sent the header, just needed to add into production.rb file:
config.action_dispatch.default_headers = {
'X-Frame-Options' => 'ALLOWALL'
}

HTTP header in Javascript files with puma on development

I have a Rails application, which uses the comfortable mexican sofa CMS. I needed server side events with ActionController::Live, so i use Puma instead of the standard Webrick.
Sometimes some of the javascript assets get served as plain/text and contain the HTTP header like in the following file:
0
HTTP/1.1 200 OK
Content-Type: application/javascript
Cache-Control: public, must-revalidate
Last-Modified: Tue, 20 May 2014 09:39:06 GMT
ETag: "9fad3cb6ef7afd353261ec38da25c2e9"
X-Request-Id: 043c6782-4e7c-471a-b6ba-6ea142242fa4
X-Runtime: 0.032228
Content-Length: 820
(function() {
$(function() {
$('form').on('ajax:success', function(e, data, status, xhr) {
...
Any ideas what's the matter and how to fix this?
As it seems this only occurs in Chrome. Firefox and Safari don't have any problems.

Rails 4, Puma, Nginx - ActionController::Live Streaming dies after first chunk sent

Here's a bare-bones Rails 4 project I've set up to troubleshoot my problem:
https://github.com/rejacobson/rails4-streamtest
I have a route set up at /home/stream that should stream a line of text 5 times in 1 second intervals.
def stream
5.times do |n|
puts "Streaming: #{n}"
response.stream.write "Streaming: #{n+1}"
sleep 1
end
rescue IOError => e
puts 'Connection closed'
ensure
response.stream.close
end
When I run puma using tcp://, without nginx, the streaming works perfectly.
curl -N http://localhost:3000/home/stream
And I get the 5 lines streamed back, no problem.
When I introduce nginx, curl will output the first line but immediately exit after that. I do continue to see output from the puts calls on the server and logs, so I know the request is still processing in the 5.times loop.
It also doesn't throw an IOError exception like it would if the user cut the connection.
Here's what I've tried so far:
Different combinations of nginx directives in the main conf file and
the server conf.
Changing rails settings.
Various puma config settings.
Setting all kinds of different headers in the controller method in the hopes that it was a caching issue.
Searching the internet has provided very little help as well.
I'm at a loss and require some direction.
Here's the output of both curl calls, with and without nginx.
Without nginx
~/projects/streamtest ▰ master ▰
ryan mirage ▰▰▰▰ curl -i -N http://192.168.1.100:3000/home/stream
HTTP/1.1 200 OK
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-UA-Compatible: chrome=1
Cache-Control: no-cache
Content-Type: text/html; charset=utf-8
Set-Cookie: request_method=GET; path=/
X-Request-Id: 9ce86358-4476-404a-97e5-769c16ec7b0c
X-Runtime: 0.978099
Transfer-Encoding: chunked
Streaming: 1Streaming: 2Streaming: 3Streaming: 4Streaming: 5
puma.stdout
Streaming: 0
Streaming: 1
Streaming: 2
Streaming: 3
Streaming: 4
[8048] 192.168.1.100 - - [14/Mar/2014 21:04:50] "GET /home/stream HTTP/1.1" 200 - 6.0661
With nginx
~/projects/streamtest ▰ master ▰
ryan mirage ▰▰▰▰ curl -i -N http://192.168.1.100:3000/home/stream
HTTP/1.1 200 OK
Server: nginx/1.4.5
Date: Sat, 15 Mar 2014 04:02:40 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-UA-Compatible: chrome=1
ETag: "a505e0aa3b11b25301a9a704252a519a"
Cache-Control: max-age=0, private, must-revalidate
Set-Cookie: request_method=GET; path=/
X-Request-Id: 8983d199-026b-4082-a5f1-f1d6c886a3d6
X-Runtime: 0.016516
Streaming: 1
puma.stdout
Streaming: 0
[7558] 192.168.1.100 - - [14/Mar/2014 21:02:40] "GET /home/stream HTTP/1.0" 200 - 0.0214
Streaming: 1
Streaming: 2
Streaming: 3
Streaming: 4
What's interesting, and I've just noticed it, is that the location of the get request log line:
"GET /home/stream HTTP/1.0" 200
is different in each curl call, and is placed in relation to how much text is actually streamed.
Any ideas as to what's going on here? Why can't rails stream the entire thing when using nginx?
Solved
It turns out all that I needed was this line in my location directive to get streaming working through nginx:
proxy_http_version 1.1;
I discovered this fix when investigating the keepalive directive in nginx's upstream module:
http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive
This piece of text in particular clued me in:
For HTTP, the proxy_http_version directive should be set to “1.1” and the “Connection” header field should be cleared:
upstream http_backend {
server 127.0.0.1:8080;
keepalive 16;
}
server {
...
location /http/ {
proxy_pass http://http_backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
...
}
}
It seems that nginx defaults to, proxy_http_version 1.0;
And according to Wikipedia, http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol
HTTP/1.1 introduced chunked transfer encoding to allow content on persistent connections to be streamed rather than buffered.
So there was my problem.
TIL

Rails3 and NginX CORS headers

I have a Rails3 app hosted via NginX which provides a JSON API that shall support cross origin resource sharing (CORS).
The related headers should be added via NginX, not via the Rails app.
Therefore I added a catcher in routes.rb to fetch OPTIONS preflight requests:
match "*options", controller: "application", action: "options", constraints: { method: "OPTIONS" }
and I added the corresponding endpoint to my application controller:
def options
render :text => "", :layout => false
end
Works. Now I want a wide open CORS config for my NginX:
server {
listen 80;
server_name localhost;
passenger_enabled on;
root /home/deployer/apps/fooapp/current/public;
location /v1 {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-FooApp-Auth-Token';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 200;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-FooApp-Auth-Token';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-FooApp-Auth-Token';
}
}
}
Great, OPTIONS request have all the needed headers in the response now:
curl -i -H'Accept: application/json' -H'Content-Type: application/json' -XOPTIONS 'http://api.fooapp.net/v1/api_session' -d'{"user":{"email":"demo#fooapp.net", "password":"somepassword"}}'
HTTP/1.1 200 OK
Server: nginx/1.2.3
Date: Sun, 02 Sep 2012 11:04:28 GMT
Content-Type: application/octet-stream
Content-Length: 0
Connection: keep-alive
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, OPTIONS
Access-Control-Allow-Headers: DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,X-FooApp-Auth-Token
Access-Control-Max-Age: 1728000
Content-Type: text/plain charset=UTF-8
Content-Length: 0
But a real POST requests for example now fails with a 404:
curl -i -H'Accept: application/json' -H'Content-Type: application/json' -XPOST 'http://api.fooapp.net/v1/api_session' -d'{"user":{"email":"demo#fooapp.net", "password":"somepassword"}}'
HTTP/1.1 404 Not Found
Server: nginx/1.2.3
Date: Sun, 02 Sep 2012 11:06:19 GMT
Content-Type: text/html
Content-Length: 168
Connection: keep-alive
<html>
<head><title>404 Not Found</title></head>
<body bgcolor="white">
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.2.3</center>
</body>
</html>
And it has to, cause the NginX log says:
2012/09/02 13:06:19 [error] 2464#0: *3 open() "/home/deployer/apps/fooapp/current/public/v1/api_session" failed (2: No such file or directory), client: 127.0.0.1, server: localhost, request: "POST /v1/api_session HTTP/1.1", host: "api.fooapp.net"
I am new to NginX, and I know thats a wide open as well as very lightweight configuration. I do not understand why NginX tries to route these requests via public, so that the underlying Rails app is not requested. How do I have to change the configuration, so that all my requests are passed to the app as before, but the CORS headers are added anyway?
Thx in advance
Felix
This comes a little late but since I just ran into the same problem it might help somebody else.
You need to enable passenger inside the location block
location /{
...
passenger_enabled on;
...
}
I hope this helps.

Resources