Accessing Raw Post Data

Rails conveniently packages post data in the params hash. The order in which data is stored in a hash is typically not the order in which the data was entered. Generally this is not a problem; however, there are some unusual fact patterns in which it is. One of those fact patterns involves PayPal's Instant Payment Notification in which PayPay expects to receive a copy of the params hash parroted back to them with the elements in the exact order that they were posted.

I am aware that beginning with Ruby 1.9, the elements of a hash are stored in the order that they were entered. However, I don't have the luxury of being that current. Accordingly, it appears that I am going to have to parse the raw post data and enter it into either an ordered hash or an array. My question is, how would I go about doing that?

Thanks for any input.

              ... doug

Try raw_post (http://api.rubyonrails.org/classes/ActionController/AbstractRequest.html#M000471)

Try raw_post (http://api.rubyonrails.org/classes/ActionController/AbstractRequest.h…)

Thanks for the suggestion. What I got to work for me was request.rawpost. That yields a string containing the post data formatted like a get request. I can take it from here. However, my approach would be to use brute force to parse the data in that string. Does anyone have a better methodology? Thanks.

           ... doug

To get an array of ordered keys for the POSTed keys/vals, you could do something like:

  ...   if request.post?     ordered_keys = request.raw_post.split('&').collect {|k_v| CGI::unescape(k_v.split('=').first.to_s) }   ...

and then use those ordered_keys in to access the params vals to accomplish your task that requires such ordering.

Jeff

To get an array of ordered keys for the POSTed keys/vals, you could do something like:

... if request.post? ordered_keys = request.raw_post.split('&').collect {|k_v| CGI::unescape(k_v.split('=').first.to_s) } ...

Thanks. That worked great for parsing the raw post data (and it took me one step closer to final success). The remaining problem is that, no matter how one slices it, I really need to get the data into an ordered hash so that I can use the post_form method of Net::HTTP to return it. Following on with your suggestion, I thought something like this would work:

    ordered_params=ActiveSupport::OrderedHash.new     ordered_keys.each do |key|       ordered_params[key]=params[key]     end

The problem is that the ordered_params hash does not seem to be ordered. Any thoughts on how I am going to get over this hurdle?

Thanks again for all the help.

            ... doug

I'd avoid using Net::HTTP to do anything but the most simple of httpclient work. You'll save a ton of time/effort by using a more full featured httpclient to perform your POST.

There are a lot of ruby httpclient options out there. Which one to use kind of depends on which one you like using that meets your needs. A couple ruby httpclient libs you might want to look at:

http://github.com/nahi/httpclient http://github.com/toland/patron

Personally, these days I end up using curl or wget wrapped in ruby for most of my httpclient work.

Jeff

I'd avoid using Net::HTTP to do anything

Thanks for the input. Your point is well taken.

None-the-less, I'd still like to be able to do this. The problem with my code seems to be in this line:

ordered_params[key]=params[key]

This is an assignment statement to an element of an ordered hash. Thus the left-hand-side is supposed to be representative of an element of an ordered hash. I think the problem is that 'key' is a string. This ordered hash thing doesn't seem to work correctly when the hash index is a string. For whatever reason, it only works correctly when the hash index is a symbol. I think that if I could figure out how to make 'key' a symbol, it would work. The problem is that I have no idea how to do that. But we are straying away from the original topic. Perhaps I should post this issue in a new thread. My original question has been quite well answered.

Thanks again for the input.

           ... doug

$ irb

irb(main):001:0> "foo".to_sym.class => Symbol

irb(main):002:0> :foo.to_s.class => String

Jeff

irb(main):001:0> "foo".to_sym.class => Symbol

irb(main):002:0> :foo.to_s.class => String

VIOLA!!! That seems to be the missing link. Thanks ever so much. :slight_smile:

        ... doug

Doug Jolley wrote:

irb(main):001:0> "foo".to_sym.class => Symbol

irb(main):002:0> :foo.to_s.class => String

VIOLA!!!

Viola: string instrument that I happen to play. Voilà: French for "there it is". :slight_smile:

That seems to be the missing link. Thanks ever so much. :slight_smile:

Great. Now the lecture. Couldn't figure out how turn a String into a Symbol? Instead of posting to the list, your thought process should have been something like this:

I need a method to turn a String into a Symbol. That method deals with an instance of class String. Therefore, it will probably be an instance method on String, or possibly a constructor on Symbol. OK, I'll look in the rdoc for String and Symbol. I'll pay particular attention to the to_* methods, since that's the Ruby convention for type conversion. If I can't find it there, I'll search the Web. If all else fails, I'll ask the list.

That is how to do efficient Ruby research.

        ... doug

Best,

Doug Jolley wrote:

irb(main):001:0> "foo".to_sym.class => Symbol

irb(main):002:0> :foo.to_s.class => String

VIOLA!!! That seems to be the missing link. Thanks ever so much. :slight_smile:

        ... doug

One thing more to consider doug is learning from what you just discovered. I wrote a program that utilizes all of google's api to search anything and everything.

By writing this program which I call GoogleHack, I learned that there's a great hidden codebase within google.

Click this link and bookmark the Code Search. When you discover the answer to some of your questions, particularly around things like this, you can search in-depth for code examples and find some great hidden feedback in the process.

http://www.google.com/codesearch?as_q=:foo.to_s&hl=en&as_lang=ruby&as_license_restrict=i&as_license=&as_package=&as_filename=&as_case=

Click this link and bookmark the Code Search.

That's really handy. Thanks a batch.

         ... doug