I am trying to write a python application that will listen for HTTP responses on a socket. I am using http-parser for this. Here is my code:
#!/usr/bin/env python
import socket
from http_parser.http import HttpStream
from http_parser.reader import SocketReader
from http_parser.util import b
def main():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((socket.gethostname(), 7000))
s.listen(5)
try:
while True:
p = HttpStream(SocketReader(s))
finally:
s.close()
if __name__ == "__main__":
main()
I have two questions:
- Is this the best way to do this? Note that I do not want to send a request and then listen for a response. I want to have a redirection mechanism that redirects all responses to the box running this script.
- How should I test this? Is there a tool that can mock HTTP responses?
EDIT
What I am trying to do is this: I have three boxes, once runs Apache, one runs this script and one is the client. When the client connects to Apache and it sends back a response, I am diverting the response to this box. So in this script, I am trying to listen for HTTP responses.
Topology
Here is my topology:
Server <----> Switch one <-----> Switch two <-----> Box one and two
Initially, box one connects to the server and sends a request. When the second switch receives responses from the server, it forks it to both box one and box two.
That is a perfectly fine implementation if you really want to operate at the level of TCP sockets. If you want more abstraction, there are lots and lots of HTTP server packages for python, including the standard library's BaseHttpServer
, and external libraries/frameworks like tornado and cherrypy.
To test your HTTP listener there are lots of options. You could write full-on HTTP client test code in Python (using an HTTP client library like urllib
), or you could:
A note on terminology: What you are listening for on your bound socket is an HTTP request, in the HTTP parlance; what you send back to the connecting client is a response.
1. Is there is a better way?
Yes, there is
2. How should I test this?
common practice is to put a test.py in the same folder, and run python test.py to test. Sample code:
#!python
# -*- coding: utf-8 -*-
import optparse
import urllib2
from django.utils import unittest
# just a sample of settings
HOST = 'localhost'
class GIOPTest(unittest.TestCase):
def test_basic(self):
#TEST GOES HERE
if __name__ == '__main__':
# This part is to accept command line parameters
option_list = ( # check optparse help for more options
make_option("--host",
action = 'store',
type = 'string',
dest = 'host',
default = 'localhost',
help = 'Server host (localhost by default)'
),
)
parser = OptionParser(option_list=option_list)
options, args = parser.parse_args()
HOST = options.host
# run the test
unittest.main()
I ended up using a raw socket and directly reading packets from it.
if you're using apache as the server you're redirecting the data to you could use apache benchmark (ab - you must be superuser though to use it as far as I know) to test it... will also help evaluate the performance impact your application has on the whole thing, example
ab -n 500 -c 20 http://localhost:7000/
where after -n is the total number of connections made to the server during the test and after -c you have the number of concurrent connections apache benchmark will make, experiment with different values of these, also read it's manual, you might find more useful options for whatever your specific purpose might be