1

I'm simply trying to POST a JSON content-type http request from one Rails server to another. Putting a % character in a value string in the JSON is causing the Rack::QueryParser::InvalidParameterError on the receiving server.

On Server A, I use the httparty gem to perform a POST request w/ a JSON body

obj = {"key":"<%= @results %>"}
resp = HTTParty.post('https://test-url.com/data',
:body => obj.to_json,
:options => { :headers => { 'Content-Type' => 'application/json', 'Accept' => 'application/json' } })

On Server B, I just parse the JSON from the request body

req_body = request.body.read()
req_body_json = JSON.parse req_body
# do work with json

This process works fine unless the obj = {"key":"<%= @results %>"} contains % chars, in which case this occurs on server B:

Started POST "/data" for 10.244.1.3 at 2018-01-02 19:27:04 +0000
F, [2018-01-02T19:27:04.245275 #1] FATAL -- :
F, [2018-01-02T19:27:04.245331 #1] FATAL -- : Rack::QueryParser::InvalidParameterError (invalid %-encoding ({"key":"\u003c%)):
F, [2018-01-02T19:27:04.245358 #1] FATAL -- :
F, [2018-01-02T19:27:04.245397 #1] FATAL -- : rack (2.0.3) lib/rack/query_parser.rb:72:in `rescue in parse_nested_query'
rack (2.0.3) lib/rack/query_parser.rb:60:in `parse_nested_query'
rack (2.0.3) lib/rack/request.rb:468:in `parse_query'
rack (2.0.3) lib/rack/request.rb:343:in `POST'
actionpack (5.1.4) lib/action_dispatch/http/request.rb:362:in `block (2 levels) in POST'
actionpack (5.1.4) lib/action_dispatch/http/parameters.rb:107:in `block in parse_formatted_parameters'
actionpack (5.1.4) lib/action_dispatch/http/parameters.rb:107:in `fetch'
actionpack (5.1.4) lib/action_dispatch/http/parameters.rb:107:in `parse_formatted_parameters'
actionpack (5.1.4) lib/action_dispatch/http/request.rb:361:in `block in POST'
rack (2.0.3) lib/rack/request.rb:57:in `fetch'
rack (2.0.3) lib/rack/request.rb:57:in `fetch_header'
actionpack (5.1.4) lib/action_dispatch/http/request.rb:360:in `POST'
...

When I change obj = {"key":"<%= @results %>"} to obj = {"key":"<= @results>"} the exception does not occur.

As far I know % is a valid in JSON, what am I missing here?

choey
  • 53
  • 10
  • `"<%= @results %>"` is an `erb` construct. Are you intending string interpolation? I assume (perhaps incorrectly) that this is not happening in a view. In which case it would be more like `"#{ @results }"` – jvillian Jan 02 '18 at 19:51
  • Oops I should have been more clear about that. Yes, I'm in fact trying to send code that would normally exist in a view .html.erb file, but I'm just sending it as a string. `"<%= @results %>"`, is just an example of a string that contains `%`s. If the obj were `obj = {"key":"%something%"}` the problem still occurs. – choey Jan 02 '18 at 19:59
  • Perhaps try `to_query` instead of `to_json`? – jvillian Jan 02 '18 at 20:02
  • I'll gladly give it a try, though every example I've seen appears to use `to_json` for this task - such as here: https://stackoverflow.com/a/7617185/6837388 – choey Jan 02 '18 at 20:34
  • Apologies, I abstracted my HTTParty a long time ago. Just checked my code and in fact I use `to_json` as well. A misfire on my part. – jvillian Jan 02 '18 at 20:36
  • @jvillian, Thank you anyway, I appreciate the help – choey Jan 02 '18 at 22:43

1 Answers1

0

Considering they way how it's implemented here: https://github.com/jnunemaker/httparty/blob/38125db0d079d52a3b0da815150fa2135bb0110d/lib/httparty.rb#L559,

Your body and headers hash keys should be siblings, try the next:

resp = HTTParty.post('https://test-url.com/data',
  :body => obj.to_json,
  :headers => { 'Content-Type' => 'application/json',
                'Accept' => 'application/json' }
)