Могу ли я попросить Sinatra / Rack не читать все тело запроса в память?


Скажем, у меня есть маршрут Синатры Ала:

put '/data' do
  request.body.read
  # ...
end

Оказывается, что весь запрос.тело считывается в память. Есть ли способ потреблять тело, когда оно входит в систему, вместо того, чтобы предварительно буферизировать его в Rack/Sinatra?

Я вижу, что могу сделать это, чтобы прочитать тело по частям, но все тело все еще кажется прочитанным в памяти заранее.
put '/data' do
  while request.body.read(1024) != nil 
    # ...
  end
  # ...
end
1 3

1 ответ:

Вы не можете избежать этого в целом, не исправляя Sinatra и/или Rack. Это делается Rack::Request, Когда request.POST называется Ли Синатрой создавать params.

Но вы можете поместить промежуточное программное обеспечение перед Синатрой, чтобы удалить тело:
require 'sinatra'
require 'stringio'

use Rack::Config do |env|
  if env['PATH_INFO'] == '/data' and env['REQUEST_METHOD'] == 'PUT'
    env['rack.input'], env['data.input'] = StringIO.new, env['rack.input']
  end
end

put '/data' do
  while request.env['data.input'].body.read(1024) != nil 
    # ...
  end
  # ...
end