Как использовать Rack::RewindableInput::Middleware в приложении Sinatra Ruby?

Это код, который работает отлично:

require 'sinatra'
post '/foo' do
  "Equals to #{params[:a]}!"
end

Если я отправлю запрос POST, он вернет все в порядке:

$ ruby foo.rb -p 8888
$ curl -X POST -H 'Content-Length: 5' --data 'a=444' http://localhost:8888/foo
Equals to 444!

Затем я модифицирую код, добавляя Rack::RewindableInput::Middleware, потому что это необходимо для другого случая, где rewind был доступен в более ранних версиях Rack:

require 'sinatra'
use Rack::RewindableInput::Middleware
post '/foo' do
  "Equals to #{params[:a]}!"
end

Я получаю это:

$ ruby foo.rb -p 8888
$ curl -X POST -H 'Content-Length: 5' --data 'a=444' http://localhost:8888/foo
Equals to !

Что я делаю не так?

Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
1
0
112
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Похоже, это взаимодействие между промежуточным программным обеспечением RewindableInput и промежуточным программным обеспечением MethodOverride, которое Синатра добавляет по умолчанию.

Sinatra добавляет любое промежуточное программное обеспечение, которое вы указываете с помощью use, после своего собственного промежуточного программного обеспечения по умолчанию, поэтому входящие запросы сначала видят MethodOverride, а затем RewindableInput.

MethodOverride будет анализировать входные данные (таким образом, потребляя IO), если тип контента указывает, что это данные формы, ища параметр _method. Он помещает все данные в хэш объекта запроса env, чтобы их можно было использовать позже.

RewindableInput заменяет объект ввода копией с возможностью перемотки, но ввод теперь пуст.

Это не будет проблемой, поскольку данные формы уже были преобразованы в хеш, но Rack повторно использует этот хеш только в том случае, если базовый объект ввода-вывода тот же. Поскольку ввод теперь пуст, его повторный анализ не дает данных.

Обходной путь — поменять порядок этих двух частей промежуточного программного обеспечения. Используйте disable :method_override, чтобы Синатра не добавлял его сам по себе, а затем добавьте его после RewindableInput (в качестве альтернативы вы можете просто отключить MethodOverride, если вы его не используете):

disable :method_override

use Rack::RewindableInput::Middleware
use Rack::MethodOverride

Это работает. Кстати, использование RewindableInput в нашем приложении требуется только при запуске сервера с rackup. Начиная с puma, приложение использует объект Puma::NullIO в качестве тела ответа, который по-прежнему отвечает на rewind.

d_rail 11.06.2024 04:25

Другие вопросы по теме