Ruby Rack Heroku : Unable to access multiple URLs - ruby

I have followed the Heroku guide on deploying static files using Ruby Rack (https://devcenter.heroku.com/articles/static-sites-ruby),
However I am unable to access any HTML file in \public apart from index.html (every URL resolves to the home page)
The config.ru file :
use Rack::Static,
:urls => ["/bootstrap", "/css", "/fonts", "/images", "/js", "/font-awesome"],
:root => "public"
run lambda { |env|
[
200,
{
'Content-Type' => 'text/html',
'Cache-Control' => 'public, max-age=86400'
},
File.open('public/index.html', File::RDONLY)
]
}
I have checked the following posts :
Ruby Rack Heroku: Serving Static Files
How to setup URLs for static site with Ruby Rack on Heroku
Still I am unable to go beyond the index.html page.
While I change the config.ru as shown below ... I get application error
use Rack::Static,
:urls => ["/bootstrap", "/css", "/fonts", "/images", "/js", "/font-awesome"],
:root => "public"
map "/" do
run lambda { |env|
[
200,
{
'Content-Type' => 'text/html',
'Cache-Control' => 'public, max-age=86400'
},
File.open('public/index.html', File::RDONLY)
]
}
end
map "/about" do
run lambda { |env|
[
200,
{
'Content-Type' => 'text/html',
'Cache-Control' => 'public, max-age=86400'
},
File.open('public/about/index.html', File::RDONLY)
]
}
end
Is there a way to map multiple URLs? I have 5-6 pages in my index.html, but unable to access.
Thanks for your help.

You could create a simple controller that just renders these pages. May be easier than trying to bypass the MVC. Let me know if you need help with this :)
Update -----
Example
Controller:
class PublicController < ApplicationController
def index
render "public/index"
end
def about
render "public/about/index"
end
end
Then place your html files in the views folder in the sub-directories specified in the controller.
Also don't forget to add these methods to your routes.rb file in the config directory.

Related

Rack::Builder and Rack::TryStatic doesn't work

I have a Middleman app which I am serving using Rack::TryStatic.
Here is the config.ru.
use Rack::TryStatic,
root: 'build',
urls: %w[/],
try: ['.html', 'index.html', '/index.html']
run lambda{ |env|
four_oh_four_page = File.expand_path("../build/404.html", __FILE__)
[ 404, { 'Content-Type' => 'text/html'}, [ File.read(four_oh_four_page) ]]
}
My understanding is that when you use a config.ru with run, map or use
methods, they are converted to a Rack::Builder object.
I've tried wrapping this config in a Rack::Builder object like this:
app = Rack::Builder.new do
use Rack::TryStatic,
root: 'build',
urls: %w[/],
try: ['.html', 'index.html', '/index.html']
run lambda{ |env|
four_oh_four_page = File.expand_path("../build/404.html", __FILE__)
[ 404, { 'Content-Type' => 'text/html'}, [ File.read(four_oh_four_page) ]]
}
end
run app
When I do this, I get the 404 page for all requests.
Why doesn't this work?
It looks like there is a bug in the current released version of TryStatic that has been fixed in master, where the try array is being lost when used in way that causes the middleware to be reinitialized.
You can avoid this by making sure the app only get s initialized once by using to_app:
run app.to_app
or equivalently use app instead of new:
app = Rack::Builder.app do
# ...

Static site set up with Rake gem. How do you add New Relic's yml file correctly?

I currently have a static website that deploys to Heroku via a Rack app. Here is what my rack file looks like :
use Rack::Static,
:urls => ["/images", "/javascript", "/css", "/favicon.ico"],
:root => "public"
run lambda { |env|
[
200,
{
'Content-Type' => 'text/html',
'Cache-Control' => 'public, max-age=86400'
},
File.open('public/index.html', File::RDONLY)
]
}
I downloaded a config file from New Relic's site, but now I need to implement New Relic. Does anyone know what I need to change in my Rack file from the yml file?
You could try just including the the yml file in the root path of your project.
New Relic is not setup to handle static applications at this point.

How to enable gzip compression for static Rack sites on Heroku Cedar?

Following the Creating Static Sites in Ruby with Rack article, I get a static site on Heroku with a config.ru that looks like this:
use Rack::Static,
:urls => ["/images", "/js", "/css"],
:root => "public"
run lambda { |env|
[
200,
{
'Content-Type' => 'text/html',
'Cache-Control' => 'public, max-age=86400'
},
File.open('public/index.html', File::RDONLY)
]
}
When I run YSlow over the result, it reported none of the files were gzipped. What do I do to compress both the assets and the public/index.html?
From my previous experience with Sprockets, Sinatra, and the Rack::Deflater, I was pretty sure I was just another use Rack::Deflater line away from what I wanted.
I changed the config.ru to this:
use Rack::Static,
:urls => ["/images", "/js", "/css"],
:root => "public"
use Rack::Deflater
run lambda # ...same as in the question
and I was able to verify that responses were sent gzipped:
$ curl -H 'Accept-Encoding: gzip' http://localhost:9292 | file -
/dev/stdin: gzip compressed data
but not for static assets under /css, /js, or /images:
$ curl -H 'Accept-Encoding: gzip' http://localhost:9292/css/bootstrap.min.css | file -
/dev/stdin: ASCII English text, with very long lines
And that's when I realized this was a standard middleware stack—Rack::Static intercepts the call to static files and thus skips the following stack! That's why it worked for public/index.html but not for assets.
The following config.ru worked (note that use Rack::Deflater now precedes use Rack::Static):
use Rack::Deflater
use Rack::Static,
:urls => ["/images", "/js", "/css"],
:root => "public"
run lambda { |env|
[
200,
{
'Content-Type' => 'text/html',
'Cache-Control' => 'public, max-age=86400'
},
File.open('public/index.html', File::RDONLY)
]
}
Verified with:
$ curl -H 'Accept-Encoding: gzip' http://localhost:9292/css/bootstrap.min.css | file -
/dev/stdin: gzip compressed data, from Unix

Serve files using Rack TryStatic directly?

I'm using Middleman to create a static site.
Middleman generates static html files into ./build directory.
Here's the config I'm currently using:
require 'rubygems'
require 'middleman'
require 'rack/contrib/try_static'
use Rack::TryStatic, :root => "build", :urls => %w[/], :try => ['.html']
run Middleman::Application.server
So Middleman is serving the static files right now. How can I make Rack::TryStatic handle the requests directly?
I tried to make it something like
run Rack::TryStatic, :root => "build", :urls => %w[/], :try => ['.html']
But it doesn't work is run only accepts 1 argument. And Rack::TryStatic requires 2 arguments, app and options to initialize, and I don't have any app.
How can I do this?
(And if it matters, I'm deploying to Heroku)
As you’ve noticed, a Rack middleware component such as Rack::TryStatic needs another app to pass requests onto. You could create a simple one to use that for example just returned a 404 response, such as:
app = lambda {|env| [404, {'Content-type' => 'text/plain'}, ['Not found']
run Rack::TryStatic.new app, :root => "build", :urls => %w[/], :try => ['.html']
or equivalently:
use Rack::TryStatic, :root => "build", :urls => %w[/], :try => ['.html']
run lambda {|env| [404, {'Content-type' => 'text/plain'}, ['Not found']]}
If you have your own 404 file, you could use rack-contrib’s Rack::NotFound instead of a custom end point of your own:
use Rack::TryStatic, :root => "build", :urls => %w[/], :try => ['.html']
run Rack::NotFound.new('path/to/your/404.html')
If you weren’t using the :try array of file extensions to try and serve, you could use Rack::File directly. Internally, Rack::TryStatic uses Rack::Static, which in turn uses Rack::File. Unlike TryStatic and Static, Rack::File is a Rack application in its own right, and so doesn’t need a separate app to pass requests to. Your config.ru would then simply be:
run Rack::File.new './build'
although this wouldn’t allow for “bare” requests to be served with the corresponding .html file — all requests would need to specify the whole file name.

Rack throwing an error when trying to serve a static file

use Rack::Static, :urls => ['/stylesheets', '/images'], :root => 'public'
run proc { |env| [200, { 'Content-Type' => 'text/html', 'Cache-Control' => 'public, max-age=86400' }, File.open('public/index.html')] }
I get private method `open' called for Rack::File:Class when I rackup. Really can't see where the problem is. Running rack 1.1. Help please...
There is a Rack::File class, which has precedence in your rackup file because of the way Ruby looks up names. This is not the class you are looking for, you want Ruby's own File class. That class can be referenced directly without lookup ambiguity by using the prefix ::
::File.open('public/index.html')

Resources