Question

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.

Was it helpful?

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.)

OTHER TIPS

You have to refer to the multi-form posting example in Grinder script gallery, but changing the Post to Put. It works for me.

files = ( NVPair("self", "form.py"), ) parameters = ( NVPair("run number", str(grinder.runNumber)), )

    # This is the Jython way of creating an NVPair[] Java array
    # with one element.
    headers = zeros(1, NVPair)

    # Create a multi-part form encoded byte array.
    data = Codecs.mpFormDataEncode(parameters, files, headers)
    grinder.logger.output("Content type set to %s" % headers[0].value)

    # Call the version of POST that takes a byte array.
    result = request1.PUT("/upload", data, headers)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top