File upload not working with Rails 4 in development using Pow and Nginx
Asked Answered
I

1

5

I am using Pow and Nginx to serve my Rails 4 app in development. A simple file upload is returning 500 error and the request is not reaching the Rails controller. I assume this is the case because there is no mention of the request in the Rails log. Without any mention of the error, I am not sure what is going wrong here.

I started with an Ajax file upload but replaced it with a simple form which is also not working.

Tried this

Original Upload Button

and then went to this

Simple Upload Form

Current avatar.html.erb

<%= form_for @user, html: { multipart: true }, method: "post", url: '/settings/avatar/update', class: "", id: "update_avatar" do |f| %>
  <%= f.file_field :avatar, class: 'js-upload-photo-button js-change-avatar-btn', accept: 'image/png,image/gif,image/jpeg,image/jpg' %>
    <%= f.submit "Upload" %>
<% end %>

Request headers in Chrome

Full Request Headers

Expanded Request Headers section

Expanded Request Headers section

nginx.log

127.0.0.1 - - [01/Feb/2014:11:28:26 +0530] "POST /settings/avatar/update HTTP/1.1" 500 643 "https://allotrop.dev/settings/avatar" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.77 Safari/537.36"

pow access.log

[Sat Feb 01 2014 11:28:26 GMT+0530 (IST)] INFO [127.0.0.1] GET allotrop.dev /500.html

There are other questions here about Rails returning 500 error with no mention in log rails 500 error no production log entry , Rails 3.2.13, 500 error in development with no log and How to properly diagnose a 500 error (Rails, Passenger, Nginx, Postgres)

But these are one-off errors and do not seem related to the problem I am facing. It would be great if anyone can point me in the right direction.

Update 1

Relevant line from routes.rb

post '/settings/avatar/update', to: 'settings#update_avatar'

Update 2

Found my nginx error log. BTW, if you are using Homebrew, it is at /usr/local/Cellar/nginx/1.4.0/logs/error.log

nginx/error.log

2014/02/01 13:05:54 [crit] 8787#0: *85813 open() "/usr/local/var/run/nginx/client_body_temp/0000000010" failed (13: Permission denied), client: 127.0.0.1, server: *.dev, request: "POST /settings/avatar/update HTTP/1.1", host: "allotrop.dev", referrer: "https://allotrop.dev/settings/avatar"

Indicant answered 1/2, 2014 at 6:34 Comment(2)
Can you check with method: 'PATCH' in your form? If it doesn't will be good if you can update your routes file here.Selfloading
Using Patch is not helping. I have added the relevant route in the question.Indicant
I
23

The problem is not with Rails but with Nginx which is pretty evident from the nginx error.log. This question helped me understand what I was dealing with - Rails 3 + carrierwave + nginx = permission denied.

Nginx uses the client_body_temp_path directive to specify the location where it will temporarily store the uploaded files from the user request. Homebrew had set it by default to /usr/local/var/run/nginx. This folder also contains fastcgi_temp, proxy_temp, scgi_temp and uwsgi_temp for me. Nginx worker processes run with user nobody and they were not able to access these folders. I chowned all these folders to the nobody user, but that did not help.

Finally, I did

client_body_temp_path /tmp/nginx/; inside the HTTP module of my nginx.conf to make it work.

Doing a ls -l shows

drwx------ 2 nobody wheel 68 Feb 1 14:44 nginx

I am not sure why this worked inside /tmp and not inside the original /var/run/nginx. I belive I will face similar issue when I use other temp folders or in production. Will update this thread if and when that happens.

I recommend symlinking the other relevant logs like the nginx access and error log, pow access and app log to the /log directory of your Rails app. It helps in looking up errors in one of these when you face a tricky bug.

Indicant answered 1/2, 2014 at 9:34 Comment(5)
Thank you @movingahead, adding client_body_temp_path /tmp/nginx/; solved my issue as well :-)Ilanailangilang
Adding client_body_temp_path /tmp/nginx/; worked for me too!! this should be marked as the right answer.Gustation
Setting client_body_temp_path to anything under /tmp turned out to be unreliable because OS X would sometimes clean out these directories. I went back to investigate why the original defaults set up during install (under /usr/local/var/run/nginx) weren't working and found that nginx needs execute permissions to be set on all ancestor directories (source: nginxlibrary.com/403-forbidden-error). In my case, chmod o+x /usr/local/var fixed the issue without needing to change nginx.conf.Mistymisunderstand
Had completely same issue, even chmodding the /usr/local/var/run/nginx folders did not resolve permission issue, but client_body_temp_path /tmp/nginx/; did anwer. Thanks!Gilmore
Totally saved me here! Thanks!!Danica

© 2022 - 2024 — McMap. All rights reserved.