With http.server how to access the called IP address? - python-3.x

This must be very simple, but can't find any reference on documentation and google isn't helping.
On the below example
from http.server import BaseHTTPRequestHandler, HTTPServer
PORT_NUMBER = 80
class myHandler(BaseHTTPRequestHandler):
def do_GET(self):
print(self.path) # <<<<<<<< Here
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
self.wfile.write(bytes("Hello world", "utf8"))
server = HTTPServer(('', PORT_NUMBER), myHandler)
server.serve_forever()
If my machine has multiple interfaces, the binding is done with 0.0.0.0. How can I on the request handler retrieve the IP which was received the socket connection ?

In the do_* methods of an instance of BaseHTTPRequestHandler, self.request is the socket.socket object associated with the request. You can get the server side of the socket with self.request.getsockname(), which will give you a tuple of the server IP and port that the client connected to. Therefore the IP address will be:
self.request.getsockname()[0]

Related

Python 3.10 - Is this a safe HTTPS simple server template?

New to web-facing python applications, and managed to put together a couple of templates to create a template that will serve as foundation for a project-level HTTPS server that handles basic requests.
Is python secure for creating HTTPS servers? Obviously environment is a factor, and I'd plan to run this isolated from other devices on the network. It's going to be providing non-sensitive information that is stored locally on the machine which will support TLS 1.3.
But what else do I need to consider looking out for?
import http.server
import ssl
host = '127.0.0.1'
port = 443
class Handler(http.server.SimpleHTTPRequestHandler):
def _set_response(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_GET(self):
self._set_response()
self.wfile.write("GET request for {}".format(self.path).encode('utf-8'))
def do_POST(self):
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
self._set_response()
self.wfile.write("POST request for {}".format(self.path).encode('utf-8'))
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
context.load_cert_chain('cert.pem', 'key.pem')
httpd = http.server.HTTPServer((host, port), Handler)
httpd.socket = context.wrap_socket(httpd.socket, server_side=True)
httpd.serve_forever()

ConnectionRefusedError: [Errno 111] Connect call failed -- What IP's do i need to target?

This is my first time posting, and I'm in a difficult situation i'd consider somewhat unique.
My Goal and Whats happened so far:
Basically, I just need to pass integers from my desktop PC to a raspberry pi in "real time", preferably over a wireless connection. The code snippets below are versions of the "test program" that employ specifically what I'm having issues with. To achieve this, I'm using the python websockets module
The issue I'm facing is new to me, because previously this program worked entirely as intended, as I lived in a location where I owned my router in a house, but now I live in an apartment complex with special network restrictions (needing to register MAC addresses and such)
Previous Results (When I lived at the previous location)
I achieved the desired results of pasting random integers to the console as fast as possible that were generated from the server PC with the following programs below. Note that when I put i used the IP that could be easily found when you google "what is my IP"
SERVER SIDE (ON THE PC)
import asyncio
import websockets
import random
async def createdata():
return random.randint(0, 15000)
async def senddata(websocket, path):
number = await createdata()
print("sending data")
await websocket.send(str(number))
print(number)
start_server = websockets.serve(senddata, "<INSERTIPHERE>", 4421)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
CLIENT SIDE (ON THE RASP PI)
import asyncio
import websockets
async def datarecieve():
uri = "ws://<INSERTIPHERE>:4421"
async with websockets.connect(uri) as websocket:
data = await websocket.recv()
print(data)
while True:
asyncio.get_event_loop().run_until_complete(datarecieve())
Results Now (Now that I live in the apartment complex)
I get the error thrown on the client side: ConnectionRefusedError: [Errno 111] Connect call failed (ipgoeshere, port). Here are the programs:
SERVER SIDE (ON THE PC)
import asyncio
import websockets
import random
async def createdata():
return random.randint(0, 15000)
async def senddata(websocket, path):
number = await createdata()
print("sending data")
await websocket.send(str(number))
print(number)
start_server = websockets.serve(senddata, "localhost", 4421)
asyncio.get_event_loop().run_until_complete(start_server)
asyncio.get_event_loop().run_forever()
CLIENT SIDE (ON THE RASP PI)
import asyncio
import websockets
async def datarecieve():
uri = "ws://<externalipofappartmentcomplex>:4421"
async with websockets.connect(uri) as websocket:
data = await websocket.recv()
print(data)
while True:
asyncio.get_event_loop().run_until_complete(datarecieve())
More Information About What I've Tried or What I'm Willing to Do
For the server side, I've also tried ips like: 127.0.0.1, 0.0.0.0, and the ipv4 assigned to the device (found in ipconfig in cmd)
For the Client side, I've also tried the ipv4 assigned to the server device
Opening up the port on the firewall of the server computer
I've considered just buying my own wireless router and hopefully finding luck that way
Thank you for any help.

Unable to connect using ip address from client in simple python socket program

Honestly, this is lifted more or less from tutorials point networking on python-https://www.tutorialspoint.com/python/python_networking.html
Server program:
import socket # Import socket module
dd="You connected sucessfully to the server"
dd1=bytes(dd,'UTF-8')
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # Create a socket object
host = socket.gethostname() # Get local machine name
port = 12345 # Reserve a port for your service.
s.bind((host, port)) # Bind to the port
s.listen(5) # Now wait for client connection.
while True:
c, addr = s.accept() # Establish connection with client.
print ('Got connection from', addr)
c.send(dd1)
c.close() # Close the connection
Client side:
import socket # Import socket module
s = socket.socket(socket.AF_INET) # Create a socket object
host = '80.78.xxx.xxx' # Get local machine name/value
port = 12345 # Reserve a port for your service.
s.connect((host, port))
print(s.recv(102004))
s.close() # Close the socket when done
So, I'm able to run it on the same PC and get result. If my understanding of the code is correct, host means localhost. But it should also work when I try to access it using the ip address. But it doesn't. Please help. It returns the error: Error 10060
https://help.globalscape.com/help/archive/cuteftp6/socket_error_=__10060.htm#:~:text=10060%20is%20a%20Connection%20Time,prefers%20PORT%20for%20data%20connections.&text=ERROR%3A%3E%20Can't%20connect%20to%20remote%20server.
I forwarded the ports 12340 to 12350 to my ip address on the router. Removed all firewall. Yet this happens.
A similar error happend when I tried to put a website up using node.js. Works perfectly on local host but doesn't work when I try to access using public IP address. I'm very confused and would be glad if you pointed to any literature to get a deeper understanding.

Why isn't my HTTP proxy connecting to an HTTPS website?

I am trying to understand why a proxy is not connecting to the website, but displays my IP instead
import httpx
import asyncio
proxies = {"http": "http://34.91.135.38:80"}
async def main():
async with httpx.AsyncClient(proxies=proxies) as client:
s = await client.get('https://api.ipify.org')
print(s.text)
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
When I try to do that, it will display my IP, not the IP I selected. I want to be able to use my proxy to connect to the website

How to create a simple HTTP webserver in python 3 responding to GET request with a generated content?

How do I create a simple HTTP webserver in python 3, that would return a generated content for GET requests?
I checked this question,
How to create a simple HTTP webserver in python?, but the solution proposed will return files, which is not the thing I need.
Instead, my server should respond with a generated response.
I know about frameworks like Flask and Django, but they would be an overkill for me. I need the shortest and the least resource greedy code that will just return generated content for any request.
After a little bit of research, I have come up with this as the simplest possible solution:
from http.server import HTTPServer, BaseHTTPRequestHandler
class MyRequestHandler(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(b'My content')
httpd = HTTPServer(('localhost', 5555), MyRequestHandler)
httpd.serve_forever()
You can do so with the http module as shown below:
from http.server import BaseHTTPRequestHandler, HTTPServer
import time
hostname = "localhost"
serverPort = 8080
class Server(BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(bytes("<html><head><title>Python Webserver</title>
</head>", "utf-8"))
self.wfile.write(bytes("<body>", "utf-8"))
self.wfile.write(bytes("<p>Web server is open!</p>", "utf-8"))
self.wfile.write(bytes("</body></html>", "utf-8"))
if __name__ == "__main__":
webServer = HTTPServer((hostname, serverPort), Server)
print("Server started http://%s:%s" % (hostname, serverPort))
try:
webServer.serve_forever()
except KeyboardInterrupt:
pass
webServer.server_close()
print("Server closed")
time.sleep(2)
This code creates a web server on http://localhost:8080 and displays some text saying Web server is open!.

Resources