rails aws-s3 delete file throws AWS::S3::PermanentRedirect error - EU bucket problem? - ruby-on-rails-3

I'm building a rails3 app on heroku, and I'm using aws-s3 gem to manipulate files stored in an Amazon S3 eu bucket.
When I try to perform a AWS::S3::S3Object.delete filename, 'mybucketname' command, I get the following error:
AWS::S3::PermanentRedirect (The bucket you are attempting to access
must be addressed using the specified endpoint. Please send all future
requests to this endpoint.):
I have added the following to my application.rb file:
AWS::S3::Base.establish_connection!(
:access_key_id => "myAccessKey",
:secret_access_key => "mySecretAccessKey"
)
and the following code to my controller:
def destroy
song = tape.songs.find(params[:id])
AWS::S3::S3Object.delete song.filename, 'mybucket'
song.destroy
respond_to do |format|
format.js { render :nothing => true }
end end
I found a proposed solution somewhere to add AWS_CALLING_FORMAT: SUBDOMAIN to my amazon_s3.yml file, as supposedly, aws-s3 should handle differently eu buckets than us.
However, this did not work, same error is received.
Could you please provide any assistance?
Thank you very much for your help.

the problem is you need to type SUBDOMAIN as uppercase string in config, try this out

You can specify custom endpoint at connection initialization point:
AWS::S3::Base.establish_connection!(
:access_key_id => 'myAccessKey',
:secret_access_key => 'mySecretAccessKey',
:server => 's3-website-us-west-1.amazonaws.com'
)
you can find actual endpoint through the AWS console:
full list of valid options - here https://github.com/marcel/aws-s3/blob/master/lib/aws/s3/connection.rb#L252
VALID_OPTIONS = [:access_key_id, :secret_access_key, :server, :port, :use_ssl, :persistent, :proxy].freeze

My solution is to set the constant to the actual service link at initialization time.
in config/initializers/aws_s3.rb
AWS::S3::DEFAULT_HOST = "s3-ap-northeast-1.amazonaws.com"
AWS::S3::Base.establish_connection!(
:access_key_id => 'access_key_id',
:secret_access_key => 'secret_access_key'
)

Related

Force Swagger UI To Load https path when hosted on Heroku

I have a rails 4 app with a Grape API and Swagger through the gem grape-swagger and grape-swagger-ui gems.
In dev everything works well, I load http://localhost:3000/api/swagger and the swagger header's text input along the top loads the expected url, http://localhost:3000/api/swagger_doc. This points properly to the file it seeks, swagger_doc.json.
I've pushed this app to heroku, which forces https connections. Unfortunately, when loading https://my-app.herokuapp.com/api/swagger the swagger header's text input along the top loads http://my-app.herokuapp.com/api/swagger_doc instead of loading https://my-app.herokuapp.com/api/swagger_doc (http vs https).
I've tried coming at this from the heroku side with things like:
routes.rb
unless Rails.env.development?
get "*path" => redirect("https://my-app.herokuapp.com%{path}"), :constraints => { :protocol => "http://" }
post "*path" => redirect("https://my-app.herokuapp.com%{path}"), :constraints => { :protocol => "http://" }
end
config/environments/production
config.force_ssl = false
config/environments/production
#config.force_ssl = false
And I've come at it with trying to set or manipulate the base_path attribute of add_swagger_documentation.
app/controllers/api/base.rb
base_path: "my-app.herokuapp.com",
app/controllers/api/base.rb
base_path: "http://my-app.herokuapp.com",
app/controllers/api/base.rb
base_path: = lambda do |request|
return "http://my-app.herokuapp.com"
end
app/controllers/api/base.rb
base_path: lambda { |request| "http://#{request.host}:#{request.port}" }
I recently clicked "view raw" on one of my resources and noticed that it was picking up my changes to base_path but that base_path isn't even used to populate the url in the text input in the swagger header. It seems to be generated from a js file. I'm unable to edit it and would happily accept a hack to do so as a solution. Here's that raw output:
https://gist.github.com/johnnygoodman/5fd246765dc5236fb8c4
The line of interest is:
"basePath":"http://localhost:3000/my-app.herokuapp.com"
Which would break the app if it was being populated and used, but it is not. I don't see an option in the grape-swagger gem that I can use to pass in this variable and change the path to https.
In conclusion:
I'd like the swagger text input box to load https://my-app.herokuapp.com/api/swagger_doc when I visit https://my-app.herokuapp.com/api/swagger.
Anyone know a hack to accomplish this on heroku?
I was able to work around this. I suggest:
Do not use + uninstall #gem 'grape-swagger-ui'
Use and install gem 'grape-swagger-rails' and follow the docs here: https://github.com/ruby-grape/grape-swagger-rails

Preventing duplicates when seeding with existing image using Paperclip + Amazon S3

Every time I re-seed my database locally, duplicate images are being created in my Amazon S3 bucket. I think this is happening because I am not seeding correctly, but I don't know the proper way to do it. I've been using the method shown here. I'm using Rails 4, Ruby 2, paperclip 3.5.2, and aws-sdk 1.20.0.
You can see below in my seeds.rb file, I'm trying to set the image to the url of an image that has already been uploaded to the correct folder in my bucket. However, I think using open() here is causing a new, identical file to be saved to the same folder, usually something like http://s3.amazonaws.com/BUCKET_NAME/restaurants/images/1/original/open-uri20131111-22904-xvzitl.?1384211739.
EDIT: so my bucket will have both this file stored as well as http://s3.amazonaws.com/BUCKET_NAME/restaurants/images/1/original/NAME.jpg
Would really appreciate any help!
model
has_attached_file :image,
:styles => { :medium => "300x300>", :thumb => "100x100>" }
seeds.rb
Restaurant.create!( name: ...,
description: ...,
image: open('https://s3.amazonaws.com/<BUCKET NAME>/restaurants/images/1/original/<NAME>.jpg') )
config/initializers/paperclip.rb
Paperclip::Attachment.default_options[:storage] = :s3
Paperclip::Attachment.default_options[:s3_credentials] = {
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
Paperclip::Attachment.default_options[:bucket] = ENV['AWS_BUCKET']
Paperclip::Attachment.default_options[:url] = ":s3_path_url"
Paperclip::Attachment.default_options[:path] = "/:class/:attachment/:id/:style/:basename.:extension"
Paperclip::Attachment.default_options[:default_url] = "https://s3.amazonaws.com/<BUCKET NAME>/images/missing.png"
I'm pretty late to the party on this one but I figure others may still be having the same problem. If you set the attachments on your models to nil before deleting them paperclip will delete them from S3.

How Do You Expire A Memcached Entry On Heroku

I am using action caching on my Rails 3 app on Heroku with the :expires_in option. I've tried calling expire_action, directly in the controller upon update, and within a sweeper. Nothing seems to expire the cache entry properly.
In my controller:
caches_action :embed, :if => Proc.new { |c| c.request.format.js? || c.request.format.rss? }, :expires_in => 5.minutes
In my action:
expire_action :action => :embed, :format => :js
And I've also attempted it in a sweeper, attempting to use the url generator to get the exact key:
expire_action obj_embed_url(#obj.unique_token)
I wonder if it is Heroku using the Varnish cache layer, which you can't expire. (The cache clearly expires after the 5 minutes, because I can see the content update.) It appears that I have the memcached add-on configured correctly (using the Dalli gem; config.cache_store = :dalli_store), and I can see the appropriate environment variables...
$ heroku config |grep MEM
MEMCACHE_PASSWORD => xxxxxxxxxxxxxxxxx
MEMCACHE_SERVERS => xxx.xxx.northscale.net
MEMCACHE_USERNAME => appxxxxxx%40heroku.com
What am I missing here?
finally figured this out.
Heroku's paths must not be matching up with the expire create/expire calls. so if you specify the path in the cache creation, and call that path specifically in the expire, it will work. also i had to use "expire_fragment" instead of "expire_action". here's my code:
in your controller:
caches_action :load, :up, :juice, :fresh, :cache_path => :custom_cache_path.to_proc
def custom_cache_path
path = "#{params[:controller]}/#{params[:action]}"
path += "/#{params[:id]}" if params[:id]
path += "/#{params[:sha]}" if params[:sha]
path
end
in the expiring method:
expire_fragment "serve/up/#{#site.id}"
expire_fragment "serve/fresh/#{#site.secret}"

Error with facebook access token

My problem is on facebook callback url. I am using fbgraph gem on Rails 3.0.
I ask for extended permissions on my tab application. So in the callback I wait code parameter and access_token.
I extract this code from fbgraph official GIT repository.
def authorize
begin
#auth.client.authorization_code = params[:code]
#In access_token line should return me access__token but throw a error message (see below)
access_token = #auth.client.access_token! # => Rack::OAuth2::AccessToken
#facebook_user = FbGraph::User.me(access_token).fetch # => FbGraph::User
#MORE CODE WITHOUT IMPORTANCE
redirect_to :controller => "dashboard", :action => "index"
rescue Exception => e
logger.info(e.message)
end
end
Throw this error message:
Rack::OAuth::Client::Error # => #status = 400, Message => Missing redirect uri
Please I need help quickly. Excuse me and thanks in advance
I'm using the fb_graph gem which is similar. In order to get the access_token you also need to supply the callback URI - this is the fb_graph version:
client.redirect_uri = "http://your.callback.uri"
client.authorization_code = params[:code]
access_token = client.access_token!
Update:
Looking at the fbgraph gem documentation I think you need to replace these two lines:
#auth.client.authorization_code = params[:code]
access_token = #auth.client.access_token!
With this:
access_token = #auth.client.authorization.process_callback(params[:code], :redirect_uri => callback_url)
To be honest I looked at using the fbgraph gem but the documentation was so bad that I switched to fb_graph instead which is similar and actually has some useful examples in the documentation.

Testing authenticated file uploads in merb

This is something that has been driving me mad over the past few days. I have an action which allows authenticated users to upload assets to the site. I know that the controller action is correct as I can run through the process manually however I want to test it using rspec.
I have to use the request helper so I can reuse an authenticated session which is a :given for this set of tests.
it "should allow authenticated file uploads" do
file = File.open(a_valid_file)
mock_file = mock("file")
mock_file.stub!(:path).and_return(file.path)
request( resource(:assets), :method => "POST",
:params => { :file =>
{:tempfile => mock_file, :filename => File.basename(file.path)} }
)
end
If I breakpoint inside the spec it all works nicely, however when I run the spec and try to access the path in the controller action through the debugger I get this:
e file[:tempfile].path
NoMethodError Exception: undefined method `path' for "#[Spec::Mocks::Mock:0x3fda2a4736c0 #name=\"file\"]":String
My guess is that the stub!(:path) is not being set for whatever mock object is making it through the request.
The question is: Am I going about the right way for testing file uploads and if not what is another way?
I was doing it wrong. By using request it was calling to_s on all paramaters, so my mock object was being passed as "#[Spec::Mocks::Mock:0x3fda2a4736c0 #name=\"file\"]". That will teach me to pay more attention to exception output.
Instead I should use multipart_post and stub out the authentication calls in a block.
it "should allow authenticated file uploads" do
file = File.open(a_valid_file)
multipart_post( resource(:assets), :method => "POST",
:params => { :file => file } ) do |controller|
controller.stub!(:ensure_authenticated).and_return(true)
controller.session.stub!(:user).and_return(User.first)
)
end