Use multiple public directories in Sinatra - sinatra

My sinatra application is contained in a gem. This means that the assets (css/js) live in the gem. This application writes on the fly generated images and serves them; currently writing into and serving from the public dir.
I prefer to not write the generated images in the gem dir but to a "cache" dir of some sorts under the web-application implementing this gem.
Gem is installed at /var/www/TE/shared/gems/ruby/1.8/gems/tubemp-0.6.0, so assets are at e.g. /var/www/TE/shared/gems/ruby/1.8/gems/tubemp-0.6.0/lib/public/css/.
Gem is deployed in a simple rack-app at /var/www/TE/current/, so I would prefer to write and serve the thumbnails from /var/www/TE/current/public.
However, the setting for a custom public-dir allows only one dir to be set:
set :public_folder, File.join(Dir.pwd, "public")
Breaks the serving of assets; Dir.pwd being the directory of the Rack app. Public is now the dir under the Rack-app, but that is not where the assets are found: they live under the "public" in the gem.
set :public_folder, File.join(gemdir, "public")
Breaks serving of the generated thumbnails.
I could rewrite the application so it serves either the assets or the thumbnails trough Sinatra, but that seems quite some overhead.
Is that the only way? Or is there a way to give Sinatra two or more public dirs to serve its static items from?

I think there's probably a few options, but here's how I got a little app to serve static files from two places, an extension and the main app's public folder:
Directory layout
root/
app.rb
public/images/foo.jpg
lib/sinatra/
gemapp.rb
gemapp/public/images/bar.jpg
The extension 
# lib/sinatra/gemapp.rb
module Sinatra
module GemApp
def self.registered(app)
app.set :gem_images, File.expand_path( "gemapp/public/images", File.dirname(__FILE__))
app.get "/images/:file" do |file|
send_file File.join( settings.gem_images, file)
end
app.get "/gemapp" do
"running"
end
end
end
register GemApp
end
The main app
require 'sinatra'
require_relative "./lib/sinatra/gemapp.rb"
get "/" do
"home"
end
It served files fine for me.

Related

Sinatra - how to match production urls with the app's urls

Consider the following simple Sinatra application:
require 'sinatra'
post '/user/login' do
# login logic...
end
When deploying the application to a production environment, the url /user/login is usually changed to something else, i.e., /nitro/nutcracker/v1/user/login. And of course, the Sinatra app will not serve this url.
To cut the unwanted prefix, I've considered using a filter (i.e., before block), and routes with regex (i.e., get /*/user/login), but surely there are better solutions?
What say you?
You can mount it with rack. On the production server, create a config.ru file, and put this inside:
require_relative 'my_app.rb'
map('/nitro/nutcracker/v1/') { run Sinatra::Application } # Or your class, if it's modular
This will prefix the entire app with /nitro/nutcracker/v1/.
Then you run the server with rackup, or your application server might have a command line argument to pass a rack config file.

Caching external resources with sw-precache

I'm trying to get sw-precache to pre-cache external CDN resources, but the generated service-worker.js doesn't contain the CDN url's in the precacheConfig array.
This is what I have in my gulpfile:
staticFileGlobs: [
'http://netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.min.css',
'client/assets/**/*.{js,html,css,png,jpg,gif,svg,eot,ttf,woff,ico}'
]
The files inside my local client/assets folder are added to the precacheConfig array, but the external font-awesome css isn't. Is there a way to achieve this?
sw-precache can only precache and keep up to date local assets, like those that match the client/assets/**/*... pattern you're using. It's not meant to work with remote assets that are accessed via CDN.
You have a couple of approaches:
Use npm (or the package manager or your choice) to download a local copy of the resource (i.e. font-awesome) and then deploy that third party resource alongside your first-party assets. If the third-party code is picked up by a pattern you pass to staticFileGlobs then it can be precached and versioned just like anything else local.
Use runtime caching to handle the resource on the CDN. Since the URL for your specific asset includes a 4.0.3 versioning string, it's safe to assume that the underlying contents will never change, and a cacheFirst strategy is probably safe.
You can modify your sw-precache configuration to look like the following:
{
staticFileGlobs: [
'client/assets/**/*.{js,html,css,png,jpg,gif,svg,eot,ttf,woff,ico}'
],
runtimeCaching: [{
urlPattern: /^https:\/\/netdna\.bootstrapcdn\.com\//,
handler: 'cacheFirst'
}],
// ...any other config options...
}
That configuration is broad enough to pick up anything served off that CDN, cache it, and then serve it cache-first once in subsequent visits.
Please note that your example used an http: protocol for your CDN's URL, and you'll need to use https: to obtain a response that plays nicely with service worker caching.

Best file and dir permissions for zend?

What are the best permission settings to folders and files within a Zend application with public pages and pages only accessible after login?
My guess is:
All folders including modules, controllers, models and views: 755 Everyone can read the directory, but its contents can only be changed by the user.
All files: 644 Only the owner has read and write permissions; the group and others can read only.
For a public folder that allows uploading and deleting users private files: 700,
The private file itself 600.
Is this interpretation just?
I am wondering if permissions for the backend of an application after a user is logged in should better be 750 or even 700 for folders and 640 (or 600?) for files, making them inaccessible for the rest of the world?
The web server's user is the one accessing the file system, not the end user. This is normally www-data for Linux systems running Apache. You should therefore base your permissions on that user/group.
The client however should only have read access to the root of the site, which is the /public folder. The public folder will contain the front-end images, js, css and index.php which is Zend's single point of entry.

Pow config.ru for serving static files outside of the public directory?

How do you setup a config.ru file to have Pow serve html/css/js files outside of the public directory? Let's say I wanted to serve them out of the html folder instead.
You could use TryStatic from rack-contrib:
require 'rack/contrib/try_static'
use Rack::TryStatic,
:root => "html",
:urls => %w[/]
You might want to add if ENV['RACK_ENV'] == 'development' if you only want this during development (e.g. if your web server is configured to serve from html/)
.

nestacms and webbynode rapp

I would like to deploy a nestacms blog on webbynode by using the webbynode gem as allways I do with rails. Altough Webbynode seem to support Sinatra and Rack application easily, I get a WARNING during deployment stating that the application will not run smoothly because it lacks a public folder:
WARNING: Missing public folder in your Rack app, it'll not run smoothly!
Actually the rapid application development (RAPP webbynode gem) sets the need of a public folder into the Nginx configuration:
server {
listen 80;
server_name super_duper_blog.webbyapp.com ;
root /var/rapp/super_duper_blog/public/;
passenger_enabled on;
}
Instead this is my nestacms config.ru:
require 'rubygems'
require 'bundler/setup'
Bundler.require(:default)
require 'nesta/app'
Nesta::App.root = ::File.expand_path('.', ::File.dirname(__FILE__))
run Nesta::App
It would be nice if the author and SO user Graham Ashton could jump in and help me. Anyway, how could I get around the problem?
UPDATE
After creating the project, with nesta new you nedd to:
Create a public folder manually
Add some content in it. Say for ex. humnans.txt and favicon.ico
git add . and git commit -m "added public with humans and favicon"
wn push
And your nestacms website will go on line at a private webbynode address (blog.webbyapp.com)
Then you can use wn changedns www.example.com to make your site available for the masses
I've never used webbynode, so I'm not sure quite how its set up. Have you seen the Nginx passenger install guide? Could be useful:
http://modrails.com/documentation/Users%20guide%20Nginx.html#deploying_a_rack_app
It says you need public/ and tmp/, so I'm inclined to believe it.
Did you try making these directories yourself? Does the site actually start up? How are you deploying your site to the webbynode?
All my Sinatra apps are deployed with Vlad (see http://effectif.com/articles/deploying-sinatra-with-vlad) which takes care of creating public/ and tmp/ for you. It also touches tmp/restart.txt (see the Passenger guide I linked to above) when you deploy a new version of the site if you tell it that you're using Passenger. Capistrano also works fine (and is more extensively documented these days).