Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 如何在rails中解析来自Amazon SNS通知的请求正文_Ruby On Rails_Json_Amazon Web Services - Fatal编程技术网

Ruby on rails 如何在rails中解析来自Amazon SNS通知的请求正文

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/

我正在rails 3.0应用程序中设置一个端点,以接收来自Amazon SNS服务的推送通知

Amazon发布的请求有一个JSON负载,但他们将请求的内容类型设置为“text/plain”,这导致Rails无法解析出主体

来自以下地址的post请求示例:

因此,在我的控制器中,我可以使用request对象读取request.body并自己解析它,如下所示:

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内容类型。

此建议没有解决问题/不起作用。问题在于传入请求的
内容类型
。在Rails
request.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"