How do i GZIP static resources using zlib? - ruby

Edit: I'm using Ruby with Sinatra.
UPDATE: here is the code I'm using which doesn't work...
get '/' do
session[:time] = Time.now
z = Zlib::Deflate.new(6, 31)
z.deflate(File.read('public/Assets/Styles/build.css'))
z.flush
z.finish
z.close
erb :home
end
...I don't get any errors. But when I check the file via Firebug's Yslow plugin it tells me that file isn't GZIP'ed
I'm trying to understand how I GZIP web page content and static files like JavaScript and CSS using zlib?
I know I can pass a string of data to Zlib::Deflate.deflate but I'm using Sinatra with ERB files. So do I pass in a path to the ERB file and the Js/CSS files? Or can I pass in the directory where scripts/styles are stored? Would I pass in a path to the ERB file or the symbol that references the ERB file?

Unless you are writing your own HTTP server, your server needs to handle this. The client first has to let the server know that it accepts gzip content encoding, and then the server can deliver gzip content encoding.
Zlib::Deflate.deflate will not produce gzip-encoded data. It will only produce zlib-encoded data. You would need to use Zlib::Deflate.new with the windowBits argument equal to 31 to start a gzip stream.

Related

Ruby Sinatra Embed erb Partial External HTML File

I have a need to hold a "Purchase Contract" type of report in my website. I am using Sinatra using erb files to deliver content. I would like to email the current report (the versions will change) out when people sign up for various items.
I'm thinking I can house it in the database, or an external file, in some kind of format, so I can do the both:
import it into an erb file for presentation on the web
use it in an email so it's readable in text format
So basically I need it in a format that's basic as possible, but it has to translate into HTML (erb) and text.
What are my options with the format of this file? And how can I translate that into HTML? I've looked at markdown and it's not very pretty with the gems that I find that translate to text. Seeing that it needs plain text as well as HTML I'm a bit lost as to how to get this done.
File Snippet
Privacy Policy
Updated Feb 20, 2019
Website.com (“Website”) is a private business. In this Privacy Statement the terms “we” and “our” refer to Website. This Privacy Statement explains Website’s practices regarding personal information of our users and visitors to this website (the “Website”), as well as those who have transactions with us through telephone, Internet, faxes and other means of communications.
Website’s Commitment to Privacy
At Website, we are committed to respecting the privacy of our members and our Website visitors. For that reason we have taken, and will continue to take, measures to help protect the privacy of personal information held by us.
This Privacy Statement provides you with details regarding: (1) how and why we collect personal information; (2) what we do with that information; (3) the steps that we take to help ensure that access to that information is secure; (4) how you can access personal information pertaining to you; and (5) who you should contact if you have questions and concerns about our policies or practices.
Solution: Save the file as HTML and use this gem for conversion into text:
https://github.com/soundasleep/html2text_ruby
Works fine if the HTML is simple enough.
Remaining: Still have the issue as using the HTML file as a partial.
Solved:
#text = markdown File.read('views/privacy.md')
So park the source file as a markdown file, which can translate to HTML. When I need the email version, I need to translate to HTML then to text using the HTML2text gem. https://rubygems.org/gems/html2text
As I understand it, you have a portion of text (stored in a database or a file, it doesn't really matter where) and you want to:
serve this up formatted as HTML via a webpage
send it plain via email
Assuming a standard Sinatra project layout where the views directory lives in the project dir, e.g.
project-root/
app.rb
views/
and a route to deliver the text in app.rb:
get "/sometext" do
end
If you put the erb template in the views directory and as the last line of the route make a call to the erb template renderer you should get the output in HTML. e.g.
project-root/
app.rb
views/
sometext.erb # this is the erb template
In the Sinatra app
# app.rb
# I'm assuming you've some way to differentiate
# bits of text, e.g.
get "/sometext/:id" do |id|
#text = DB.sometext.getid id # my fake database call
erb :sometext # <- this will render it, make it the final statement of the block
# make sure #text is in the template
# else use locals, e.g.
# erb :sometext, :locals => { text: #text }
end
Now when a user visits http://example.org/sometext/485995 they will receive HTML. Emailing the text to the user could be triggered via the website or some other method of your choice.

Accept file upload (without a form) in Sinatra

I have this Sinatra::Base code:
class Crush < Sinatra::Base
post '/upload' do
erb params.inspect
end
end
I am using Postman and its interface for uploading a file. So I send a POST request with form-data, where in the body of the request the name is hello and the value is a file test.txt which contains just a simple string hey there.
When I do params.inspect I get this long string
{"------WebKitFormBoundaryocOEEr26iZGSe75n\r\nContent-Disposition: form-data; name"=>"\"hello\"; filename=\"test.txt\"\r\nContent-Type: text/plain\r\n\r\nhey there\r\n------WebKitFormBoundaryocOEEr26iZGSe75n--\r\n"}
So basically a long has with a single key and a single value. Reading most Sinatra tutorials (where the file is accepted from a form), there's a nice way Sinatra handles this using params[:file], but this doesn't seem to be the case when the file is coming straight from the body of an HTTP request.
I tried a non-modular approach too withou Sinatra::Base, thinking it's some parsing middle-ware missing, but got the same result.
Is there something I'm missing here? Must I go and make my own custom parser to get the content of this long hash? Or is there an easier way?
I figured it's Postman issue. When I switch from 'x-www-form-urlencoded' to 'form-data' in Postman, in the Header section, the field: Content-Type => application/x-www-form-urlencoded is NOT removed. So for those who encounter this problem, make sure you remove it manually.

How can I get both header and web page content in a single call?

I’m using Rails 4.2.7. I know how to use openURI to get the headers from a URL …
open(url){|f| pp f.meta }
and I know how to get the contents of the URL
open(url).read
So how can I get both headers and contents in one call, preferably storing headers into one variable and contents into another?
You just have to reuse the result of the open call:
f = open(url)
pp f.meta
pp f.read

Content type of a distant file

I would like to get the content type of a distant file because I have a problem when I download it. The content type is wrong. Here is my code to download a file
url = "http://my_url/my_file.mp4"
file = open(URI::encode(url))
content_type = file.content_type # => text/plain instead of video/mpeg or video/mp4
I tried the following code to get the content_type before but still not working:
url = URI.parse(url)
Net::HTTP.start(url.host, url.port){|http| http.head(url.request_uri)['Content-Type']}
Does anybody have an idea?
Edit
Here is the code I use to find out which content_type it is..
MIME::Types.type_for(URI::encode(url)).map{|type| type.content_type}.join(' ')
# => "application/mp4 audio/mp4 video/mp4 video/vnd.objectvideo"
But here is the result with a video with sound track.. How am I suppose to only pink "video/mp4"? I can't check every file type to see what the result is.. It's endless.
Servers aren't obligated to tell you the correct content type and in many cases they'll get it wrong because it's not normally important. Most browsers provide considerable leeway on what they'll accept and process.
The only way to know for sure is to pull down the file and use a tool like file to examine it. This has a fairly large database of different file formats and ways of identifying them.
The result of your request might be an HTML error message. You won't know until you verify the file's contents.

Reading body stream in Sinatra

I'm trying to upload a file with XHR request using PUT method with Sinatra.
My first idea was to upload the file and writing the stream directly into a MongoDB GridFS
#fs.open("test.iso", "w") do |f|
f.write request.body.read
end
It works, but, it loads the entire file into the RAM and it write it into the MongoDB GridFS.
I'd like to avoid this behavior by writing it continuously to the GridFS (stream the file, not loading it and put it in the GridFS) without loading the entire file into the RAM : because for huge files (like 1GB or more) it's clearly a bad practice (due to RAM consumption).
How can I do that ?
EDIT :
Can I have Sinatra / Rack not read the entire request body into memory? method is creating a TempFile, the thing is I want to only work with streams to optimize memory consumption on server-side.
Like a php://input would do in PHP.
EDIT 2 :
Here is how I'm currently handling it :
HTML/JS part
Ruby/Sinatra part
It looks like the streaming support in Sinatra is only in the opposite direction for long running GET requests out to the client.
If you do a POST multipart upload, Sinatra will write the data to a tempfile and provide you with the details in the params Hash.
require 'sinatra'
require 'fileutils'
post '/upload' do
tempfile = params['file'][:tempfile]
filename = params['file'][:filename]
FileUtils.mv(tempfile.path, "test.iso")
"posted"
end
While in the same sinatra directory:
$ echo "testtest" > /tmp/file_to_upload
$ curl --form "file=#/tmp/file_to_upload" http://localhost:4567/upload
posted
$ cat test.iso
testtest

Resources