4

Building a simple file server using the SimpleHTTPServer module in Python, however I'm running into issues when trying to get the IP from a connecting client. Here is what I have..

import SimpleHTTPServer

Handler = SimpleHTTPServer.SimpleHTTPRequestHandler
httpd = SocketServer.TCPServer(("", 8080), Handler)

print "Serving local directory"

while True:
    httpd.handle_request()
    print Handler.client_address[0]

When a client connects I get..

AttributeError: class SimpleHTTPRequestHandler has no attribute 'client_address'

I know this is because I haven't instantiated the class yet, but is there another way to get the IP from the client without having to create a handler instance? The client's IP is outputted to the console when a connection is made, I just need a way to grab that IP within my script.

Thanks!

veefu
  • 2,820
  • 1
  • 19
  • 29
adev
  • 95
  • 1
  • 2
  • 9

1 Answers1

8

Indeed, the Handler class object is unrelated to specific instances. Set up your own handler class, like this:

import SimpleHTTPServer
import SocketServer


class MyHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def handle_one_request(self):
        print(self.client_address[0])
        return SimpleHTTPServer.SimpleHTTPRequestHandler.handle_one_request(self)

print("Serving local directory")
httpd = SocketServer.TCPServer(("", 8080), MyHandler)

while True:
    httpd.handle_request()
phihag
  • 278,196
  • 72
  • 453
  • 469
  • How would I then go about using it in the rest of the script? To be more clear, I will need it to do some operations later on in the script. – adev May 05 '16 at 16:23
  • Simply call any per-request functions inside `handle_one_request`. If you want global information (for example, print the last 10 requesting IPs), set up a global variable (alternatively, one attached to the server object) where you enter information in to. – phihag May 05 '16 at 16:25
  • Not sure I understand, mind showing me an example? Any attempts I make eventually ends in me trying to access a variable from the class (which I can't do) – adev May 05 '16 at 16:42
  • This answer already contains an example, but I'd gladly add another one. To know that, I must know *when* you want which IPs though. Possible options for when could be when the time strikes midnight, when you get 100 requests, on every request, etc. . – phihag May 05 '16 at 16:46
  • It would simply be once a client connects. To be more specific, this script will need to use an incoming IP as a key to a dictionary entry that maps to a certain MAC address. So end to end operation, this should host a directory, get the incoming IP, lookup the corresponding MAC address, and then be able to work on that MAC address. – adev May 05 '16 at 16:54
  • @Devigili Then simply replace `print(self.client_address[0])` with `mac_address = lookupMACAdress(self.client_address[0])`, and then work on the `mac_address`. If you want, you can also assign it to the handler (`self.mac_address = lookupMACAdress(self.client_address[0])`) so that you can later use it as `self.mac_address`, for example in a `do_GET` method. – phihag May 05 '16 at 16:59
  • But my dictionary is outside of the scope of the MyHandler class, how would I be able to get the IP out of the class if the class is never instantiated? I could pass it in as a variable but I'd rather find another way if its possible. – adev May 05 '16 at 18:13
  • There is a multitude of options: global in the current module, global in another module, attach it to a class, attach it to the server (not the handler). Pick any. – phihag May 05 '16 at 18:35
  • Then what is the valid syntax to set that global variable (wherever I put it) from within the handler? Every time I try to access I simply get an out of scope problem. – adev May 05 '16 at 18:49
  • Write `mac_addresses = {}` in the third line of this example, and then from inside the handler access `mac_addresses[self.client_address[0]]`. – phihag May 05 '16 at 18:52
  • Okay, that works. Can you explain why declaring `current_ip = None` on line 3 and then using `current_ip = self.client_address[0]` within the Handler doesn't work? – adev May 05 '16 at 19:02
  • That doesn't really make sense in the first place, as `current_ip` would then be a global variable, and the server could very well be multi-threaded, so it would be wrong. If you want to store the current IP, either pass it on as function arguments during the request, or assign it to the request handler. But the immediate reason is that you when you assign (`=`), you create or change a variable in the current scope, not the global one. – phihag May 05 '16 at 19:04
  • Oh wow, now it clicked. I got it working nice and smoothly. Thanks so much, you're a master! – adev May 05 '16 at 19:16