Thursday, May 26, 2016

Solution: HTTP POST via curl has “data” value unexpectedly truncated

Problem

When using the curl command-line utility to manually sent an HTTP POST to a server, the “data” value specified in the message is unexpectedly truncated when the server receives it. 

For example, given this command line:

curl --request POST "https://www.myserver.example.com/api/submit" --header "Content-Length:115" --header "Accept-Language:en-us" --header "Host:www.myserver.example.com" --header "Accept:image/jpeg, application/x-ms-application, image/gif, application/xaml+xml, image/pjpeg, application/x-ms-xbap, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*" --header "User-Agent:Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1)" --header "Connection:Keep-Alive" --header "Cookie:ASP.NET_SessionId=some_sesson_token_here;" --header "Referer:https://www.myserver.example.com/" --header "Content-Type:application/x-www-form-urlencoded; Charset=UTF-8" --data "PrimaryID=719&SecondaryID=27483&email1=someone@example.com&email2=someone2@example.com&message=Visit+my+site+at+http://mysite.example.com&TertiaryID=1738242&subject=Subject+text+goes+here"

The server (an ASP.NET MVC application) received the message, but the “message” parameter was assigned a value of “Visit my site at http” – the “://mysite.example.com” portion of the value was missing.

The subsequent included parameters in the “--data” value, such as TertiaryID, were also completely missing their values, according to the server.

Solution

The problem is the Content-Length header value (from earlier in the command line).  As written, it has a value of 115, so the server is truncating the data value after 115 characters (which happened to be just after the “http” in the “message” parameter in this example).

The solution is to either set the Content-Length value to the actual length of the data value, or to just omit the Content-Length header entirely.

Thanks to my colleague Kevin for pointing that out and saving my sanity!  I had originally approached this problem assuming that the “://” was the problem – that curl wasn’t sending it correctly, and/or that the server was refusing it (possibly for security reasons) – but that turned out to be just a red herring, based on the fact that the incorrect Content-Length value just happened to fall near that substring’s position.