Send a request to webservice via an xml file? - python

I have a webservice running at "tcs-webdev2:8200/scheduler/requestgroup" to which new build requests can be sent using an xml file(sample xml file below). I need some guidance
on how requests to a webserive via n xml file work.
Sample xml file:-
<BuildInfo>
<BuildSource>DEV_CI</BuildSource>
<SoftwareProductBuild>MAAAAANLGD0000211.1_101</SoftwareProductBuild>
<PriorrootBuild>MAAAAANLGD0000211.1</PriorrootBuild>
<NewSIBuilds>
<Image>
<Type>LNX</Type>
<SoftwareImageBuild>buildlocation</SoftwareImageBuild>
<Location>\\\sever\buildlocation\checkout</Location>
<Variant>Default</Variant>
<LoadType>Debug</LoadType>
</Image>
</NewSIBuilds>
</BuildInfo>

It depends on your web service, how exactly you need to send the request, but you have to something like the following:
import httplib
with open("your_xml_filename.xml") as f:
body = f.read()
headers = {"Content-type": "application/xml"}
conn = httplib.HTTPConnection("tcs-webdev2", 8200)
conn.request("POST", "/scheduler/requestgroup", body, headers)
response = conn.getresponse()
print( response.status )
print( response.read())
conn.close()
It assumes that tcs-webdev2 is a valid hostname (if not, you can use the IP address). Also this request is an HTTP POST, your service might need different request type. Also some additional headers and authentication might be needed.

Related

Node server doesnt recieve the JSON file I send him

i'm trying to send a post request to my express server using python, this is my code:
import requests
print("started");
URL = "http://localhost:5000/api/chat"
PARAMS = {'ID':"99","otherID":"87",'chat':[{"senderName":"tom","text":"helloworld"}]}
r = requests.post(url = URL, data = PARAMS)
pastebin_url = r.text
print("The pastebin URL is:%s"%pastebin_url)
but when I recieve the call, I get an empty object on my Node server, am I missing something?
(With postman it works fine so its not the server)
typically requests library differentiates on the type of request depending on the param used to make the request. Meaning if you intend to make a JSON post then one should use the json param like so:
response = requests.post(url=URL, json=PARAMS)
what this does is set the accompanying headers which is why when your express server attempts to parse it, it comes back empty

python making a post file request

Hi guys I'm developing a Python 3 quart asyncio application and I'm trying to setup a test framework around my http API.
Quart has methods to build json, form and raw requests but no files request. I believe I need build the request packet myself and post a "raw" request.
Using postman I can see that the requests need to look like this:
----------------------------298121837148774387758621\r\n
Content-Disposition: form-data; name="firmware"; filename="image.bin"\r\n
Content-Type: application/octet-stream\r\n
\r\n
\x00#\x00\x10\x91\xa0\t\x08+\xaa\t\x08/\xaa\t\x083\xaa\t\x087\xaa\t\x08;\xaa\t\x08\x00\x00\x00\
....
\xff\xff\xff\xff\xff\xff\xff\xa5\t\tZ\x0c\x00Rotea MLU Main V0.12\x00\x00k%\xea\x06\r\n
----------------------------298121837148774387758621--\r\n
I'd prefer not to encode this myself if there is a method that exists.
Is there an module in Python where I can build the raw packet data and send it with the Quart API?
I have tried using quart requests:
import requests
from .web_server import app as quart_app
test_client = quart_app.test_client()
firmware_image = 'test.bin'
with open(firmware_image, 'rb') as f:
data = f.read()
files = {'firmware': (firmware_image, data , 'application/octet-stream')}
firmware_req = requests.Request('POST', 'http://localhost:5000/firmware_update', files=files).prepare()
response = await test_client.post('/firmware_update',
data=firmware_req.body,
headers={'Content-type': 'multipart/form-data'})
Any suggestions would be greatly appreciated.
Cheers. Mitch.
Python's requests module provides a prepare function that you can use to get the raw data it would send for the request.
import requests
url = 'http://localhost:8080/'
files = {'file' : open('z', 'rb'),
'file2': open('zz', 'rb')}
req = requests.Request('POST',url, files=files)
r = req.prepare()
print(r.headers)
print(r.body)

python post request throwing '400 Bad Request'

I am trying to execute below script where I try to send POST request. I have replaced some values in headers part in order to post it here. The issue I have is related to body of my request which I read from xmlFile.xml. File is in the same directory as my script. XML is written in one line and begins with following line:
<?xml version="1.0"?>
Could you please help? I cannot understand why it is returning 400 Bad Request. XML separately is working fine, but not from within the py script.
#!/usr/bin/python
import httplib
def do_request(xmlFile):
request = open(xmlFile, "r").read()
conn = httplib.HTTPConnection("ipAddress", port)
conn.putrequest("POST", "selector HTTP/1.1")
conn.putheader("Content-Length", "%d" % len(request))
conn.putheader("Content-Type", "text/xml")
conn.putheader("Host", "ipAddress")
conn.putheader("User-Agent", "userAgent")
conn.endheaders()
conn.send(request)
response = conn.getresponse()
print(response.status, response.reason)
data = response.read()
print(data)
conn.close()
do_request('xmlFile.xml')
IIRC the second argument to putrequest() should be the path part of the url (/ for the root). But you're making it much more complicated than it has to be - you could use conn.request(method, path, params, headers) as showed here, or (even better) just use python-requests actually (even the official httplib doc recommend it).

Make an http POST request to upload a file using Python urllib/urllib2

I would like to make a POST request to upload a file to a web service (and get response) using Python. For example, I can do the following POST request with curl:
curl -F "file=#style.css" -F output=json http://jigsaw.w3.org/css-validator/validator
How can I make the same request with python urllib/urllib2? The closest I got so far is the following:
with open("style.css", 'r') as f:
content = f.read()
post_data = {"file": content, "output": "json"}
request = urllib2.Request("http://jigsaw.w3.org/css-validator/validator", \
data=urllib.urlencode(post_data))
response = urllib2.urlopen(request)
I got a HTTP Error 500 from the code above. But since my curl command succeeds, it must be something wrong with my python request?
I am quite new to this topic and my question may have very simple answers or mistakes.
Personally I think you should consider the requests library to post files.
url = 'http://jigsaw.w3.org/css-validator/validator'
files = {'file': open('style.css')}
response = requests.post(url, files=files)
Uploading files using urllib2 is not impossible but quite a complicated task: http://pymotw.com/2/urllib2/#uploading-files
After some digging around, it seems this post solved my problem. It turns out I need to have the multipart encoder setup properly.
from poster.encode import multipart_encode
from poster.streaminghttp import register_openers
import urllib2
register_openers()
with open("style.css", 'r') as f:
datagen, headers = multipart_encode({"file": f})
request = urllib2.Request("http://jigsaw.w3.org/css-validator/validator", \
datagen, headers)
response = urllib2.urlopen(request)
Well, there are multiple ways to do it. As mentioned above, you can send the file in "multipart/form-data". However, the target service may not be expecting this type, in which case you may try some more approaches.
Pass the file object
urllib2 can accept a file object as data. When you pass this type, the library reads the file as a binary stream and sends it out. However, it will not set the proper Content-Type header. Moreover, if the Content-Length header is missing, then it will try to access the len property of the object, which doesn't exist for the files. That said, you must provide both the Content-Type and the Content-Length headers to have the method working:
import os
import urllib2
filename = '/var/tmp/myfile.zip'
headers = {
'Content-Type': 'application/zip',
'Content-Length': os.stat(filename).st_size,
}
request = urllib2.Request('http://localhost', open(filename, 'rb'),
headers=headers)
response = urllib2.urlopen(request)
Wrap the file object
To not deal with the length, you may create a simple wrapper object. With just a little change you can adapt it to get the content from a string if you have the file loaded in memory.
class BinaryFileObject:
"""Simple wrapper for a binary file for urllib2."""
def __init__(self, filename):
self.__size = int(os.stat(filename).st_size)
self.__f = open(filename, 'rb')
def read(self, blocksize):
return self.__f.read(blocksize)
def __len__(self):
return self.__size
Encode the content as base64
Another way is encoding the data via base64.b64encode and providing Content-Transfer-Type: base64 header. However, this method requires support on the server side. Depending on the implementation, the service can either accept the file and store it incorrectly, or return HTTP 400. E.g. the GitHub API won't throw an error, but the uploaded file will be corrupted.

How to send XML through HTTP Request in Python?

import urllib2
request = urllib2.Request("URL HERE", data="<port>0</port>",
headers={'Content-Type': 'application/xml'})
u = urllib2.urlopen(request)
response = u.read()
I tried this but found out the XML is never getting to the server. I need the XML to get to the server at the same time the HTTP request does so the proper response is sent back.
Perhaps this is what you are looking for:
http://www.voidspace.org.uk/python/articles/urllib2.shtml#data

Categories

Resources