]> source.dussan.org Git - redmine.git/commitdiff
File upload fails when run with uWSGI (#35715).
authorGo MAEDA <maeda@farend.jp>
Sat, 14 Aug 2021 01:38:26 +0000 (01:38 +0000)
committerGo MAEDA <maeda@farend.jp>
Sat, 14 Aug 2021 01:38:26 +0000 (01:38 +0000)
Contributed by Pavel Rosický and Holger Just.

git-svn-id: http://svn.redmine.org/redmine/trunk@21173 e93f8b46-1217-0410-a6f0-8f06a7374b81

app/controllers/attachments_controller.rb
test/integration/api_test/attachments_test.rb

index 8e28194a302f9bdb4c37d26f4587eaceba7e5d02..91cd7ce413339c6e5b3aaf81456fe784e77521ad 100644 (file)
@@ -105,7 +105,7 @@ class AttachmentsController < ApplicationController
       return
     end
 
-    @attachment = Attachment.new(:file => request.body)
+    @attachment = Attachment.new(:file => raw_request_body)
     @attachment.author = User.current
     @attachment.filename = params[:filename].presence || Redmine::Utils.random_hex(16)
     @attachment.content_type = params[:content_type].presence
@@ -303,4 +303,14 @@ class AttachmentsController < ApplicationController
   def update_all_params
     params.permit(:attachments => [:filename, :description]).require(:attachments)
   end
+
+  # Get an IO-like object for the request body which is usable to create a new
+  # attachment. We try to avoid having to read the whole body into memory.
+  def raw_request_body
+    if request.body.respond_to?(:size)
+      request.body
+    else
+      request.raw_post
+    end
+  end
 end
index 538649950f7544f28e65608709b6b45d175ab28d..1589e3f72d22ad4bb1850ff5f7775725b279aa4c 100644 (file)
@@ -272,4 +272,29 @@ class Redmine::ApiTest::AttachmentsTest < Redmine::ApiTest::Base
     assert_equal 12, attachment.filesize
     assert File.exist? attachment.diskfile
   end
+
+  test "POST /uploads.json should be compatible with a uwsgi's input" do
+    set_tmp_attachments_directory
+    assert_difference 'Attachment.count' do
+      request_body = Rack::RewindableInput.new(StringIO.new('File content'))
+      # Uwsgi_IO object does not have size method
+      request_body.instance_eval('undef :size', __FILE__, __LINE__)
+      post(
+        '/uploads.json',
+        :headers => {
+          "CONTENT_TYPE" => 'application/octet-stream',
+          "CONTENT_LENGTH" => '12',
+          "rack.input" => request_body
+        }.merge(credentials('jsmith'))
+      )
+      assert_response :created
+    end
+    json = ActiveSupport::JSON.decode(response.body)
+    assert_kind_of Hash, json['upload']
+    token = json['upload']['token']
+    assert token.present?
+    assert attachment = Attachment.find_by_token(token)
+    assert_equal 12, attachment.filesize
+    assert File.exist? attachment.diskfile
+  end
 end