Sinatra 2.x版本before过滤器是否变更?升级后全局content_type设置失效
问题根因
- Sinatra 2.0+ 调整了过滤器的执行优先级,当子类挂载到Rails路由时,Rails的路由分发逻辑会先触发Sinatra子类的初始化上下文,父类定义的before过滤器如果没有显式指定作用域,会在部分场景下被Rails默认的响应头设置覆盖。
- Sinatra 1.x中
:json默认直接映射为application/json,但和Rails 5.2共存时,Rails的MIME类型注册逻辑会修改Sinatra的默认符号映射规则,部分场景下:json会被识别为非标准类型,导致content_type设置失效回退为text/html。
解决方案
不需要在每个接口内单独声明content_type,可以用下面两种更稳妥的全局配置方式:
方式一:类级别默认配置(推荐,优先级最高)
直接在父类PmoWebservice中添加类级别默认content_type设置,不需要依赖before过滤器:
class PmoWebservice < Sinatra::Base # 全局默认响应Content-Type,优先级高于自动推断和过滤器设置 set :default_content_type, 'application/json' # 全局默认字符集 set :default_charset, 'utf-8' end
该配置会自动被子类继承,所有接口默认返回application/json; charset=utf-8的响应头。
方式二:修正before过滤器的写法
如果要继续用before过滤器,把符号类型改为明确的字符串,避免和Rails的MIME映射冲突:
class PmoWebservice < Sinatra::Base before do content_type 'application/json', charset: 'utf-8' end end
同时需要确保子类没有定义其他会覆盖响应头的after过滤器或者中间件。
补充验证
如果配置后仍不生效,可以在父类的before过滤器中添加日志排查:
before do puts "Before filter executed, current content_type: #{response['Content-Type']}" content_type 'application/json', charset: 'utf-8' end
确认过滤器是否被子类正常触发,如果没有触发,检查Rails路由中挂载Sinatra子类的代码是否正确,是否添加了额外的中间件修改响应头。
内容的提问来源于stack exchange,提问作者Ed Allen
相关产品推荐
相关产品推荐

