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()
Related
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 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!.
For a project, I need a server and a client. Not a problem so far. The difficulty is for me, that the connection must be encrypted since sensible information will be sent. You could use RSA encryption. I just don't know yet how to exchange the keys so nobody could intercept them or get any other chance to reach them.
Since I don't know, how to do it in general, I did not try anything so far.
Here is a TLS connection implementation in Python. All key exchanging and encrypting data is done within the protocol.
import socket
import ssl
def main():
#Define Host Name And Port (Port 443 Is Typical Encrypted Web Connection Port)
host_name = "www.google.com"
host_port = 443
#Create Unencrypted Connection And Then Encrypted It By Wrapping It
unencrypted_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
unencrypted_socket.settimeout(10)
encrypted_socket = ssl.wrap_socket(unencrypted_socket,ssl_version=ssl.PROTOCOL_TLSv1) #Optional Ciphers Spec Parameter Too
#Connect To The Host, Send Data And Wait To Recieve Data
encrypted_socket.connect((host_name,host_port))
encrypted_socket.send(b"Hello")
response = encrypted_socket.recv(512)
#Close The Connection
encrypted_socket.close()
main()
Note: I am using Python 3.6, and I think that a newer version of TLS is available to use as of Python 3.7.
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]
My working setup at the moment:
I have an app which consists of a python flask-socketio server and a react interface. The python server collects some data from a specific connected hardware and sends it through sockets to the react interface.
What i want to add:
Besides the actual functionalities, I also want to add a communication through sockets between the local python server and a remote node server. It is possible for local python server to act as a local server and a remote client?
What i have tried:
I tried to add code for a socketio client on the main script of python server.
here:
from flask_socketio import SocketIO
import socketio
socketio_server = SocketIO(app, async_mode='gevent', engineio_logger=False)
####PART OF THE CODE THAT I TRIED TO ADD THE COMMUNICATION AS A CLIENT###
##Connecting to server as a client
sio = socketio.Client() # !!! at this point i receive a new connection on remote server, however the code freezes on this line and the script hang on until the end of the connection
sio = socketio.Connect(host, port)
#i want to send data to a specific namespace
sio.emit('remote-client', {'foo':'bar'})
########################################################################
# Serve React App
#app.route('/', defaults={'path': ''})
#app.route('/<path:path>')
def serve(path):
if path != "" and os.path.exists("static" + path):
return send_from_directory('static', path)
else:
return send_from_directory('static', 'index.html')
#---------------------Web Sockets-----------------------------#
#socketio_server.on('connect', namespace='/test')
def test_connect():
print 'Client Connected'
#socketio_server.on('disconnect', namespace='/test')
def test_disconnect():
print 'Client disconnected'
if __name__ == '__main__':
print "Starting Server..."
socketio_server.run(app, debug=False)
os.kill(os.getpid(), signal.SIGTERM)
So, is this the right approach to achieve what I want? If it is, how can the python script act as a socketio server and client at the same time?
Regards,
Ricardo
EDIT: I Just realized that I am able to use ordinary sockets (import socket) along with socketio server. But if you have a better approach I will consider!