upload file to box api v2 - ruby

i am trying to upload a file to box.com with their v2 api.
i am able to successfully upload a file with curl, but cannot upload a file from my rails application. i am passing my upload function the correct folder id and file is a tempfile object created by a form upload in my app.
here is the successful curl command
curl https://upload.box.com/api/2.0/files/data -H "Authorization: BoxAuth api_key=API_KEY&auth_token=TOKEN" -F contract=#test.png -F folder_id=387656851 -ssl3
and here is my ruby code
class BoxApi
require 'httmultiparty'
include HTTMultiParty
ssl_version :SSLv3
def initialize
#key = API_KEY
#token = TOKEN
end
def upload_file(folder_id,file,filename,content_type)
File.open(file) do |open_file|
response = self.class.post('https://upload.box.com/2.0/files/data', :query => {
:file => open_file,
:folder_id => folder_id
}, :headers => {'Authorization' => "BoxAuth api_key=#{#key}&auth_token=#{#token}"})
p response
end
end
i get an html page back from box with this text
It appears that your firewall may be blocking Box or you are encountering an error.Please contact your IT administrator to configure your firewall to recognize all sub-domains of .box.com, .box.com and .boxcdn.net. The ports that should be opened for these domains are 80 and 443.If that does not resolve the issue, then please submit a support ticket at https://www.box.com/help.
any ideas why the curl command would be working but not the ruby code?

Despite from being late, this could be useful for people who came across this question.
There is a gem ruby-box to use with Box service at the 2.0 version of their API.

This works properly for me
require 'httmultiparty'
class SomeClient
include HTTMultiParty
base_uri 'https://api.box.com/2.0'
end
response = SomeClient.post('/files/data',
:headers => { 'authorization' => 'BoxAuth api_key={YOUR API KEY}&auth_token={YOUR TOKEN' },
:body => { :folder_id => '0', :somefile => File.new('large.jpeg')}
)
I would try to verify that
You can make non-upload API calls (i.e. GET /folders/0)
If not, check your firewall settings.

Sean already covered this in his answer but I'll highlight it explicitly. We had some issues using the https://upload.box.com URL which is no longer recommended by box. I'd recommend trying the https://api.box.com/2.0 URL and seeing if that it changes your results.
Worst case I'd try capturing my packets using a packet analyzer like wireshark and looking for differences between the two cases.

Related

Add support for rendering views to a rails api only application

I built an api only rails app, but since i'm using a 3rd party email service, I need to be able to render the email template into a string to pass it to the mailing service wrapper gem. So far any attempt to render templates into a string returns an empty string, and i suspect it is because the application is configured to be API only. Ho do I add support to rendering templates into a string?
If this is not the case, please let me know. I'm using postmark mail service. postmark-rails gem, which integrates into standard rails mailers didn't work at all, and plain postmark gem (which uses postmark API instead of postmark SMTP server) works fine, but now my problem is producing the proper html for the email.
this is what I'm trying:
html = render_to_string(
partial: "transfer_mailer/transfer.html.erb",
locals: {
:#body => #body,
:#campaign => #campaign,
:#chat => #chat
}
)
but it returns empty string.
My setup involves Rails 5.0.1, ruby 2.3.1p112 (2016-04-26 revision 54768) [x86_64-linux], Sidekiq 4.2.7, and in production im using nginx/1.10.2 and Phusion Passenger 5.1.1. Production environment is deployed in an azure virtual machine, and I added both inbound and outbound rules for allowing traffic through ports 25, 465, 2525, and 587.
Any help would be really appreciated.
Looking at the docs for render_to_string, it looks like the path doesn't need to include .html.erb, so maybe removing that will fix it.
You can see here for some example code:
In your case, it would be:
render_to_string(
partial: '/transfer_mailer/transfer',
locals: {
:#body => #body,
:#campaign => #campaign,
:#chat => #chat
},
layout: false
)
Also make sure the partial filename starts with an underscore, even though you don't include it with render_to_string or render calls.
There is the other way to use render_to_string for resolving your issue. Please see the code below.
#body = XXX
#campaign = YYY
#chat = ZZZ
html = render_to_string(
file: 'transfer_mailer/transfer.html.erb'
)
Hope it helps.

Intercept WEBrick request

I have a web app that runs on different pieces of hardware, that for the most part consists of smart TVs and set-top boxes.
My web app contains a ruby script to setup the app for local debugging. This script builds my app, listens for file changes, and hosts the app using a simple WEBrick server.
Now I'm running into a problem on a specific piece of hardware. This hardware expects to get a success response from a POST request to a health_check API running on the same host as the web app, before it will load up the web app.
I'm simply hoping to intercept this request and spoof it so that the hardware will load my client. So far I've gotten as far as this:
def start_server
require 'webrick'
root = File.expand_path 'public'
request_callback = Proc.new { |req, res|
if req.path =~ /health_check/
# return 200 response somehow?
end
}
server = WEBrick::HTTPServer.new :Port => 5000, :DocumentRoot => root, :RequestCallback => request_callback
server.start
end
I can modify the response object to set status to 200, but it still ends up returning a 404.
You don't need to "intercept" all requests and check for a specific path. You simply want mount_proc, to handle a specific route with a proc.
Add the following before server.start:
server.mount_proc '/health_check' do |req, res|
res.body = 'what what' # your content here
end
You'll probably want to wrap this in a check to determine if you're running on whatever custom hardware requires this behavior.
See Custom Behavior in the WEBrick docs.

HTTParty with Proxy

I am on heroku trying to access an API that requires my apps ip to be whitelisted. So, I used the heroku add-on proximo to get host/ip for the api's whitelist.
A quick test I set up to test connectivity using HTTParty is failing.
class FakeRequest
include HTTParty
http_proxy 'XX.XXX.XX.XX', 80, 'user', 'pass'
def set_defaults
{:api_key=>"BLARG_BLARG",
:login_name=>"user",
:method => "do_something",
:response_format => "json",
:v => "1.0",
:login_password=>"pass"}
end
def make_post
HTTParty.post "https://test.com", :query => set_defaults
end
end
Going this like:
req = FakeRequest.new
req.make_post
Returns an error message from the api complaining that the source IP is not whitelisted. I looked at the source IP and it is not using the proxy. How can I make HTTParty post using the proxy and not my ISP's IP.
This is the module I built to do just this:
module ProximoParty
PROXIMO = URI.parse(ENV['PROXIMO_URL'])
def self.included(base)
base.send(:include, HTTParty)
base.http_proxy(PROXIMO.host, 80, PROXIMO.user, PROXIMO.password)
end
end
This uses the PROXIMO URL as it is added to your heroku app when you install the addon. So you can drop this file into your app and include ProximoParty into your FakeRequest class instead of HTTParty and it should "just work".
It looks like my code is doing the same thing your code is doing though, so what I'm guessing is that you may not be manually carrying over the credentials properly for proximo.
I ran into a similar problem where it wasn't quite working for me right off the bat. I believe the problem was that I was getting tripped up that there looked to be a "proxy:" protocol in the proximo URL but that was just the username part of the URL.
Anyways, this may or may not help, but please let me know if it does!
It blows my mind how many answers you can get on this question that don't work. Here is how I got it working:
HTTParty::Basement.http_proxy('localhost', 8000, nil, nil)
Put this as a global override in your env.rb file. That's it. Done.
With recent versions of HTTParty it's as simple as using the
http_proxy method:
class Foo
include HTTParty
http_proxy 'http://example.com', 80, 'user', 'pass'
end
HTTParty can use a proxy server address using the following proxy options.
[:+http_proxyaddr+:] Address of proxy server to use
[:+http_proxyport+:] Port of proxy server to use.
[:+http_proxyuser+:] User for proxy server authentication
[:+http_proxypass+:] Password for proxy server authentication.
As you configure HTTParty as an inclusion in your module, you have to call HTTParty method through your class, so:
def make_post
self.class.post "https://test.com", :query => set_defaults
end
I included a link because it include lengthy setup steps. But point taken about the link changing and page becoming invalid. We used squid proxy server on a EC2 AMI and called it a day.
I think you need to call the local httparty, like this:
def make_post
self.post "https://test.com", :query => set_defaults
end

Why does Google's Custom Search API say that I'm missing an access token when using the Ruby client?

I'm trying to use Google's Custom Search API through the Google API Ruby client. I have setup my API key through the Google API console, and have also created my CSE. Based on the documentation, it seems that, as long as I provide an API key (which I am doing), I shouldn't need an OAuth2 authentication token to call the list method. However, when I try to execute the code below, I get the following error:
ArgumentError: Missing access token.
What am I missing? Here's my code:
# create client
client = Google::APIClient.new
# Fetch discovery doc
search = client.discovered_api('custom search')
# Call list method
response = client.execute(
search.cse.list, 'key' => '<my API key>', 'cx' => '<my CSE id>', 'alt' => 'json', 'q' => 'hello world'
)
I believe this is in fact a bug in the client (it's in alpha). After fiddling with it a little more, I've found a workaround:
just after creating the client object, assign it a "dummy" access token:
client.authorization.access_token = '123'
then you can call the search.cse.list method without getting the 'ArgumentError: Missing access token.' error.
If you're just after using Google CSE with ruby, try google-cse. I just built the gem, although I've been using it for a while privately. Much easier to work with than the alpha client
I found out that adding client.retries = 3 to my code solves this problem.
With the current version of the gem (0.7.1), you need to set the authorization to nil in addition to setting the key:
require 'google/api_client'
client = Google::APIClient.new
client.key = ENV['GOOGLE_API_KEY']
client.authorization = nil
client.execute ...

401 error with Ruby OAuth for Twitter

xI've been working for days to get Twitter to authenticate with Ruby, but I'm not having any luck.
My first attempt was something like this:
class TwitterController < ApplicationController
def index
#callback_url = "http://dev.twipler.com:3000/twitter/auth"
#auth= TwitterOAuth::Client.new( :consumer_key => "xxx", :consumer_secret => "xxxxxxxxxxxxxxxxx" )
#rtoken = #auth.request_token :oauth_callback => #callback_url
#token = #rtoken.token
#secret = #rtoken.secret
#link = #rtoken.authorize_url
session['token' ] = #token
session['secret'] = #secret
redirect_to #link
end
def auth
#auth.authorize_from_request(session[:rtoken], session[:rsecret], params[:oauth_verifier])
end
end
And a very similar way but with the Twitter gem, and the same with the OAuth gem directly. No matter what OAuth::Consumer::token_request dies with a 401 error.
So, out of desperation I attempted to git clone Snitter, add my Twitter creds, and try it, but it too dies with a 401.
I've tried using localhost:300/twitter/auth, http://dev.twipler.com:3000/twitter/auth, and a bit.ly for each of the former 2. Nothing works.
Any help?
EDIT: Of course I would forget to do the most logical thing to do and delete my secrets. (They've been changed ;)).
You may want to edit your consumer secret out. With that, anyone can make requests on behalf of your app.
That said, make sure your system time is synced to an ntp server. If your system time has drifted fast or slow, OAuth requests will fail, since their include a timestamp and relatively short TTL. I had this exact problem a while back.
Failing that, you can crack open the oauth gem and turn on HTTP debugging, which will show you the full HTTP transaction including any error message returned.

Resources