def httprequest(self, postdata): if not self.anubisURL.startswith("http://"): raise "Invalid URL, only http:// URLs are allowed: url='%s'" % ( self.anubisURL) if not postdata: raise "Invalid/No POST data supplied: postdata='%s'" % (postdata) headers = {} headers["Content-Type"] = "multipart/form-data" message = MIMEMultipart(_subtype="form-data") ### notification element part = MIMEText(None) part.set_payload(postdata["notification"], "us-ascii") part.add_header("Content-Disposition", "form-data", name="notification") message.attach(part) ### email element part = MIMEText(None) part.set_payload(postdata["email"], "us-ascii") part.add_header("Content-Disposition", "form-data", name="email") message.attach(part) ### type element part = MIMEText(None) part.set_payload(postdata["analysisType"], "us-ascii") part.add_header("Content-Disposition", "form-data", name="analysisType") message.attach(part) ### file data element part = MIMEBase('application', "octet-stream") part.set_payload(postdata['executable']['content']) ### Add content-disposition header. dispHeaders = postdata["executable"].get("headers", {}) part.add_header("Content-Disposition", "form-data", name="executable", filename=postdata["executable"]["filename"]) for dhName, dhValue in dispHeaders: part.add_header(dhName, dhValue) message.attach(part) message.epilogue = "" headerBlock, body = message.as_string().split("\n\n", 1) for hName, hValue in message.items(): headers[hName] = hValue ### Make the HTTP request and get the response. ### Precondition: 'url', 'method', 'headers', 'body' are all setup properly. scheme, netloc, path, parameters, query, fragment = urlparse.urlparse( self.anubisURL) if parameters or query or fragment: raise "Unexpected URL: parameters=%r, query=%r, fragment=%r" % ( parameters, query, fragment) try: conn = httplib.HTTPConnection(netloc) conn.request("POST", path, body, headers) response = conn.getresponse() except socket.error, e: response = ConnRes(404, e)
def httprequest(self, postdata): if not self.anubisURL.startswith("http://"): raise "Invalid URL, only http:// URLs are allowed: url='%s'" % (self.anubisURL) if not postdata: raise "Invalid/No POST data supplied: postdata='%s'" % (postdata) headers = {} headers["Content-Type"] = "multipart/form-data" message = MIMEMultipart(_subtype="form-data") ### notification element part = MIMEText(None) part.set_payload(postdata["notification"], "us-ascii") part.add_header("Content-Disposition", "form-data", name="notification") message.attach(part) ### email element part = MIMEText(None) part.set_payload(postdata["email"], "us-ascii") part.add_header("Content-Disposition", "form-data", name="email") message.attach(part) ### type element part = MIMEText(None) part.set_payload(postdata["analysisType"], "us-ascii") part.add_header("Content-Disposition", "form-data", name="analysisType") message.attach(part) ### file data element part = MIMEBase('application', "octet-stream") part.set_payload(postdata['executable']['content']) ### Add content-disposition header. dispHeaders = postdata["executable"].get("headers", {}) part.add_header("Content-Disposition", "form-data", name="executable", filename=postdata["executable"]["filename"]) for dhName, dhValue in dispHeaders: part.add_header(dhName, dhValue) message.attach(part) message.epilogue = "" headerBlock, body = message.as_string().split("\n\n",1) for hName, hValue in message.items(): headers[hName] = hValue ### Make the HTTP request and get the response. ### Precondition: 'url', 'method', 'headers', 'body' are all setup properly. scheme, netloc, path, parameters, query, fragment = urlparse.urlparse(self.anubisURL) if parameters or query or fragment: raise "Unexpected URL: parameters=%r, query=%r, fragment=%r" % (parameters, query, fragment) try: conn = httplib.HTTPConnection(netloc) conn.request("POST", path, body, headers) response = conn.getresponse() except socket.error, e: response = ConnRes(404, e)
def httprequest(url, postdata={}, headers=None, ssl=False): """A urllib.urlopen() replacement for http://... that gets the content-type right for multipart POST requests. "url" is the http URL to open. "postdata" is a dictionary describing data to post. If the dict is empty (the default) a GET request is made, otherwise a POST request is made. Each postdata item maps a string name to either: - a string value; or - a file part specification of the form: {"filename": <filename>, # file to load content from "content": <content>, # (optional) file content "headers": <headers>} # (optional) headers <filename> is used to load the content (can be overridden by <content>) and as the filename to report in the request. <headers> is a dictionary of headers to use for the part. Note: currently the file part content but be US-ASCII text. "headers" is an optional dictionary of headers to send with the request. Note that the "Content-Type" and "Content-Length" headers are automatically determined. The current urllib.urlopen() *always* uses: Content-Type: application/x-www-form-urlencoded for POST requests. This is incorrect if the postdata includes a file to upload. If a file is to be posted the post data is: Content-Type: multipart/form-data This returns the response content if the request was successfull (HTTP code 200). Otherwise an IOError is raised. For example, this invocation: url = 'http://www.perl.org/survey.cgi' postdata = { "name": "Gisle Aas", "email": "gisle at aas.no", "gender": "M", "born": "1964", "init": {"filename": "~/.profile"}, } Inspiration: Perl's HTTP::Request module. http://aspn.activestate.com/ASPN/Reference/Products/ActivePerl/site/lib/HTTP/Request/Common.html """ if not url.startswith("http://"): raise "Invalid URL, only http:// URLs are allow: url='%s'" % url if not headers: headers = {} if not postdata: method = "GET" body = None else: method = "POST" # Determine if require a multipart content-type: 'contentType'. for part in postdata.values(): if isinstance(part, dict): contentType = "multipart/form-data" break else: contentType = "application/x-www-form-urlencoded" headers["Content-Type"] = contentType # Encode the post data: 'body'. if contentType == "application/x-www-form-urlencoded": body = urllib.urlencode(postdata) elif contentType == "multipart/form-data": message = MIMEMultipart(_subtype="form-data") for name, value in postdata.items(): if isinstance(value, dict): # Get content. if "content" in value: content = value["content"] else: fp = open(value["filename"], "rb") content = fp.read() part = MIMEBase('application', "octet-stream") part.set_payload(content) # Encoders.encode_base64(part) # Add content-disposition header. dispHeaders = value.get("headers", {}) if "Content-Disposition" not in dispHeaders: #XXX Should be a case-INsensitive check. part.add_header("Content-Disposition", "form-data", name=name, filename=value["filename"]) for dhName, dhValue in dispHeaders: part.add_header(dhName, dhValue) else: # Do not use ctor to set payload to avoid adding a # trailing newline. part = MIMEText(None) part.set_payload(value, "us-ascii") part.add_header("Content-Disposition", "form-data", name=name) message.attach(part) message.epilogue = "" # Make sure body ends with a newline. # Split off the headers block from the .as_string() to get # just the message content. Also add the multipart Message's # headers (mainly to get the Content-Type header _with_ the # boundary attribute). headerBlock, body = message.as_string().split("\n\n", 1) for hName, hValue in message.items(): headers[hName] = hValue #print "XXX ~~~~~~~~~~~~ multi-part body ~~~~~~~~~~~~~~~~~~~" #import sys #sys.stdout.write(body) #print "XXX ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" else: raise "Invalid content-type: '%s'" % contentType # Make the HTTP request and get the response. # Precondition: 'url', 'method', 'headers', 'body' are all setup properly. scheme, netloc, path, parameters, query, fragment = urlparse.urlparse(url) if parameters or query or fragment: raise "Unexpected URL form: parameters, query or fragment parts "\ "are not allowed: parameters=%r, query=%r, fragment=%r"\ % (parameters, query, fragment) if ssl: conn = httplib.HTTPSConnection(netloc) else: conn = httplib.HTTPConnection(netloc) conn.request(method, path, body, headers) response = conn.getresponse() return response
def httprequest(url, postdata={}, headers=None, ssl = False): """A urllib.urlopen() replacement for http://... that gets the content-type right for multipart POST requests. "url" is the http URL to open. "postdata" is a dictionary describing data to post. If the dict is empty (the default) a GET request is made, otherwise a POST request is made. Each postdata item maps a string name to either: - a string value; or - a file part specification of the form: {"filename": <filename>, # file to load content from "content": <content>, # (optional) file content "headers": <headers>} # (optional) headers <filename> is used to load the content (can be overridden by <content>) and as the filename to report in the request. <headers> is a dictionary of headers to use for the part. Note: currently the file part content but be US-ASCII text. "headers" is an optional dictionary of headers to send with the request. Note that the "Content-Type" and "Content-Length" headers are automatically determined. The current urllib.urlopen() *always* uses: Content-Type: application/x-www-form-urlencoded for POST requests. This is incorrect if the postdata includes a file to upload. If a file is to be posted the post data is: Content-Type: multipart/form-data This returns the response content if the request was successfull (HTTP code 200). Otherwise an IOError is raised. For example, this invocation: url = 'http://www.perl.org/survey.cgi' postdata = { "name": "Gisle Aas", "email": "gisle at aas.no", "gender": "M", "born": "1964", "init": {"filename": "~/.profile"}, } Inspiration: Perl's HTTP::Request module. http://aspn.activestate.com/ASPN/Reference/Products/ActivePerl/site/lib/HTTP/Request/Common.html """ if not url.startswith("http://"): raise "Invalid URL, only http:// URLs are allow: url='%s'" % url if not headers: headers = {} if not postdata: method = "GET" body = None else: method = "POST" # Determine if require a multipart content-type: 'contentType'. for part in postdata.values(): if isinstance(part, dict): contentType = "multipart/form-data" break else: contentType = "application/x-www-form-urlencoded" headers["Content-Type"] = contentType # Encode the post data: 'body'. if contentType == "application/x-www-form-urlencoded": body = urllib.urlencode(postdata) elif contentType == "multipart/form-data": message = MIMEMultipart(_subtype="form-data") for name, value in postdata.items(): if isinstance(value, dict): # Get content. if "content" in value: content = value["content"] else: fp = open(value["filename"], "rb") content = fp.read() part = MIMEBase('application', "octet-stream") part.set_payload( content ) # Encoders.encode_base64(part) # Add content-disposition header. dispHeaders = value.get("headers", {}) if "Content-Disposition" not in dispHeaders: #XXX Should be a case-INsensitive check. part.add_header("Content-Disposition", "form-data", name=name, filename=value["filename"]) for dhName, dhValue in dispHeaders: part.add_header(dhName, dhValue) else: # Do not use ctor to set payload to avoid adding a # trailing newline. part = MIMEText(None) part.set_payload(value, "us-ascii") part.add_header("Content-Disposition", "form-data", name=name) message.attach(part) message.epilogue = "" # Make sure body ends with a newline. # Split off the headers block from the .as_string() to get # just the message content. Also add the multipart Message's # headers (mainly to get the Content-Type header _with_ the # boundary attribute). headerBlock, body = message.as_string().split("\n\n",1) for hName, hValue in message.items(): headers[hName] = hValue #print "XXX ~~~~~~~~~~~~ multi-part body ~~~~~~~~~~~~~~~~~~~" #import sys #sys.stdout.write(body) #print "XXX ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~" else: raise "Invalid content-type: '%s'" % contentType # Make the HTTP request and get the response. # Precondition: 'url', 'method', 'headers', 'body' are all setup properly. scheme, netloc, path, parameters, query, fragment = urlparse.urlparse(url) if parameters or query or fragment: raise "Unexpected URL form: parameters, query or fragment parts "\ "are not allowed: parameters=%r, query=%r, fragment=%r"\ % (parameters, query, fragment) if ssl: conn = httplib.HTTPSConnection(netloc) else: conn = httplib.HTTPConnection(netloc) conn.request(method, path, body, headers) response = conn.getresponse() return response