Mawg
Mawg

Reputation: 40145

How to get port number from an HTTP response, using Python?

I am trying to simulate Network Address Translation for some test code. I am mapping virtual users to high port numbers, then, when I want to test a request from user 1, I send it from port 6000 (user 2, from 6001, etc).

However, I can't see the port number in the response.

        connection = httplib.HTTPConnection("the.company.lan", port=80, strict=False,   
                                          timeout=10, source_address=("10.129.38.51", 6000))
        connection.request("GET", "/portal/index.html")
        httpResponse = connection.getresponse()
        connection.close()

httpResponse.status is 200, but I don't see the port number anywhere in the response headers.

Maybe I should be using some lower level socket functionality? If so, which is simplest and supports both HTTP and FTP? Btw, I only want to use built-in modules, nothing which I have to install.


[Update] I should have made it clearer; I really do need to get the actual port number received in the response, not just remember it.

Upvotes: 2

Views: 4164

Answers (3)

JumpAlways
JumpAlways

Reputation: 310

Considring your comments, I had to provide a new answer.

I though you can also put a non standard header host in your HTTPRespose,
'Host: domain/IP:port', so that your client can read it when it receives a response.


Server Response:

HTTP/1.1 200 OK
Date: Day, DD Month YYYY HH:MM:SS GMT
Content-Type: text/html; charset=UTF-8
Content-Encoding: UTF-8
Content-Length: LENGTH
Last-Modified: Day, DD Month YYYY HH:MM:SS GMT
Server: Name/Version (Platform)
Accept-Ranges: bytes
Connection: close
Host: domain/IP:port                                  #exapmple: the.company.lan:80

<html>
<head>
    <title>Example Response</title>
</head>
<body>
    Hello World!
</body>
</html>


Client:

connection = httplib.HTTPConnection("the.company.lan", port=80, 
                                    strict=False, timeout=10,
                                    source_address=("10.129.38.51", 6000))

connection.request("GET", "/portal/index.html")
httpResponse = connection.getresponse()

## store a dict with the response headers
## extract your custom header 'host'
res_headers = dict(httpResponse.getheaders());
server_address = tuple(headers['host'].split(':'))

## read the response content
HTMLData = httpResponse.read(CONTENT_LENGTH_HEADER)

connection.close()


This way you got server_address as a tuple (domain, port).

Upvotes: 0

JumpAlways
JumpAlways

Reputation: 310

To complete @TimSpence answer, you can use a socket object as an interface for your connection and then treat with some API your data as an HTTP object.

host = 'xxx.xxx.xxx.xxx'
port = 80
address = (host, port)

## socket object interface for a TCP connection
listener_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM,
                                socket.IPPROTO_TCP)
listener_socket.bind(address)
listener_socker.listen(MAX_CONNECTIONS)

## new_connection is the connection object you use to handle the data echange
## source_address (source_host, source_port) is the address object
##    source_port is what you're looking for
new_connection, source_address = listener_socket.accept()

data = new_connection.recv(65536)

## handle data as an HTTP object(for example as an HTTP request)

new_connection.close()

Upvotes: 2

Tim Spence
Tim Spence

Reputation: 67

HTTP messages do not contain anything about ports so the httpResponse will not have that information.

However, you will need a different connection object (which will map to a different underlying socket) for each request anyway so you can get that information from the HTTPconnection object.

_, port = connection.source_address

Does that help?

Upvotes: 2

Related Questions