gpt4 book ai didi

ruby-on-rails - Rack rack.input 变量被截断了吗?

转载 作者:数据小太阳 更新时间:2023-10-29 06:56:40 28 4
gpt4 key购买 nike

我写了一段 Rack Middleware 来自动解压缩压缩的请求体。代码似乎工作正常,但是当我将它插入我的 Rails 应用程序时,我从 ActionController::ParamsParser 收到失败的“无效 JSON”。

作为调试机制,我将压缩内容和解压缩内容写入一个文件(以确保代码正常工作)并且我确实收到了我的原始 JSON 文档(在客户端将其压缩之前) .

我发布的数据 JSON 数据,解压缩的内容被检测为来自 http://jsonlint.com 的有效 JSON .

知道我做错了什么吗?

class CompressedRequests
def initialize(app)
@app = app
end

def call(env)
input = env['rack.input'].read

#output the zipped data we received
File.open('/Users/ben/Desktop/data.gz', 'w+') do |f|
f.write input
end

if env['REQUEST_METHOD'] =~ /(POST|PUT)/
if env.keys.include? 'HTTP_CONTENT_ENCODING'
new_input = decode(input, env['HTTP_CONTENT_ENCODING'])
env['rack.input'] = StringIO.new(new_input)

#output our decoded data (for debugging)
File.open('/Users/ben/Desktop/data.txt', 'w+') do |f|
f.write env['rack.input'].read
end

env.delete('HTTP_CONTENT_ENCODING')
end
end

env['rack.input'].rewind
status, headers, response = @app.call(env)
return [status, headers, response]
end

def decode(input, content_encoding)
if content_encoding == 'gzip'
Zlib::GzipReader.new(input).read
elsif content_encoding == 'deflate'
Zlib::Inflate.new.inflate new input
else
input
end
end
end

这是我从控制台得到的错误:

Contents::"2010-05-17T12:46:30Z","background":false},{"longitude":-95.38620785000001,"latitude":29.62815358333334,"estimated_speed":14.04305,"timestamp":"2010-05-17T12:46:36Z","background":false},{"longitude":-95.3862767,"latitude":29.62926725,"estimated_speed":39.87791,"timestamp":"2010-05-17T12:46:42Z","background":false},{"longitude":-95.38655023333334,"latitude":29.63051011666666,"estimated_speed":46.09239,"timestamp":"2010-05-17T12:46:49Z","background":false},{"longitude":-95.38676226666666,"latitude":29.63158775,"estimated_speed":47.34936,"timestamp":"2010-05-17T12:46:55Z","background":false},{"longitude":-95.38675346666666,"latitude":29.63219841666666,"estimated_speed":22.54016,"timestamp":"2010-05-17T12:47:03Z","background":false},{"longitude":-95.38675491666666,"latitude":29.63265714999999,"estimated_speed":14.03642,"timestamp":"2010-05-17T12:47:10Z","background":false},{"longitude":-95.38677551666666,"latitude":29.63358661666667,"estimated_speed":29.29489,"timestamp":"2010-05-17T12:47:17Z","background":false},{"longitude":-95.38679026666662,"latitude":29.63466445,"estimated_speed":38.34926,"timestamp":"2010-05-17T12:47:24Z","background":false},{"longitude":-95.38681656666668,"latitude":29.63590941666666,"estimated_speed":44.82093,"timestamp":"2010-05-17T12:47:31Z","background":false},{"longitude":-95.38683366666667,"latitude":29.63679638333334,"estimated_speed":40.21729,"timestamp":"2010-05-17T12:47:37Z","background":false},{"longitude":-95.38685133333333,"latitude":29.63815714999999,"estimated_speed":44.86543,"timestamp":"2010-05-17T12:47:44Z","background":false},{"longitude":-95.3868655
/!\ FAILSAFE /!\ Mon Oct 18 18:18:43 -0500 2010
Status: 500 Internal Server Error
Invalid JSON string
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.5/lib/active_support/json/backends/yaml.rb:14:in `decode'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.5/lib/active_support/json/decoding.rb:11:in `__send__'
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.5/lib/active_support/json/decoding.rb:11:in `decode'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.5/lib/action_controller/params_parser.rb:42:in `parse_formatted_parameters'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.5/lib/action_controller/params_parser.rb:11:in `call'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.5/lib/action_controller/session/cookie_store.rb:93:in `call'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.5/lib/action_controller/failsafe.rb:26:in `call'
/Users/ben/projects/safecell/safecellweb/lib/compressed_requests.rb:36:in `call'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `call'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `synchronize'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/lock.rb:11:in `call'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.5/lib/action_controller/dispatcher.rb:114:in `call'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.5/lib/action_controller/reloader.rb:34:in `run'
/Library/Ruby/Gems/1.8/gems/actionpack-2.3.5/lib/action_controller/dispatcher.rb:108:in `call'
/Library/Ruby/Gems/1.8/gems/rails-2.3.5/lib/rails/rack/static.rb:31:in `call'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:46:in `call'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:40:in `each'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/urlmap.rb:40:in `call'
/Library/Ruby/Gems/1.8/gems/rails-2.3.5/lib/rails/rack/log_tailer.rb:17:in `call'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/content_length.rb:13:in `call'
/Library/Ruby/Gems/1.8/gems/rack-1.0.1/lib/rack/handler/webrick.rb:50:in `service'

最后一条信息,我在 ActionController::Failsafe 之后插入这个中间件。

编辑:看起来这不是截断问题

经过更多挖掘,看起来它毕竟不是截断问题。日志只是对输出进行了剪辑,因此它看起来像是一个截断问题。

在这一点上,我不确定为什么 JSON 无效。我需要手动转义吗?

最佳答案

无论如何我都不是 ruby 专家。我也没有尝试重现这个问题来验证我的结果。但是在深入研究了 Rack 和 Action 包代码之后,我可能会有一些东西。

“rack.input”的文档指出:“输入流是一个类似 IO 的对象,其中包含原始 HTTP POST 数据。”

看来您使用的是正确的。

但是,actionpack 会尝试从正文中解析出 JSON(如果内容类型指定为 JSON)并像这样检索正文:

when :json
body = request.raw_post

其中“request”是actionpack自己的Request类,“raw_post”是这样定义的:

def raw_post
unless @env.include? 'RAW_POST_DATA'
@env['RAW_POST_DATA'] = body.read(@env['CONTENT_LENGTH'].to_i)
body.rewind if body.respond_to?(:rewind)
end
@env['RAW_POST_DATA']
end

和“Request.body”是:

def body
if raw_post = @env['RAW_POST_DATA']
raw_post.force_encoding(Encoding::BINARY) if raw_post.respond_to?(:force_encoding)
StringIO.new(raw_post)
else
@env['rack.input']
end
end

这一切看起来都很好(尽管很难弄清楚谁先缓存了值:))。看起来问题在于如何读取帖子数据:

@env['RAW_POST_DATA'] = body.read(@env['CONTENT_LENGTH'].to_i)

所以我猜问题是,由于您更改了“rack.input”但没有更新“CONTENT_LENGTH”,actionpack 正在截断数据,因为显然压缩内容比解压缩内容短。

尝试更新您的中间件代码中的“CONTENT_LENGTH”,看看是否能解决问题。

关于ruby-on-rails - Rack rack.input 变量被截断了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3964293/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com