Ruby on rails 如何在rails中解析来自Amazon SNS通知的请求正文
我正在rails 3.0应用程序中设置一个端点,以接收来自Amazon SNS服务的推送通知 Amazon发布的请求有一个JSON负载,但他们将请求的内容类型设置为“text/plain”,这导致Rails无法解析出主体 来自以下地址的post请求示例: 因此,在我的控制器中,我可以使用request对象读取request.body并自己解析它,如下所示:Ruby on rails 如何在rails中解析来自Amazon SNS通知的请求正文,ruby-on-rails,json,amazon-web-services,Ruby On Rails,Json,Amazon Web Services,我正在rails 3.0应用程序中设置一个端点,以接收来自Amazon SNS服务的推送通知 Amazon发布的请求有一个JSON负载,但他们将请求的内容类型设置为“text/plain”,这导致Rails无法解析出主体 来自以下地址的post请求示例: 因此,在我的控制器中,我可以使用request对象读取request.body并自己解析它,如下所示: def receive_notification if request.content_type =~ /text\/plain/
def receive_notification
if request.content_type =~ /text\/plain/
body = request.body.read.force_encoding("UTF-8")
params.merge(JSON.parse(body))
request.body.rewind
end
# ... go on with rest of controller stuff
end
有人有更好的方法吗?我们可以把它移回到链的上游,这样我的控制器就不用担心请求对象了吗?编写一个中间件,在参数解析之前运行并识别来自Amazon的请求(通过用户代理或那些自定义头),然后将内容类型更改为“application/json”,这是一个坏主意吗?(你是怎么做到的?也许试试这个
我最近遇到了这个问题。web上提到的大多数方法对我都不起作用,所以我创建了一个中间件。中间件检测消息是否来自SNS(通过查找类型头),并强制内容类型为
application/json
在我的例子中,message参数也是作为字符串传递的JSON(来自S3 bucket通知的SNS消息)。这并不能处理这种情况,但可以很容易地进行扩展
# app/middleware/sns_content_type.rb
class SnsContentType
def initialize(app, message = "Response Time")
@app = app
end
def call(env)
env['CONTENT_TYPE'] = 'application/json' if env['HTTP_X_AMZ_SNS_MESSAGE_TYPE'].present?
@app.call(env)
end
end
创建中间件后,需要按如下方式安装:
# config/application.rb
config.middleware.insert_before ActionDispatch::ParamsParser, "SnsContentType"
这将在解析参数之前插入中间件,这意味着params解析器将看到JSON内容类型。此建议没有解决问题/不起作用。问题在于传入请求的
内容类型
。在Railsrequest.format
中,是关于传出响应的内容类型。是否无法在控制器(甚至每个操作)的基础上实现这一点?首先,将更改本地化到需要的地方。同时,还要保留堆栈中的另一个中间件。与许多不需要的请求相比,很少有请求需要这一点。我在控制器级别尝试这样做的问题是,您需要在rails解析请求之前放置这段代码,以便让它解释json。如果你想把事情完全保存在控制器中,你必须使用类似于JSON.parse(request.raw)
的东西,然后自己做事情。
# app/middleware/sns_content_type.rb
class SnsContentType
def initialize(app, message = "Response Time")
@app = app
end
def call(env)
env['CONTENT_TYPE'] = 'application/json' if env['HTTP_X_AMZ_SNS_MESSAGE_TYPE'].present?
@app.call(env)
end
end
# config/application.rb
config.middleware.insert_before ActionDispatch::ParamsParser, "SnsContentType"