Search code examples
jythongrinder

Sending form data with an HTTP PUT request using Grinder API


I'm trying to replicate the following successful cURL operation with Grinder.

curl -X PUT -d "title=Here%27s+the+title&content=Here%27s+the+content&signature=myusername%3A3ad1117dab0ade17bdbd47cc8efd5b08" http://www.mysite.com/api

Here's my script:

from net.grinder.script import Test
from net.grinder.script.Grinder import grinder
from net.grinder.plugin.http import HTTPRequest
from HTTPClient import NVPair
import hashlib

test1 = Test(1, "Request resource")
request1 = HTTPRequest(url="http://www.mysite.com/api")
test1.record(request1)
log = grinder.logger.info
test1.record(log)
m = hashlib.md5()

class TestRunner:
    def __call__(self):
        params = [NVPair("title","Here's the title"),NVPair("content", "Here's the content")]
        params.sort(key=lambda param: param.getName())
        ps = ""
    for param in params:
            ps = ps + param.getValue() + ":"
        ps = ps + "myapikey"
        m.update(ps)
        params.append(NVPair("signature", ("myusername:" + m.hexdigest())))
        request1.setFormData(tuple(params))
        result = request1.PUT()

The test runs okay, but it seems that my script doesn't actually send any of the params data to the API, and I can't work out why. There are no errors generated, but I get a 401 Unauthorized response from the API, indicating that a successful PUT request reached it, but obviously without a signature the request was rejected.


Solution

  • This isn't exactly an answer, more of a workaround that I came up with, that I've decided to post since this question hasn't yet received any responses, and it may help anyone else trying to achieve the same thing.

    The workaround is basically to use the httplib and urllib modules to build and make the PUT request instead of the HTTPClient module.

    import hashlib
    import httplib, urllib
    
    ....
    
    params = [("title", "Here's the title"),("content", "Here's the content")]
    params.sort(key=lambda param: param[0])
    ps = ""
    for param in params:
        ps = ps + param[1] + ":"
    ps = ps + "myapikey"
    m = hashlib.md5()
    m.update(ps)
    params.append(("signature", "myusername:" + m.hexdigest()))
    
    params = urllib.urlencode(params)
    print params
    headers = {"Content-type": "application/x-www-form-urlencoded"}
    conn = httplib.HTTPConnection("www.mysite.com:80")
    conn.request("PUT", "/api", params, headers)
    response = conn.getresponse()
    print response.status, response.reason
    print response.read()
    conn.close()
    

    (Based on the example at the bottom of this documentation page.)