views:

357

answers:

2

I'm been playing with calling my rails controller using an HTTP POST. I can get it to work with a curl command such as this, given a model named item and an attribute in that item called name:

curl -X POST -d "<item><name>myname</name></item>" -H "Content-Type: text/xml" http://localhost:3000/items.xml

What I'm curious about is how to make the same call using text instead of xml as my content type.... I tried:

curl -X POST -d "name=myname" http://localhost:3000/items.xml

but that seems to pass the 'name' parameter as the top level scope; so it doesn't end up in my params in the controller....

I'm a noob at this; just want to understand how to do it both ways....

Thanks!

+3  A: 

Hi,

Short answer, you need to

(a) send it as -H "Content-type: application/x-www-form-urlencoded".

(b) specify the parameters as Object[field]=value - for example User[name] would refer to the name field in some user object.

(c) [Not Required because you use curl] encode the parameters and POST/PUT them.


Encoding the parameters

The encoding is simple enough and although curl will do it for you, it's useful to understand it. I've quoted an extract from the W3C spec... "

application/x-www-form-urlencoded

This is the default content type. Forms submitted with this content type must be encoded as follows:

  1. Control names and values are escaped. Space characters are replaced by +', and then reserved characters are escaped as described in [RFC1738], section 2.2: Non-alphanumeric characters are replaced by %HH', a percent sign and two hexadecimal digits representing the ASCII code of the character. Line breaks are represented as "CR LF" pairs (i.e., `%0D%0A').

  2. The control names/values are listed in the order they appear in the document. The name is separated from the value by =' and name/value pairs are separated from each other by &'.

"

Simple Example (New User Form)

The example below is how to send a simple "New User" form.

If I have fields in the user object for name, password, email etc, I specify them like this ...

user[firstname]=chris&user[login]=cmccauley&user[company_id]=8&user[email]=&user[surname]=mccauley

then curl will escape them to give ...

user%5Bfirstname%5D=chris&user%5Blogin%5D=cmccauley&user%5Bcompany_id%5D=8&user%5Bemail%5D=&user%5Bsurname%5D=mccauley

... before posting them like this extract from a wire dump ...



Wireshark dump


POST /users/19 HTTP/1.1    
Host: localhost:3000    
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.10) Gecko/2009042523 Ubuntu/9.04 (jaunty) Firefox/3.0.10    
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8    
Accept-Language: en-us,en;q=0.5    
Accept-Encoding: gzip,deflate    
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7    
Keep-Alive: 300    
Connection: keep-alive    
Referer: http://localhost:3000/users/19/edit

Cookie: _my_session=048d330143de668e027c8cd52654e8c5

Content-Type: application/x-www-form-urlencoded

Content-Length: 259



user%5Bfirstname%5D=chris&user%5Blogin%5D=cmccauley&user%5Bcompany_id%5D=8&user%5Bemail%5D=&user%5Bsurname%5D=mccauley&user_password=********&user%5Bjob_id%5D=14&user%5Bpassword%5D=dd793a64b74e108fcdc5d809040e24afcc21ad2c&authenticity_token=&id=19&_method=PUT
Chris McCauley
+2  A: 

"Content-type: application/x-www-form-urlencoded" is already default with curl -d, no need for anything extra

-X POST is superfluous, as -d implies POST

-d does not URL encode the data. To get curl to do that for you, you need to use --data-urlencode instead

Daniel Stenberg