Thanks a lot for the help Ben :) On Nov 4, 4:07 am, Ben Hoskings <[email protected]> wrote: > Yeah, it doesn't work without nginx. > > (I babushka up nginx and friends in production, and I use the same deps on my > MacBook to build my dev stack. But at the moment I'm running things with pow, > since I'm not working on an app with any X-Accel-Redirect downloads.) > > You could just test that the correct headers are being set - testing nginx's > config is outside the scope of your app's suite, and I think if you automate > the process of adding the nginx config on production, then you don't need to > worry about testing the whole path. IMO YMMV IANAL and so on. > > (That's part of the point of babushka: e.g. the nginx vhost deps verify the > config is the one you think it is.) > > - Ben > > On 04/11/2011, at 9:35 AM, markbrown4 wrote: > > > > > > > > > Thanks Ben, > > > One more question, How does this work in a dev environment without > > unicorn / nginx ? > > I'm just running the default "rails s" WEBrick server on dev. > > > I'm guessing the answer will be "dev & production should run an > > identical stack" so you can test / debug these things before deploy. > > > Cheers, > > > On Nov 4, 9:22 am, Ben Hoskings <[email protected]> wrote: > >> You should move the files outside of the public/ directory, into something > >> like data/ or assets/ at the top level of your app, and serve them through > >> authenticated requests with nginx. > > >> The way it works is that instead of rails sending the data itself, it adds > >> a header to the response containing the filesystem path to the file. The > >> header is one that nginx recognises, and it inserts the file data into the > >> response. > > >> This is far better than serving the file with rails because serving static > >> content is what nginx is built to do, extremely fast; doing it with rails > >> is really inefficient because you have to load the contents of the file > >> into ruby land. It's slow and your rails process' resident size will > >> balloon. When nginx serves the content, however, it streams the file from > >> disk in the fastest way possible on your OS, using a fixed amount of > >> memory no matter how large the file is. > > >> You serve them from an internal location in nginx. This is a location that > >> isn't accessible publicly, but that nginx will serve from if asked to by > >> the upstream. Add something like this to your vhost config (replace > >> /assets with the path within your app (outside public/) that you chose for > >> the images): > > >> location /assets { > >> internal; > >> root /srv/http/your.app/current; # don't include public/ > > >> } > > >> Then, to serve a file within the action on one of your routes, you just > >> set the right headers for nginx, and render an empty response: > > >> def photo > >> # The model and paths are totally made up cause I haven't seen your > >> app :) > >> photo = Photo.find(params[:id]) > >> x_accel_redirect "/assets/photos/#{photo.id}/#{photo.style}.jpg", > >> :disposition => 'attachment', > >> :filename => photo.filename, > >> :type => photo.content_type > >> end > > >> private > > >> # Maybe put this private method in application_controller or > >> # in a module if you want to use it in a few different places. > >> def x_accel_redirect path, opts > >> send_file_headers!({ > >> :disposition => 'attachment' > >> }.merge(opts)) > >> response.headers['X-Accel-Redirect'] = path > >> render :nothing => true > >> end > > >> There's a way to do this by instructing rails to, using > >> "config.action_dispatch.x_sendfile_header", but I can't remember it > >> offhand. I prefer to just explicitly set the headers anyway, it's easy and > >> there are no shenanigans that way. > > >> - Ben > > >> On 03/11/2011, at 10:28 PM, markbrown4 wrote: > > >>> Yes, the routes were setup so photo's & documents are only accessible > >>> to logged in users. > >>> The files are in a /private/ directory. > > >>> I'm new to nginx and rails so I need to take baby steps through this > >>> one. > >>> If I delete the routes how else can I authenticate and serve the > >>> images with the headers? > > >>> Here's the current config > >>> -- > >>> server_name <%= var :domain %> <%= var :extra_domains, :default => '' > >>> %> <%= var :www_aliases %>; > >>> root <%= var(:app_root) / 'public' %>; > > >>> if ($host !~ ^<%= var(:domain).gsub('.', '\.') %>$) { > >>> rewrite ^(.*)$ http://<%= var(:domain) %>$1 permanent; > >>> } > > >>> location ~* \.(js|css|jpe?g|png|gif|ico|eot|woff|ttf|swf)$ { > >>> if ($request_uri ~ "\?[0-9]+$") { > >>> expires max; # cache timestamped assets forever... > >>> break; > >>> } > >>> if ($request_uri !~ "\?[0-9]+$") { > >>> expires 1d; # ...and others for 1 day > >>> break; > >>> } > >>> } > > >>> error_page 503 /system/maintenance.html; > >>> location /system/maintenance.html { return 503; } > > >>> try_files /system/maintenance.html $uri/index.html $uri.html $uri > >>> @app; > > >>> location @app { > >>> proxy_pass http://<%= upstream_name %>; > >>> proxy_redirect off; > > >>> proxy_buffer_size 64k; > >>> proxy_buffers 32 16k; > >>> client_max_body_size 128m; > > >>> proxy_set_header Host $host; > >>> proxy_set_header X-Real-IP $remote_addr; > >>> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; > >>> } > >>> -- > > >>> Here's an example of the current action. > > >>> class ResourceController < ActionController::Base > > >>> def resume > >>> head(:not_found) and return if (user = > >>> Person.find_by_id(params[:id])).nil? > >>> head(:forbidden) and return unless user.downloadable? > >>> (current_person) > > >>> path = user.resume.path(params[:style]) > > >>> if File.exist? path > >>> send_file(path, :type => user.resume.content_type) > >>> end > >>> end > > >>> end > > >>> -- > > >>> Thanks, > > >>> On Nov 3, 5:48 pm, Ben Hoskings <[email protected]> wrote: > >>>> Do you need to serve those assets through the stack? Serving them with > >>>> nginx will be orders of magnitude more efficient (i.e. webscale). > > >>>> Anything that would otherwise 404 will be passed to your app. If nginx > >>>> is serving them then they're present on disk, so I'd delete the routes > >>>> and let nginx take care of it :) > > >>>> If you want authentication in front of those routes, then you should > >>>> move them outside public/, and use the 'X-Accel-Redirect' header to > >>>> serve them with nginx on authenticated requests. > > >>>> - Ben > > >>>> On 03/11/2011, at 11:02 AM, markbrown4 wrote: > > >>>>> Hi, > > >>>>> We have routes setup for downloading images / documents > > >>>>> get 'photo/:id/:style.:format', :controller => 'resource', :action > >>>>> => 'photo' > >>>>> get 'photos/thumb/missing.png', :controller => 'resource', :action > >>>>> => 'photo_missing' > >>>>> get 'resume/:id/:style.:format', :controller => 'resource', :action > >>>>> => 'resume' > >>>>> get 'file/:id/:style.:format', :controller => 'resource', :action > >>>>> => 'file' > > >>>>> Nginx config is skipping the routing though. > > >>>>> Do I need to prevent all images from being served directly to resolve > >>>>> it or is there a better way? > >>>>> location ~* \.(js|css|jpe?g|png|gif|ico|eot|woff|ttf|swf)$ > > >>>>> Thanks, > > >>>>> -- > >>>>> You received this message because you are subscribed to the Google > >>>>> Groups "Ruby or Rails Oceania" group. > >>>>> To post to this group, send email to [email protected]. > >>>>> To unsubscribe from this group, send email to > >>>>> [email protected]. > >>>>> For more options, visit this group > >>>>> athttp://groups.google.com/group/rails-oceania?hl=en. > > >>> -- > >>> You received this message because you are subscribed to the Google Groups > >>> "Ruby or Rails Oceania" group. > >>> To post to this group, send email to [email protected]. > >>> To unsubscribe from this group, send email to > >>> [email protected]. > >>> For more options, visit this group > >>> athttp://groups.google.com/group/rails-oceania?hl=en. > > > -- > > You received this message because you are subscribed to the Google Groups > > "Ruby or Rails Oceania" group. > > To post to this group, send email to [email protected]. > > To unsubscribe from this group, send email to > > [email protected]. > > For more options, visit this group > > athttp://groups.google.com/group/rails-oceania?hl=en.
-- You received this message because you are subscribed to the Google Groups "Ruby or Rails Oceania" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/rails-oceania?hl=en.
