user2363318
user2363318

Reputation: 1067

jenkins posting job xml via requests fails with exception

I have python write the file to disk for trouble shooting

Caused by: com.thoughtworks.xstream.io.StreamException:  : only whitespace content allowed before start tag and not - (position: START_DOCUMENT seen -... @1:1)

Code:

timeout = 3
headers = {'content-type': 'text/xml'}
configFile = {'file': open(os.environ['NEWJOBXML'], 'rb').read()}

newjobxml = requests.post("http://" + os.environ['USER'] + ":" + os.environ['API_TOKEN'] + "@" + os.environ['JR_URL'] + "/createItem?name=" + newjob, files=configFile, headers=headers, timeout=int(timeout))

I get this for the header too:

{'Accept': '*/*',
 'Accept-Encoding': 'gzip, deflate',
 'Authorization': 'Basic ********************************************************',
 'Connection': 'keep-alive',
 'Content-Length': '11629',
 'User-Agent': 'python-requests/2.5.1 CPython/2.7.5 Darwin/13.3.0',
 'content-type': 'text/xml'}

When I post the same xml via curl, no errors

curl -H "Content-type: text/xml" -X POST http://USER:API_TOKEN@JR_URL/createItem?name=newjob --data-binary @/tmp/.config.xml

I am trying to migrate my code from bash to python.

Upvotes: 1

Views: 675

Answers (1)

Lukas Graf
Lukas Graf

Reputation: 32600

Use requests.post(url, data=f.read(), ...) instead of the files keyword argument.


Using requests.post(files=files) will upload your file(s) as Multipart-encoded data (see the requests docs) - this is what you want for file upload in an HTML form, but that's not what you need in in your case.

curl --data-binary @filename will send the raw, unencoded contents of the file as the POST body. Such a request will look like this:

POST / HTTP/1.1
Host: localhost
Content-type: text/xml
Content-Length: 4

FOO

(Where FOO is the request body / the file contents).

Your request with the multipart encoded data however currently looks like this:

POST / HTTP/1.1
Host: localhost
Content-type: text/xml
Content-Length: 144

--c225e276f4d4486fabe5770cd4f72a11
Content-Disposition: form-data; name="file"; filename="file"

FOO

--c225e276f4d4486fabe5770cd4f72a11--

So the equivalent to curl's --data-binary for the requests library is to simply pass the raw data in the data keyword argument:

data = open('foo.xml', 'rb').read()
newjobxml = requests.post(url, data=data, headers=headers, timeout=int(timeout))

BTW: You may want to take a look at the autojenkins Python module.

Upvotes: 2

Related Questions