CGI and POST/PUT URL Variables

Hi Everyone,

I encountered a strange problem when trying to write a cgi script to handle a PUT/POST scenario for a set of REST-style web services I'm writing in Ruby.

If I do a normal post to a url, say:

/cgi-bin/cgi.rb?a=1&b=1

The params attribute in the CGI class contains {'a'=>'1', 'b'=>'1'}. However, when doing a PUT or POST to the same URL, the params hash contains two elements, one that's empty, and the other that is keyed on the payload to the PUT/POST operation.

Can anyone see my error?

Thanks!

-Trevor Elliott

#!/usr/bin/ruby

···

#
# CGI script

require 'cgi'
require 'stringio'

cgi = CGI.new
cgi.out('type' => 'text/plain') {
   $stderr.write("handling #{cgi.request_method} request")
   cgi.params.inject(StringIO.new) { |out,value|
     value.each { |item| out << 'Item: ' << item << "\n" }
     out
   }.string
}

#!/usr/bin/env ruby
#
# Test script
# uses the ruby-json gem

require 'net/http'
require 'uri'

require 'rubygems'
require 'json/objects'

host = URI.parse('http://127.0.0.1:8080/cgi-bin/cgi.rb?thing=1')
req = Net::HTTP::Put.new(host.path + '?' + host.query)
req.body = {:id => 1, :name => 'test'}.to_json
req.set_content_type('text/plain')
puts req.body
puts req.path

res = Net::HTTP.new(host.host, host.port).start { |http|
   http.request(req)
}
puts res.body

Trevor Elliott wrote:

Hi Everyone,

I encountered a strange problem when trying to write a cgi script to
handle a PUT/POST scenario for a set of REST-style web services I'm
writing in Ruby.

If I do a normal post to a url, say:

/cgi-bin/cgi.rb?a=1&b=1

The params attribute in the CGI class contains {'a'=>'1', 'b'=>'1'}.
However, when doing a PUT or POST to the same URL, the params hash
contains two elements, one that's empty, and the other that is keyed on
the payload to the PUT/POST operation.

Can anyone see my error?

There is no error, Ruby's CGI module ignores the query string when the
method isn't GET. AFAIK, this is correct behaviour, you put all query
parameters into the body of the request when using POST - no idea about
PUT, that method only sees use with REST, which has been of only passing
interest to me. [insert rant about HTTP flawedness and bending over
business logic backwards to be stateless here]

Either redo the client code to use the proper way of passing the query
string to the application, or redo the CGI script to manually parse the
request string for the query string. The CGI module should have some
functionality for that.

Also, see Hypertext Style: Cool URIs don't change. for why "/cgi-bin/" and
".rb" are bad, bad things to put in your URL.

David Vallner

Trevor Elliott wrote:

Hi Everyone,

I encountered a strange problem when trying to write a cgi script to
handle a PUT/POST scenario for a set of REST-style web services I'm
writing in Ruby.

There is no error, Ruby's CGI module ignores the query string when the
method isn't GET. AFAIK, this is correct behaviour, you put all query
parameters into the body of the request when using POST - no idea about
PUT, that method only sees use with REST, which has been of only passing
interest to me. [insert rant about HTTP flawedness and bending over
business logic backwards to be stateless here]

David Vallner

I had my suspicions after I posted the question, so thanks for confirming
them :slight_smile: Given that this behavior had worked for me previously in other
situations, I just expected it to work here; I'll rethink my interaction
with the server.

-trevor elliott