Sinatra - Accessing request in Rack::ResponseHeaders - ruby

I want to access request in the Rack::ResponseHeaders. I am using Sinatra in my app.
Below is my code:
use Rack::ResponseHeaders do |headers|
# Manipulation of request variables.
# Setting request headers.
end
The question is that in order to manipulate variables in request, I need to have the request variable first.
Please suggest.

First thing is, you need to install the gem rack-contrib via rubygems:
$ gem install rack-contrib
This gem contains contributed rack utilities. Then you need to require this gem in your app:
require 'rack/contrib'
It may be enough to only require the response headers utility (not tested):
require 'rack/contrib/response_headers'
Then you can use this utility to tap into the headers, for example:
use Rack::ResponseHeaders do |headers| # tap into headers
unless headers['cache-control'] # if header not set,
headers['cache-control'] = "public, max-age=1800" # set it to ...
end
end
Let me know whether this is working for you.

Related

Downloading a track from Soundcloud using Ruby SDK

I am trying to download a track from Soundcloud using the ruby sdk (soundcloud 0.2.0 gem) with an app. I have registered the app on soundcloud and the client_secret is correct. I know this because I can see my profile info and tracks using the app.
Now when I try to download a track using the following code
#track = current_user.soundcloud_client.get(params[:track_uri])
data = current_user.soundcloud_client.get(#track.download_url)
File.open("something.mp3","wb"){|f|f.write(data)}
and when I open the file it has nothing in it. I've tried many approaches including the following one,
data = current_user.soundcloud_client.get(#track.download_url)
file = File.read(data)
And this one gives me an error
can't convert nil into String
on line 13 which is in
app/controllers/store_controller.rb:13:in `read'
that is the File.read function.
I have double checked that the track I am trying to download is public and downloadable.
I tried to test the download_url that is being used explicitly by copying it from console and sending a request using Postman and it worked. I am not sure why it is not working with the app when other things are working so well.
What I want to do is to successfully be able to either download or at least get the data which I could store somewhere.
Version details : -
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]
Rails 3.2.18
soundcloud 0.2.0
There are few assumptions that you have to understand before doing this thing.
Not every track on SoundClound can be downloaded! Only tracks that are flagged as downloadable can be downloaded - your code has to consider that option!
Your track URL has to be "resolved" before you get to download_url and after you get download_url you have to use your client_id to get the final download URL.
Tracks can be big, and downlowding them requires time! You should never do tasks like this straight from your Rails app in your controller or model. If the tasks runs longer you always use some background worker or some other kind of background processing "thing" - Sidekiq for example.
Command-line client example
This is example of working client, that you can use to download tracks from SoundClound. Its using official Official SoundCloud API Wrapper for Ruby, assumes that you are using Ruby 1.9.x and its not dependent on Rails in any way.
# We use Bundler to manage our dependencies
require 'bundler/setup'
# We store SC_CLIENT_ID and SC_CLIENT_SECRET in .env
# and dotenv gem loads that for us
require 'dotenv'; Dotenv.load
require 'soundcloud'
require 'open-uri'
# Ruby 1.9.x has a problem with following redirects so we use this
# "monkey-patch" gem to fix that. Not needed in Ruby >= 2.x
require 'open_uri_redirections'
# First there is the authentication part.
client = SoundCloud.new(
client_id: ENV.fetch("SC_CLIENT_ID"),
client_secret: ENV.fetch("SC_CLIENT_SECRET")
)
# Track URL, publicly visible...
track_url = "http://soundcloud.com/forss/flickermood"
# We call SoundCloud API to resolve track url
track = client.get('/resolve', url: track_url)
# If track is not downloadable, abort the process
unless track["downloadable"]
puts "You can't download this track!"
exit 1
end
# We take track id, and we use that to name our local file
track_id = track.id
track_filename = "%s.aif" % track_id.to_s
download_url = "%s?client_id=%s" % [track.download_url, ENV.fetch("SC_CLIENT_ID")]
File.open(track_filename, "wb") do |saved_file|
open(download_url, allow_redirections: :all) do |read_file|
saved_file.write(read_file.read)
end
end
puts "Your track was saved to: #{track_filename}"
Also note that files are in AIFF (Audio Interchange File Format). To convert them to mp3 you do something like this with ffmpeg.
ffmpeg -i 293.aif final-293.mp3

undefined method `configure' for Savon:Module

I'm getting the above error in a gem with this code snippet
Savon.configure do |config|
config.log = false
config.log_level = :error
HTTPI.log = false
end
This code used to pass in past runs on Travis, so I'm not sure why this changed when I altered the Readme.
Part of this confusion comes from my situation--inheriting a gem to maintain--along with this line in the gemspec:
gem.add_dependency 'savon'
There's no version number specified, so the newest run switched over to using Savon 2, which ditched the Savon.configure global behavior. If you're in the same boat as me, changing this line to the last pre-2.0 version of Savon will resolve the issue:
gem.add_dependency 'savon', '~>1.2.0'
Then bundle install and you should be good.
Or you want to upgrade your code. I know I do.
Savon.configure was removed from Savon 2.0 because the "problem was global state". The quickest way to keep the behavior the same in your app would be to define a app-level global hash in the same place. You'd then pass this hash into every Savon.client call you make. For instance:
# Where Savon.configure was called
APP_OPTS = {
# disable request logging, silences HTTPI as well
log: false,
# Don't log Laundry xmls to STDOUT
log_level: :error,
#... etc
}
# Elsewhere
#client = Savon::Client.new(APP_OPTS)
I'd consider this a starting point to migrating to the 2.0 configuration style. Ideally, you should always consider the client-specific 2.0 options available when initializing each Savon client.

Performing an HTTP PATCH using Ruby curb

I'm trying to do an HTTP PATCH using curb. Looking through the code, there doesn't seem to be a method exposed for this. Is there any way to use curb to do a PATCH? If not, what other libraries or methods are there in Ruby to accomplish this?
With curb latest version (v0.8.1) PATCH is supported even though it is not explicitly available within the Curl::Easy interface (see lib/curl/easy.rb).
You can find a shortcut method here:
# see lib/curl.rb
module Curl
# ...
def self.patch(url, params={}, &block)
http :PATCH, url, postalize(params), nil, &block
end
# ...
end
With it you can perform a PATCH request as follow:
curl = Curl.patch("http://www.example.com/baz", {:foo => "bar"})
Under the hood, the PATCH verb is simply passed to the easy interface as follow:
curl = Curl::Easy.new(url)
# `http` is a method implemented within the C extensions of curb
# see `ruby_curl_easy_perform_verb_str`. It allows to set the HTTP
# verb by calling `curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, verb)`
# and perform the request right after
curl.http(:PATCH)

How to get ip address, referer, and user agent in ruby?

I want to log user's ip address, referer, and user agent.
In PHP, I can get them from the following variables:
$_SERVER['REMOTE_ADDR']
$_SERVER['HTTP_REFERER']
$_SERVER['HTTP_USER_AGENT']
How to get them in ruby?
PHP is embedded in a web server. Ruby is a general-purpose language: if you need a web server context, you'll have to install it yourself. Fortunately, it's easy.
One of the easiest ways to get started is with Sinatra. Install the gem:
gem install sinatra
Then create myapp.rb:
require 'sinatra'
get '/' do
request.user_agent
end
Start up the web server:
ruby -rubygems myapp.rb
Visit Sinatra's default URL: http://localhost:4567/
Et voilĂ .
You need the array request.env
request.env['REMOTE_ADDR']:
I'm assuming you by ruby you mean ruby on rails, the following link shows you how to access them:
http://techoctave.com/c7/posts/25-rails-request-environment-variables

Trying to Workout how-to run a Ruby (Sinatra) app on the Ebb webserver

I need to write a super fast Ruby application to process web requests on Sinatra - and want to run it on the Ebb webserver. But I cannot work out how to do this. Could someone please help me?
sinatra has a -s option to specify a handler. try running your app with -s ebb.
You need to look at Rack: http://rack.rubyforge.org/
It's pretty easy really, you have a .ru file which instructs Rack how to start your application, and in your application you have a 'call' method which is called on each request, and sends the response back to Rack.
In my_app.ru
require 'my_app'
require 'ebb'
# Rack config
use Rack::Static, urls: ['/js', '/public', '/index.html']
use Rack::ShowExceptions
# Run application
run MyApp.new
In my_app.rb
class MyApp
def call env
request = Rack::Request.new env
response = Rack::Response.new
params = request.params
response.body = "Hello World"
response['Content-Length'] = response.body.size.to_s
response.finish
end
end
Then you specify the .ru file in your sinatra config, like:
rackup: my_app.ru

Resources