title: How to parse request body from Amazon SNS Notification in rails
body: <p>I'm setting up an endpoint in my rails 3.0 app to receive pushed notifications from an Amazon SNS service. </p>
  
  <p>The request that is posted by Amazon has a JSON payload, but they set content-type on the request as "text/plain", which results in Rails not parsing out the body. </p>
  
  <p>Example post request from <a href="http://docs.aws.amazon.com/sns/latest/dg/json-formats.html" rel="nofollow">Amazon's docs</a>:</p>
  
  <pre><code>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&amp;SubscriptionArn=arn:aws:sns:us-west-2:123456789012:MyTopic:c9135db0-26c4-47ec-8998-413945fb5a96"
  }
  </code></pre>
  
  <p>So in my controller I can use the request object and read request.body and parse it out myself, like so:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Anyone got a better way to do this? Can we move it back up the chain so my controller isn't worrying about the request object? Is it a bad idea to write a middleware that runs before the parameter parsing and recognizes that a request is from Amazon (by User-Agent, or those custom headers), and changes the content type to "application/json"? (And how do you do that?)</p>