I am trying to upload some pictures from my controller to my bucket on an Amazon S3. I am using the ruby Volt framework. I need CORS in order to do this, so I am using rack-cors. I have declared it correctly in my initializers/boot.rb file. This code was taken directly from the README.
Volt.current_app.middleware.use Rack::Cors do
allow do
origins '*'
resource '*', :headers => :any, :methods => [:get, :post, :options]
end
end
Unfortunately, it does not work correctly. When I try to post a picture to my S3, I get the following error:
XMLHttpRequest cannot load https://s3.amazonaws.com/bucket-name/uploads.
No 'Access-Control-Allow-Origin' header is present on the requested resource.
Origin 'http://localhost:3000' is therefore not allowed access.
The response had HTTP status code 403.
Any idea as to what might be causing this?
Related
I have a Phoenix app, that should serve its static assets (fonts, mainly) to both www.domain.com and subdomain.domain.com.
The app is hosted on heroku.
How can I set up CORS headers?
I found this library, but it doesn't seems to work on static assets (I think).
I tried to configure it like this:
defmodule MyApp.CORS do
use Corsica.Router
resource "/fonts/*", origins: ["http://subdomain.domain.com"]
end
but the resulting headers are:
cache-control:public
content-length:839
content-type:image/svg+xml
date:Sun, 19 Jun 2016 09:40:01 GMT
etag:3AAE04D
server:Cowboy
You can use the optional :headers option to Plug.Static and set the Access-Control-Allow-Origin header to *.
In lib/my_app/endpoint.ex, add the following argument at the end of the plug Plug.Static call:
headers: %{"Access-Control-Allow-Origin" => "*"}
Your code should look something like:
plug Plug.Static,
at: "/", from: :my_app, gzip: false,
only: ~w(css fonts images js favicon.ico robots.txt),
headers: %{"Access-Control-Allow-Origin" => "*"}
Note that this will not work if you want to allow more than 1 domain to work (a single domain or * would work), as I believe you have to dynamically calculate the value based on the request's Origin header for that, while Plug.Static only allows adding a static list of headers.
I am trying to use HTTParty in irb to test an API call, but I keep getting a 401. Attempts to do a get against the same URL with the same header info using the Postman Chrome add-on work fine -- any ideas?
irb> HTTParty.get("https://developer.fingercheck.com/api/v1/Employees/GetAllEmployees",
:headers => {"APIKEY" => "ABCD1234-1234-ABCD-EFGH-ABCD1234ABCD123",
"ClientSecretKey" => "ABCD1234-1234-ABCD-EFGH-ABCD1234ABCD123",
"Content-Type" => "application/json"})
=> <HTTParty::Response:0x8 parsed_response=nil, #response=#<Net::HTTPUnauthorized 401 Unauthorized readbody=true>,
#headers={"cache-control"=>["no-cache"], "pragma"=>["no-cache"],
"expires"=>["-1"], "server"=>["Microsoft-IIS/7.5"], "x-aspnet-version"=>["4.0.30319"],
"x-powered-by"=>["ASP.NET"], "date"=>["Mon, 01 Dec 2014 21:04:32 GMT"],
"connection"=>["close"], "content-length"=>["0"]}>
I have also tried to do the get call with :query=>..., :query => {:header..., and :basic_auth =>..., but none change the results. Any ideas?
I know a fair number of HTTParty questions have been asked and answered, but I didn't see anything that spoke to this particular issue.
The documentation I know of for the API is at http://developer.fingercheck.com/api/help
The error turned out to be a problem with the API, not with the code -- our headers were being read as 'Apikey' and 'Clientsecretkey' and therefore failing some equality on their side. A fix was pushed to production by them, code now functional.
Add 'Accept' => 'application/json' to your request headers.
I'm trying to get an access token from Google API in my Ruby on Rails app, as part of an overall goal of setting up a raketask. I am able to get an Auth Code fine, but when I make a post request to get an access token, I am getting a 302 error. I'll describe my current code first, and afterward list how I've tried to solve the problem so far.
Current code:
#users_controller
def auth_access
client = Signet::OAuth2::Client.new(
:authorization_uri => 'https://accounts.google.com/o/oauth2/auth',
:token_endpoint_uri => 'https://accounts.google.com/o/oauth2/token',
:client_id => ENV['OAUTH_CLIENT_ID'],
:client_secret => ENV['OAUTH_CLIENT_SECRET'],
:scope => 'https://www.googleapis.com/auth/analytics.readonly',
:redirect_uri => 'http://localhost:3000/google/auth_callback'
)
redirect_to client.authorization_uri.to_s
end
This part works fine so far. It redirects to the consent page, and when the user agrees it then redirects them to the page with the auth code in the url parameters. Next I take that auth code and try to make a POST request to API for an access token:
#users_controller
def auth_callback
http = Net::HTTP.new('accounts.google.com')
path = '/o/oauth2/token'
data = "code=#{params['code']}&client_id=#{ENV['OAUTH_CLIENT_ID']}&client_secret=#{ENV['OAUTH_CLIENT_SECRET']}&redirect_uri=http://localhost:3000/auth_final&grant_type=authorization_code"
response = http.post(path, data)
end
This when I run into a problem. The Google API returns a 302, and includes a message saying something akin to "we moved to 'https://accounts.google.com/o/oauth2/token'".
Here's how I've tried to fix the problem so far:
I assumed that the problem was that the http.post method is making a call to an http and not https.
I've tried including
http.use_ssl = true
http.ssl_version = :SSLv3
This returns the error "SSL_connect returned=1 errno=0 state=SSLv3 read server hello A: wrong version number".
I can take a guess at what this means, but I am still unsure of what the actual problem is and how to solve it. Googling the error message has not been a help.
In a similar vein, I tried using gems to make the https call for me, in particular HTTParty and Typheous, although I was not able to make any progress with them (and am still not even sure that it's an http/https problem).
I've tried using the Signet-Rails gem. This was the most productive method by far, making a successful API call and returning the information. However, it either wasn't saving the refresh token or I cannot find where it is being saved. As I need access to that token to run the rake tasks, I gave up on Signet-Rails.
I tried using Legato, and was constantly running into various problems. Overall, Legato left me with the impression that it did not integrate getting the auth code, consent and tokens into the app, instead requiring the developer to set those up in advance outside of the app's scope. I want to be able to set up the auth code as part of the app. If I am understanding Legato properly, then it is not the gem I need.
I've also tried other various odds and ends but to no avail. The above solutions were the tactics I kept coming back to. Primarily I'm looking for an answer to what is going wrong in my code, and what is the best avenue to fix it (and if I was going down the right track with any of my attempted solutions above, which one?)
Thanks for taking the time to read this and answer!
(on a complete sidenote, those last three list items should be 2, 3, 4, but the stackoverflow text editor thinks it knows better than me...)
Specify the port:
http = Net::HTTP.new('accounts.google.com', 443)
Source: SSL Error on HTTP POST (Unknown Protocol)
I have a CorsController whose job it is to respond crossdomain ajax headers (if the Origin is allows) whenever my application receives an OPTIONS request. But because I don't know exactly where that OPTIONS request will land, I have a catchall route at the top of my routes file set to catch any OPTIONS request to any path.
map.cors '*path',
:controller => 'cors',
:action => 'index',
:conditions => { :method => :options }
For actual OPTIONS requests, this works great. The problem comes in when the app should be serving a 404 Not Found.
Now what happens when I load /no/404/for/you (a path that my application does not handle a route for), I no longer get a 404. Instead this route get's activated and I get a 405 Method Not Allowed. This is causing our logs to be filled with errors that aren't really errors, and monitoring (like New Relic) to send out panic emails about error rates, when in reality everything is just fine.
It appears to see that the path matches, but the :conditions does not, and raises an exception. What interesting is that it appears the route handling is a 2 pass process. This cors route, at the top of my routes file, only triggers if there is an OPTIONS request (good) or if no other route declare after it matches and there is no static file at that path (bad).
Question:
How can I get this catch-all route to hit my controller for all OPTIONS requests, without it also intercepting and throwing errors about otherwise unmatched routes via GET, POST, PUT and DELETE?
And I need to do this, sadly, in Rails 2.x.
So you say
This cors route, at the top of my routes file, only triggers if there is an OPTIONS request (good) or if no other route declare after it matches and there is no static file at that path (bad).
You could add a route at the very end of your routes.rb that would match everything else and just return 404.
As your said it is kind of hacky but I don't see any other way to complete your catchall route at the top. Maybe someone will come up with something else.
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.