Question

I have to create a listening server that will receive HTTP POST / XML alert traffic from a network sensor and parse out the received XML. Being a beginner to Python, and having a tough time understanding classes, I wanted to get advice on if I'm implementing the classes and functionality I'm trying to achieve correctly, and if there's a better or "more Pythonic" way of doing it. I'm forcing myself to use classes in hopes that I better grasp the concept, I know I can just use regular functions.

The script so far:

I'm using the BaseHTTPServer and SocketServer module to create a threaded HTTP server, and xml.dom.minidom class for parsing the XML data. So far I have two classes set up - one to setup the threading (ThreadedHTTPServer) and another with everything else (ThreadedHTTPRequestHandler). The "everything else" class is currently managing the sessions and manipulating the data. I'm thinking I need three classes, breaking out the data manipulation into the third and leaving the second just to managing the inbound connections. Would this be correct? How would I pass the connection data from the ThreadedHTTPRequestHandler class to the new class that will be parsing and manipulating the XML data?

Any help for this newbie would be appreciated. Code is below, and it's currently working. All it does at this time is accept incoming connections and prints the XML of a specific tag I'm interested in.

import cgi
from xml.dom.minidom import parseString
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from SocketServer import ThreadingMixIn

# Server settings
HOST = ''
PORT = 5000
BUFF = 2048

class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
    """
    This class sets up multi-threading for the server
    """
    pass

class ThreadedHTTPRequestHandler(BaseHTTPRequestHandler):
    '''
    This class is the overall request handler.
    This class contains functions to manage client connections and manipulate data.
    '''

    def do_POST(self):
        '''
        This method handles the inbound HTTP POST data
        '''

        print 'Connection from: ', self.client_address[0], self.client_address[1]

        ctype = self.headers.getheader('content-type')
        content_len = int(self.headers.getheader('content-length'))

        if ctype == 'multipart/form-data':
            self.post_body = cgi.parse_multipart(self.rfile)
        elif ctype == 'application/x-www-form-urlencoded':
            self.post_body = self.rfile.read(content_len)
        else:
            self.post_body = ""

        self.done(200)
        self.handleXML()

    def done(self, code):
        '''
        Send back an HTTP 200 OK and close the connection
        '''

        try:
            self.send_response(code)
            self.end_headers()
        except:
            pass

        print 'Connection from: ', self.client_address[0], self.client_address[1], ' closed.'

#class XMLHandler():
    def handleXML(self):
        '''
        This method parses and manipulates the XML alert data
        '''

        xml_dom = parseString(self.post_body)
        xmlTag = xml_dom.getElementsByTagName('malware')[0].toxml()
        #print out the xml tag and data in this format: <tag>data</tag>
        print xmlTag

if __name__ == "__main__":
    try:
        server = ThreadedHTTPServer((HOST, PORT), ThreadedHTTPRequestHandler).serve_forever()
        print
    except KeyboardInterrupt:
        pass
Was it helpful?

Solution

You don't necessarily need a third class. What you need is a freestanding function,

def handle_xml(post_body):
    # work

so that you no longer need to store the post_body on the ThreadedHTTPRequestHandler.

Class hierarchies are a good fit for some problems, and a bad fit for most. Don't use them if you don't need to, they'll just complicate your code.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top