How to POST binary data using Rest Client? - ruby

I am trying to read in an audio file of type wav or amr from a HTML form using Rest Client. I have the code to do this in PHP.
$filename = $_FILES['f1']['name'];
public function getFile($filename) {
if (file_exists($filename)) {
$file_binary = fread(fopen($filename, "r"), filesize($filename));
return $file_binary;
} else {
throw new Exception("File not found.");
}
}
I need to convert this code to Ruby and I am having trouble doing so as I am a relative novice when it comes to Ruby.

According to RestClient's repo:
def self.post(url, payload, headers={}, &block)
Request.execute(:method => :post, :url => url, :payload => payload, :headers => headers, &block)
end
This snippet of code simply sends a file:
file = File.open('path/to/file.extension', 'r')
RestClient.post("your_url_to_the_endpoint", file)
So I assume all you still need to do is to set the headers:
begin
file = File.open(params[:f1], "rb")
url = "...."
response = RestClient.post url, file, {:Authorization => "Bearer #{#access_token}", :Accept => 'application/json', :Content_Type => 'audio/wav'}
rescue => e
#error = e.message
ensure
return erb :speech
end

Related

Ruby HTTP sending API key Basic_auth

I have been following a tutorial on GitHub Pages and
I am trying to pass an Apikey to a webservice as basic auth 'apiKey' => 'huda7da97hre3rhr1yrh0130409u1u' for example but I cannot work out how to implement it into the method, or even if that is the proper place for it.
I have a class called connection with my request method in it. I need to post 'apiKey' as header and not in the body. I have read the ruby docs but I cannot work out how to apply it to this specific class.
require "net/http"
require "uri"
require "ostruct"
require "json"
class Connection
ENDPOINT = "http://localhost"
APP_LOCATION = "/task_manager/v1/"
VERB_MAP = {
:get => Net::HTTP::Get,
:post => Net::HTTP::Post,
:put => Net::HTTP::Put,
:delete => Net::HTTP::Delete
}
def initialize(endpoint = ENDPOINT)
uri = URI.parse(endpoint)
#http = Net::HTTP.new(uri.host, uri.port)
end
def get(path, params)
request_json :get, path, params
end
def post(path, params)
request_json :post, APP_LOCATION + path, params
end
def put(path, params)
request_json :put, path, params
end
def delete(path, params)
request_json :delete, path, params
end
private
def request_json(method, path, params)
response = request(method, path, params)
body = JSON.parse(response.body)
OpenStruct.new(:code => response.code, :body => body)
rescue JSON::ParserError
response
end
def request(method, path, params = {})
case method
when :get
full_path = encode_path_params(path, params)
request = VERB_MAP[method.to_sym].new(full_path)
else
request = VERB_MAP[method.to_sym].new(path)
request.set_form_data(params)
end
#http.request(request)
end
def encode_path_params(path, params)
encoded = URI.encode_www_form(params)
[path, encoded].join("?")
end
end
If I post to the server using Advanced Rest Client and put the apikey in the
http://localhost/task_manager/v1/tasks?=
header
Authorization: 9c62acdda8fe12507a435345bb9b2338
and in the body
email=free%40mail.com&password=free&task=test
then I get
{
error: false
message: "Task created successfully"
task_id: 5
}
So how can I post it using this class?.
connection = Connection.new
result = connection.post("task", {'task' => 'task'})
Basic Authentication example:
req = Net::HTTP::Get.new(uri)
req.basic_auth 'user', 'pass'
http://docs.ruby-lang.org/en/trunk/Net/HTTP.html#class-Net::HTTP-label-Basic+Authentication
Or if you want to add a raw Authorization header in your request method you can do
request.add_field 'Authorization', 'huda7da97hre3rhr1yrh0130409u1u'
But basic authentication normally means that there is a user name and a password. With your API key - I am not sure you actually need basic authentication. I do not know what you API actually requires but if you have not tried it yet you can try sending the api key as an additional parameter
result = connection.post("register", {'email' => email, 'name' => name, 'password' => password, 'apiKey' => 'huda7da97hre3rhr1yrh0130409u1u' })

RestClient.put error in Ruby

I am trying to do a RestClient.put in Ruby for a highchart graphic but I see that this is not replicated. Also first I have a RestClient.post and works fine but the problem is then with the put. At the end I want to manage an exception because the put returns 302 but I want to manage it as OK. If then of the post I make de put manually with the restclient plugin in the browser works fine, for this I assume that the problem is in the script at the put.
This is the fragment;
date_post = Time.now
date_post = fecha_post.strftime("%Y-%m-%d")
date_unix = Time.now
date_unix = fecha_unix.strftime("%Y-%m-%d")
date_unix = (fecha_unix.to_time.to_i)
date_unix = fecha_unix.to_s + '000'
conversion = 50 #this is a example number
name_metric= "metric_example"
build_header = {:content_type => :json, :accept => :json, :Authorization=> "here_is_auth_id"}
url = "http://example.com/data.json"
params = <<-eos
{
"identifier":"#{name_metric}","date":"#{date_post}","value":[#{date_unix},[#{conversion}]]
}
eos
JSON.parse RestClient.post url, params, build_header
begin
JSON.parse RestClient.put 'http://example', params, {:content_type => :json}
rescue => e
e.response
end
Could you tell me why is not working correctly?
Thanks in advance.

Ruby -> RestClient::Resource -> post -> arguments

I do constructed RestClient wrapper
require 'json'
require 'rest_client'
$url_common_part = 'http://host:port/cgi-bin/cgi_script'
class Grabber
def initialize
#site = RestClient::Resource.new($url_common_part)
end
def post ( path, params )
site_and_path = #site["#{path}"]
payload = params.to_json
puts "\n", payload
response = site_and_path.post (
payload,
headers = {
'MY-HEADER' => 'MY-VALUE',
'content_type' => 'json',
'accept' => 'json'
}
)
return response
end
end
and get works well, but post gives error syntax error, unexpected ',', expecting ')' (SyntaxError)
May anybody suggest what am I doing wrong?
The problem is in your call to post:
response = site_and_path.post (
payload,
headers = {
'MY-HEADER' => 'MY-VALUE',
'content_type' => 'json',
'accept' => 'json'
}
)
You are doing an assignment to headers when the second parameter is a hash (which can include headers):
response = site_and_path.post (
payload,
headers: {
'MY-HEADER' => 'MY-VALUE',
'content_type' => 'json',
'accept' => 'json'
}
)

Rails Ajax -> Sinatra -> Amazon API and back

I'm not sure that I really understand how Sinatra works.
I'd like to get some products from Amazon using their API, in my Rails app. But HTTP requests are blocking the IO. I got the tip to create a Sinatra app and make an Ajax request to there instead.
Ajax: (From my Rails app)
$.ajax({
url: "http://sinatra.mydomain.com",
dataType: "json",
success: function(data) {
console.log(data);
}
});
Sinatra app: (I also make use of the Sinatra-synchrony gem)
require 'sinatra'
require 'sinatra/synchrony'
require 'erb'
require 'rest-client'
require 'amazon_product'
Sinatra::Synchrony.overload_tcpsocket!
get '/' do
req = AmazonProduct["us"]
req.configure do |c|
c.key = "KEY"
c.secret = "SECRET"
c.tag = "TAG"
end
req << { :operation => 'ItemSearch',
:search_index => "DVD",
:response_group => %w{ItemAttributes Images},
:keywords => "nikita",
:sort => "" }
resp = req.get
#item = resp.find('Item').shuffle.first
erb :layout, :locals => { :amazon_product => #item }
end
Layout.erb: (renders fine if I go to this Url in the browser)
<%= amazon_product %>
Problem:
My Ajax response is a 200 OK but with an empty response.
I'm can't figure out what's wrong. Please advise.
It seems that you've faced with ajax 'cross-domain security' problem. Try to use JSONP (JSON with padding).
Change your sinatra get handler:
get '/' do
req = AmazonProduct["us"]
req.configure do |c|
c.key = KEY
c.secret = SECRET
c.tag = TAG
end
req << { :operation => 'ItemSearch',
:search_index => "DVD",
:response_group => %w{ItemAttributes Images},
:keywords => "nikita",
:sort => "" }
resp = req.get
#item = resp.find('Item').shuffle.first
content_type :json
callback = params.delete('callback') # jsonp
json = #item.to_json
if callback
content_type :js
response = "#{callback}(#{json})"
else
content_type :json
response = json
end
response
end
And change your Ajax request:
$.getJSON("http://address_of_sinatra?callback=?",
function(data) {
console.log(data);
});
Or you can add dataType: 'jsonp' to your $.ajax request.
After that you should see data object in js debugger (at least it's working in my case :D )

Can I use rest-client to POST a binary file to HTTP without multipart?

I have tried to do the following, but the web-service is NOT REST and does not take multi-part. What do I do in order to POST the image?
#response = RestClient.post('http://www.postful.com/service/upload',
{:upload => {
:file => File.new("#{#postalcard.postalimage.path}",'rb')
}
},
{"Content-Type" => #postalcard.postalimage.content_type,
"Content-Length" => #postalcard.postalimage.size,
"Authorization" => 'Basic xxxxxx'
} # end headers
) #close arguments to Restclient.post
Got the answer: use I/O to stream as a string instead of using File.new....
:file => IO.read("#{#postalcard.postalimage.path}")

Resources