Serving large static files with Sinatra - ruby

Sinatra can serve files from a static directory with the set :public, 'your_directory' command, but how can I replicate this in a new route?
Importantly, this new route needs to respect byte ranges too! Any ideas? I feel like I should be able to leverage the already present code in the static serve part of sinatra.

I think I can just use send_file (see here) - but if anyone has any other suggestions I have open ears!

Related

purpose of the public directory in a ruby app?

I'm really new to ruby. I just installed phusion passenger and it's working with apache2 on Ubuntu.
I've successfully followed this tutorial:
https://www.phusionpassenger.com/documentation/Users%20guide%20Apache.html#_tutorial_example_writing_and_deploying_a_hello_world_rack_application
What I'm wondering about is what the public directory is for? I tried putting a home.ru which simply had puts "hello world" . When I did that, going to my browser at http://localhost:81/home.ru printed puts "hello world" instead of hello world. Is the public directory meant for server side scripts at all? If so, what am I doing wrong?
Thanks
The public directory is for what we call static files. They are served as-is by the web server without any kind of processing, and are usually cached by the browser.
For example, if you wanted to make a web page without any kind of dynamic content, you could simply drop your HTML and CSS files there and they would be directly accessible, just as your home.ru file was.
Here's documentation for Rack::Static.

PDFkit rails3.1 and development env

My Rails 3.1 app is using PDFkit to render specific pages, and I'm running into (what seems like) a common problem with where trying to generate the pdf is causing the process to hang.
I found this solution here on stackoverflow: rails 3 and PDFkit. Where I add a config.threadsafe! entry in my development.rb file and this works BUT it requires that for every change anywhere in the app I have to stop and restart my server to see my changes. NOT acceptable from a workflow - I'm currently setting up the styling for the PDF pages, and it's painfully slow process having to do this.
I also found the same issue reported here: https://github.com/jdpace/PDFKit/issues/110, and the issue points to this workaround: http://jguimont.com/post/2627758108/pdfkit-and-its-middleware-on-heroku.
ActionController::Base.asset_host = Proc.new { |source, request|
if request.env["REQUEST_PATH"].include? ".pdf"
"file://#{Rails.root.join('public')}"
else
"#{request.protocol}#{request.host_with_port}"
end
}
This removes the need to restart the change, BUT now when I load the pdf it's without the styles rendered from the asset pipeline because it's taking the assets from the public directory. I think I could work with this solution if I could know how to create the stylesheets for the pdf templates in the public folder. IS anyone developing with PDFKit and Rails3.1 where this is all working in sync?
Any help would be greatly appreciated!
Thanks!
Tony
Here is the setup I am using:
I run a second instance of rails server with rails server -p 3001 -e test which will handle my assets for the PDF. The server will print the assets requests as they come in, so I can check that everything works as expected.
I use the following asset_host in my config/environments/development file:
config.action_controller.asset_host = ->(source, request = nil){
"http://localhost:3001" if request && request.env['REQUEST_PATH'].include?(".pdf")
}
If you are using Pow, you can use multiple workers. Add this to your ~/.powconfig
export POW_WORKERS=3
(taken from Pow manual)
There's a problem with pdfkit in Rails 3.1. See my answer to this related question:
pdfkit does not style pdfs

Codeigniter App on EC2 - Helpers not loading

I recently just started to migrate over a CI application to Amazon's EC2 service. To test I set up a micro instance of ubuntu and a LAMP stack. PHP, MySQL, HTTPD are all working beautifully. The one issue i'm having now is that when I run my application I receive an error saying that my helpers won't load. The helpers in particular that aren't loading are the ones in subdirectories in the helpers directory ie: /var/www/system/application/helpers/subdirectory/foo_helper.php
The helpers are being autoloaded and in my autoload.php config file they are written like:
$autoload['helper'] = array('subdirectory/foo', 'foo2',...);
Has anyone run into this issue, or have any pointers on where I could go look in my configuration to resolve this?
Thanks for the help!
I'd try debugging the helper function of the Loader class, in particular these lines :
system/libraries/Loader.php
elseif (file_exists(APPPATH.'helpers/'.$helper.EXT))
{
include_once(APPPATH.'helpers/'.$helper.EXT);
}
This is the code that will be hit when including application helpers. Check what path CodeIgniter is trying to include. Double check that the path exists - everyone makes typos now and again ;-)
I think the issue is that when I moved from Windows to Linux I forgot to take into account that linux is case-sensitive. So now I need to go through and rename my files and folders.
But this still doesn't solve the issue where it seems like the page is being cached and I'm not able to refresh and see my changes. Is there any way to force the page to grab a fresh copy from the server on every refresh?

Camping's URL() doesn't give me "site root" as expected?

Due to circumstances beyond my control, my production Camping site appears at mysite.example.com/mysite. I'm pretty sure this is a common Apache / Passenger configuration issue, and I'm not interested in how to fix it right now because the server is out of my control. Suffice to say, the controller for "/" points there and I can't change that any time soon.
Now, for a long time, this wasn't an issue, because R(MyIndexController) points to the correct place. However, I serve my site's CSS using a Rack::Static call to make $SITE_ROOT/public accessible. This means that the stylesheet is at mysite.example.com/mysite/css/style.css. Here's where the problem comes in: the Camping URL() method, when called in my layout, gives http://mysite.example.com, not http://mysite.example.com/mysite. So I can't get it to point to the /css subdirectory, because it's missing a "hop" in the middle. When I run rackup locally, everything is fine (because this file is at localhost:8080/css/style.css), but on the production server I don't know how to fix it.
My question: is there another method (maybe directly from Rack?) that I should be calling instead? I really want to avoid hardcoding it, and/or having a hack to determine whether I'm running locally (for debug) or in production, for every rendering of the layout.
ETA: OK, this gets stranger. Obviously I've abstracted out some of the actual details above, part of which I think I "over-scrubbed". The "top level" URL is actually more akin to /mysite/rest (the developer-centric HTML presentation of our RESTful interface), as opposed to /mysite/management (accounts) or /mysite/ui (JQuery'd / "nice" UI). These are set up in our config.ru, via run Rack::URLMap.new(Hash['/rest' => RestModule, '/ui' => PrettyInterfaceModule, '/management' => UserManagerModule], etc.
So in answer to the comment below, R(Index), from a view in the RestModule, actually returns /mysite/rest/. As an example, I have a "home" link in the layout, which looks like a :href=>R(Index), and generates code that looks like <a href="/mysite/rest/">. The server is configured to serve files from ./public directly at the "site root", so ./public/css/style.css actually does apppear at http://mysite.example.com/mysite/css/style.css, as noted previously. It's that link that I'm having trouble automatically generating, and it's because of the Rack::URLMap that I thought I may have to rely on a native Rack method (not a Camping abstraction) to locate this resource.
So in this case, URL() actually returns http://mysite.example.com/mysite/rest/?
What about something like this?
URL().merge('../css/style.css')
This is an old question so I assume that you did already find a workaround but the new passenger + apache (or ngnix) behaves correctly for camping as far as I could replicate. Your app would be on the Documents root and all the includes in the /public folder so /public/css should be routed correctly regardless of you using a sub folder /mysite or not as passenger doesn't make a difference (again) as far as I can replicate. Therefore this should be easily solvable with passenger 3 + Apache or ngnix.

Serving Files in Zend Framework MVC

What is the best practice when serving files from the Zend Framework MVC? These files have to be served from the MVC as they are protected.
I know you can read in the file and place it into the Response object but this seems like a bad practice as you would be reading the entire file into memory then serving it. Right now I usually do:
header('Content-type: image/jpeg');
fpassthru(fopen($path, 'rb'));
exit;
But this also doesn't seem right as I'm stopping the execution of the script. Any suggestions?
I see nothing wrong with just exit(); What you will need to be careful of is any output buffering layers you may have on (gzip compression, etc). Large files could blow up those buffers pretty quick, so you'll want to close them out and potentially 'chunk' your output with a fopen/fread loop.
I would suggest building a super-simple script for retrieving files based on ticket system like in CMS you generate ticket to DB - filename, unique-hash and than redirect to the super-simple file-retieving script (file.php?hash=asd52ad3as1g5). It will get the hash from query and based on it fetch the real filename and push that to output as you have written using fpassthru. The hash need to be unique and hard to guess...
You could try using the X-Sendfile header. It is supported by lighttpd and newer versions of apache. Basically the webserver will replace the output of the script with the file you specified. The downside being that it is specific to the configuration of the webserver, so you may be on a host that doesn't support it.

Resources