Rails Paperclip returning wrong Cloudfront URL - ruby-on-rails

I'm working on a Rails website that uses Paperclip to upload files to Amazon S3 and then serve them through Cloudfront. I've got the uploading working fine, and Cloudfront is serving the files properly, but for some reason ModelObj.attachment.url isn't working properly on my production server. It works fine on my development server (WEBrick under Windows 8) but is returning the wrong URL on the live site (LAMP with Phusion Passenger). It returns almost the right url, but instead of
http://[stuff].cloudfront.net/kidbooks/snds/5072_original.mp3?1393858446
I'm getting
http:///kidbooks/snds/5072_original.mp3?1393858446
It's configured as follows: In environment.rb:
Paperclip::Attachment.default_options.merge!({
:storage => :s3,
:bucket => APP_CONFIG['s3_bucket'],
:path => "/#{APP_CONFIG['s3_path']}/:attachment/:id_:style.:extension",
:s3_credentials => {
...
}
})
And in the model:
has_attached_file :snd,
:url => ':s3_alias_url',
:s3_host_alias => APP_CONFIG['cloudfront_domain']
APP_CONFIG is being set properly on both servers; I've checked. (Or at least, it's being set properly in the console on the live server; I guess I could check more directly. There doesn't appear to be anything relevant in environments/development.rb or production.rb. What's going wrong here, and how can I fix it?
(I found this question, which is close to what I need, but only involves S3.)
Update: Found something weird. Model.snd.options returns a hash that includes, among other things, :s3_host_alias=>nil. Maybe my model is somehow being loaded before my configuration files?

Aha, found it. For some reason my model is either being loaded before my config files, or the loader doesn't have access to APP_CONFIG. This meant that :s3_host_alias was being set to nil, which of course broke things. I moved :s3_host_alias => APP_CONFIG['cloudfront_domain'] from the model to environment.rb, and now it's working fine.
I have no idea why my model would be loading before my config files, though.

Related

Rails: ckeditor gem not working in production mode with nginx and passenger

I am using the ckeditor WYSIWYG text editor in my rails project. In particular: I am having trouble configuring for image uploads in production mode.
It works fantastic in development mode, and even locally in production mode while using Puma. When I click to Upload a photo and click the Browse Server button. It immediately looks for photos where I expect them to: within /assets/ckeditor_assets/pictures.
The issue is getting it to work in production mode with nginx. When I use nginx in production mode: it returns a 404 Not Found error message. I looked at my server logs and here is what it says:
"/var/www/MYAPP/ckeditor/pictures" failed (2: No such file or directory)
So for some reason it is attempting to find a ckeditor directory within my public directory (because that is a symlink to my public directory). I am not even sure why ckeditor is looking for a ckeditor directory when it should instead be looking within my apps public/assets/ckeditor_assets directory.
I attempted to fix this by creating a ckeditor directory within my public directory, and then putting a pictures directory inside of there. However, when I did that I got a 403 Forbidden error.
I did notice that within the config/initializers/ckeditor.rb file there is this line:
# Customize ckeditor assets path
# By default: nil
#config.asset_path = "http://www.example.com/assets/ckeditor/"
So just to give it a shot I hardcoded where I wanted ckeditor to go and fetch the pictures, but unfortunately that didn't work either.
Any suggestions please let me know. Thanks! I will go ahead and show my ckeditor::picture model file in case that provides any clues:
class Ckeditor::Picture < Ckeditor::Asset
has_attached_file :data,
:url => "/assets/ckeditor_assets/pictures/:id/:style_:basename.:extension",
:path => ":rails_root/public/assets/ckeditor_assets/pictures/:id/:style_:basename.:extension",
:styles => { :content => '800>', :thumb => '118x100#' }
validates_attachment_presence :data
validates_attachment_size :data, :less_than => 2.megabytes
validates_attachment_content_type :data, :content_type => /\Aimage/
def url_content
url(:content)
end
end
A buddy of mine figured it out. It turns out it was simply a configuration required in the nginx.conf file. I'm using nginx and passenger.
ck_editor sends a request to ckeditor/pictures as opposed to MYAPP/ckeditor/pictures. Basically: it ignores the relative path (via passenger) of your app. I just updated the location block regex like so:
# nginx.conf
...
location ~ ^/(RELATIVE_PATH_FOR_APP|ckeditor/pictures)(/.*|$) {
...
}
An alternative is that one might be able to forgo the regex for ckeditor/pictures within the location block by overriding some of the configurations found in the ckeditor config.js file. That way you are specifying the ck_editor routing at the application level as opposed to the server level.

Certificate for this server is invalid with S3 and Paperclip

I'm working in a Rails 5 application which is deployed by the moment on Heroku. I'm using Postgrsql for data storage, Paperclip to manage image uploads and AWS S3 to store all the uploaded images.
To accomplish this I used this very detailed and useful tutorial from Heroku dev which really help me a lot.
I use the same configuration for development env to be able to test it. Actually it works like a charm in dev.
When I deploy to Heroku and after running migrations, setting up ENV variables I create a new Brochure which accepts a cover image; and everything goes good. The images are stored correctly in AWS S3.
But when I render de image in a view I wit just don't work. I got the following errors in browsers console:
Safari browser:
Failed to load resource: The certificate for this server is invalid. You might be connecting to a server that is pretending to be “sponsors.matchxperience.s3.amazonaws.com” which could put your confidential information at risk.
Chrom canary:
Failed to load resource: net::ERR_INSECURE_RESPONSE
I don't know what's the matter because in development environment everything works.
Can anybody help me out with this or any idea what's going on?
production.rb (the same in development.rb)
Rails.application.configure do
# We’ll also need to specify the AWS configuration variables for the production Environment.
config.paperclip_defaults = {
storage: :s3,
# s3_protocol: 'http',
s3_credentials: {
bucket: ENV.fetch('AWS_S3_BUCKET'),
access_key_id: ENV.fetch('AWS_ACCESS_KEY_ID'),
secret_access_key: ENV.fetch('AWS_SECRET_ACCESS_KEY'),
s3_region: ENV.fetch('AWS_REGION')
}
}
end
brochure.rb
class Brochure < ApplicationRecord
# This method associates the attribute ":cover" with a file attachment
has_attached_file :cover, styles: {
card: '500x330#',
}
# Validate the attached image is image/jpg, image/png, etc
validates_attachment_content_type :cover, :content_type => /\Aimage\/.*\Z/
end
paperclip.rb at config/initializers/
Paperclip::Attachment.default_options[:url] = ':s3_domain_url'
Paperclip::Attachment.default_options[:path] = '/:class/:attachment/:id_partition/:style/:filename'
After searching and reading different sources for this error I found many different solutions for similar errors but no one seemed to be related with Rails 5 directly and sincerely I don't even though it has something to see with Ruby or Rails.
I was convinced it was something with the AWS S3 server and I was right, I fixed it. Finally reading the official documentation for creating a new bucket I realized that it was something ridiculously simple.
In the documentation it says we can use periods . and hyphens - in our bucket's name:
Can contain lowercase letters, numbers, periods (.), and hyphens (-).
Must start with a number or letter.
Must be between 3 and 63 characters long.
...
So, I named my bucket as:
sponsors.matchxperience
Which was right written, BUT talking about server's URLs it may confuse the browser's requests to point to a different server and that was happening in my case. That's why I got that error.
The solution
Just create another bucket (or renaming the actual one may function) and copied all the content named as:
sponsors-matchxperience
And magically it just works fine in production on Heroku. I don't know what's going on with the AWS documentation but for me, that whats the error, periods . in my bucket's name.
I hope it could be useful for someone else.

How to use Amazon S3 on Spree-2-2-stable

I need to configure my images on Amazon S3, but when I tried to do so under version 2-2-stable from Spree, I realized that this configuration were moved away from the admin panel.
I read somewhere that this configuration was creating some problems, and thus it was removed on 2-2. But I assume that the functionality is still working somehow.
When I try to add these configs to my config/initialize/spree.rb, I´m getting an error because these preferences are no longer existing.
preference :s3_access_key, :string
preference :s3_bucket, :string
preference :s3_secret, :string
These preferences are found on 2-1-stable but not on 2-2-stable
https://github.com/spree/spree/blob/2-1-stable/core/app/models/spree/app_configuration.rb
https://github.com/spree/spree/blob/2-2-stable/core/app/models/spree/app_configuration.rb
Is there any way how to get it working in order to use it together with Heroku?
Here is Spree's commit with the changes and some instruction as to how to make configuration changes.
https://github.com/spree/spree/commit/b1d6c5e4b9801d888cc76c05116b814945122207
My understanding is that you can still use paperclip to manage uploading to S3, which I have successfully done using their instructions. I have however had problems getting the save path on S3 to configure correctly. This might get you started ... in an environment config file put the following:
# Paperclip configs
config.paperclip_defaults = {
:storage => :s3,
:bucket => ENV['S3_BUCKET_NAME'],
:s3_credentials => {
:access_key_id => ENV['AWS_ACCESS_KEY_ID'],
:secret_access_key => ENV['AWS_SECRET_ACCESS_KEY']
}
}
I use environment variables for the S3 credentials, so yours will most likely be different. This chunk of code has made uploading files to S3 work, like I said I just can't force a specific file path on upload. Hope that helps.
EDIT - ADDITIONAL INFO:
I added the following to the spree.rb initializer to define a custom upload path and a custom url path.
# S3 upload path and url path configuration
Spree::Image.attachment_definitions[:attachment][:path] = 'products/:id/:style/:basename.:extension'
Spree::Image.attachment_definitions[:attachment][:url] = 'products/:id/:style/:basename.:extension'
To change default upload sizes you can override the Spree image decorator model. So under app/models add a spree directory and add a file named image_decorator.rb. You can then control the sizes with the following:
Spree::Image.class_eval do
attachment_definitions[:attachment][:styles] = {
:mini => '48x48>', # thumbs under image
:small => '350x700>', # images on category view
:product => '1024x768>', # full product image
:large => '600x600>' # light box image
}
end
Check out this page for specifics --> http://guides.spreecommerce.com/developer/logic.html
So to sum up, you can do all your general image/S3 configuration by updating your environment initializer, your Spree initializer and overriding the spree image_decorator model.

Paperclip 2.3.5 to 3.3.1 causes url to differ from path

I am in the process of upgrading my rails app from 2.3 to 3.2, and I am having a problem with paperclip. My app was previously using paperclip v2.3.5 and now I am using rails 3.0.20 with paperclip v3.3.1
The problem happens when I try to upload an avatar to S3. It looks like paperclip is escaping the path before sending it to S3, but when I ask for the url of a specific style, the url uses an unescaped version of the path, and this leads to a "NoSuchKey" error from S3 (more like a 404 not found)
In my model I have
Paperclip.interpolates :last_modified do |attachment, style|
attachment.instance.updated_at.to_i
end
:path => "folder/:id/:style.:extension?:last_modified",
:url => ":s3_domain_url",
So the old version of my app was using urls from S3 like:
http://my-bucket.s3.amazonaws.com/folder/123/thumbnail.png?123456789
But now, everytime I upload an avatar, S3 will store the url like this:
http://my-bucket.s3.amazonaws.com/folder/123/thumbnail.png%3F123456789
and asking my model for the url of thumbnail style, will return:
http://my-bucket.s3.amazonaws.com/folder/123/thumbnail.png?123456789
which S3 can't find.
I know it seems to be an easy to fix issue, but my main concern is that the production app has a lot of users with many pictures and updating all of their images is a delicate task, and manually escaping the question mark is not a solution.
I just figured out how to fix a problem that was similar to this. There is a new escape_url option. Maybe try turning that to false?
:path => "folder/:id/:style.:extension?:last_modified",
:url => ":s3_domain_url",
:escape_url => false

Rails 3.2 Paperclip S3 Not Loading in Localhost

I just upgraded to Rails 3.2 and I'm using Amazon S3 with Paperclip to upload photos to my app.
Before my Image Urls would be:
http://s3.amazonaws.com/dealphotos.website.com/photos/428/large/Sandisk120Drive?1334754504
Now my Image Urls on Localhost are:
http://s3.amazonaws.com/dealphotos.website.com/deals/photos/000/000/428/large/Sandisk120Drive?1334754504
Notice the additional 000/000's - even if I take them out and visit the link it says:
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>"Long String of Numbers"</RequestId>
<HostId>
"Gives me a really long string of letters and numbers"
</HostId>
My Deal Model:
has_attached_file :photo, :styles => { :small =>"268x160>", :large =>"350x250>" },
:storage => :s3,
:bucket => 'dealphotos.website.com',
:s3_credentials => {
:access_key_id => ENV['S3_KEY_SPICY'],
:secret_access_key => ENV['S3_SECRET_SPICY']
}
And the images dont show up!
Before all I had to do was pull from Heroku and all my images and files would go to my development. What's going on?
You are most likely using the latest version of Paperclip (version >= 3).
Since this is a major version of paperclip there are documented incompatibilities with older versions of paperclip.
One MAJOR (and in my books good) change is that the default storage location of assets has changed.
Earlier it used to be /system/:attachment/:id/:style/:filename.:extension (from memory). This would be disastrous if you had 2 attachments with the same name (Company logo and Product logo) for example.
Now the new path used by paperclip is /system/:class/:attachment/:id_partition/:style/:filename.:extension
This means all your assets will be stored in the directory specified by above. :id_partitions are used so that the number of nodes (files/directories) in one directory doesnt exceed 1000.
I hope i've been able to explain the reason WHY you are seeing the problem. The default path has changed.
You have 2 options now -
Move old assets into the correct place in the new directory scheme (painful but recommended).
Move new assets into the old directory structure and add a :url + :path option in your attachment definition in the model to continue using the older scheme. (See https://github.com/thoughtbot/paperclip/blob/master/UPGRADING ).
Since it appears that you have images in BOTH the new structure and the old one. So no matter what you decide files will need to be moved from one structure to another. Unless the assets are bookmarked in some way, I suggest you move the older assets into the new directory structure.
Check out CarrierWave gem to file uploads. It works with 3.2 without any problems ;)
http://railscasts.com/episodes/253-carrierwave-file-uploads

Resources