我在我的rails3.0应用程序中设置了一个端点,以接收来自AmazonSNS服务的推送通知。
Amazon发布的请求有一个JSON有效负载,但他们将请求的content-type设置为“text/plain”,这导致Rails无法解析正文。
来自Amazon's docs的post请求示例:
POST / HTTP/1.1
x-amz-sns-message-type: Notification
x-amz-sns-message-id: 22b80b92-fdea-4c2c-8f9d-bdfb0c7bf324
x-amz-sns-topic-arn: arn:aws:sns:us-west-2:123456789012:MyTopic
x-amz-sns-subscription-arn: arn:aws:sns:us-west-2:123456789012:MyTopic:c9135db0-26c4-47ec-8998-413945fb5a96
Content-Length: 773
Content-Type: text/plain; charset=UTF-8
Host: myhost.example.com
Connection: Keep-Alive
User-Agent: Amazon Simple Notification Service Agent
{
"Type" : "Notification",
"MessageId" : "22b80b92-fdea-4c2c-8f9d-bdfb0c7bf324",
"TopicArn" : "arn:aws:sns:us-west-2:123456789012:MyTopic",
"Subject" : "My First Message",
"Message" : "Hello world!",
"Timestamp" : "2012-05-02T00:54:06.655Z",
"SignatureVersion" : "1",
"Signature" : "EXAMPLEw6JRNwm1LFQL4ICB0bnXrdB8ClRMTQFGBqwLpGbM78tJ4etTwC5zU7O3tS6tGpey3ejedNdOJ+1fkIp9F2/LmNVKb5aFlYq+9rk9ZiPph5YlLmWsDcyC5T+Sy9/umic5S0UQc2PEtgdpVBahwNOdMW4JPwk0kAJJztnc=",
"SigningCertURL" : "https://sns.us-west-2.amazonaws.com/SimpleNotificationService-f3ecfb7224c7233fe7bb5f59f96de52f.pem",
"UnsubscribeURL" : "https://sns.us-west-2.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-west-2:123456789012:MyTopic:c9135db0-26c4-47ec-8998-413945fb5a96"
}
所以在我的控制器中,我可以使用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的请求(通过User-Agent或那些自定义头),并将内容类型更改为“application/json”,这是一个坏主意吗?(如何做到这一点?)
3条答案
按热度按时间pgccezyw1#
我最近遇到了这个问题。网上提到的大多数方法对我都不起作用,所以我创建了一个中间件。中间件检测消息是否来自SNS(通过查找类型头)并强制content_type为
application/json
。在我的例子中,message参数也是以字符串形式传递的JSON(来自S3桶通知的SNS消息)。这并不能处理这种情况,但可以很容易地进行扩展。
创建中间件后,需要像这样安装它:
这将在解析参数之前插入中间件,这意味着params解析器将看到JSON内容类型。
ahy6op9u2#
在2023年第一季度,Amazon SNS推出了对从主题交付的HTTP消息的自定义
Content-Type
标头的支持。以下是发布帖子:https://aws.amazon.com/about-aws/whats-new/2023/03/amazon-sns-content-type-request-headers-http-s-notifications/您必须修改Amazon SNS订阅的
DeliveryPolicy
属性,将headerContentType
属性设置为application/json
或支持的任何其他值。您可以在此处找到支持的所有值:https://docs.aws.amazon.com/sns/latest/dg/sns-message-delivery-retries.html#creating-delivery-policy您可以通过调用
Subscribe
或SetSubscriptionAttributes
API操作来设置DeliveryPolicy
属性:或者,您也可以使用AWS CloudFormation来设置此策略。
vm0i2vca3#
试试这个https://stackoverflow.com/a/14664355