15

I found here a (apparently-)working HTTPS server for python 2: http://code.activestate.com/recipes/442473-simple-http-server-supporting-ssl-secure-communica/?c=15536

I'm trying to port it in python3 but I have no good results. This is my code:

from socketserver import BaseServer
import string,cgi,time
from os import curdir, sep
from http.server import SimpleHTTPRequestHandler, HTTPServer
import ssl
import os # os. path
import socket

class SecureHTTPServer(HTTPServer):
    def __init__(self, server_address, HandlerClass):
        BaseServer.__init__(self, server_address, HandlerClass)
        ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
        #server.pem's location (containing the server private key and
        #the server certificate).
        fpem = 'certificate1.pem'
        ctx.load_verify_locations(fpem)
        self.socket = ctx.wrap_socket(socket.socket(self.address_family,
                                                        self.socket_type))
        self.server_bind()
        self.server_activate()


class SecureHTTPRequestHandler(SimpleHTTPRequestHandler):
    def setup(self):
        self.connection = self.request
        self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
        self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
    def do_GET(self):
        print('get recieved!');
        self.send_error(404,'File Not Found: %s' % self.path)

def test(HandlerClass = SecureHTTPRequestHandler,
         ServerClass = SecureHTTPServer):
    server_address = ('', 1443) # (address, port)
    httpd = ServerClass(server_address, HandlerClass)
    sa = httpd.socket.getsockname()
    print ("Serving HTTPS on", sa[0], "port", sa[1], "...")
    httpd.serve_forever()


if __name__ == '__main__':
    test()

When I run it I get no errors, but when I connect to localhost:1443 (with https) I get no response and the print('get recieved!'); is't triggered.

2 Answers 2

18

I found another (simpler) solution here: http://www.piware.de/2011/01/creating-an-https-server-in-python/

This is my working porting to python3:

from http.server import HTTPServer,SimpleHTTPRequestHandler
from socketserver import BaseServer
import ssl

httpd = HTTPServer(('localhost', 1443), SimpleHTTPRequestHandler)
httpd.socket = ssl.wrap_socket (httpd.socket, certfile='certificate.pem', server_side=True)
httpd.serve_forever()
Sign up to request clarification or add additional context in comments.

2 Comments

I don't think you need BaseServer here.
Thanks, this mostly worked for my but I had to add the parameter for my private key (keyfile='private.pem') in the wrap_socket call.
16

Since Python 3.7 ssl.wrap_socket is deprecated, use SSLContext.wrap_socket instead:

check: https://docs.python.org/3.7/library/ssl.html#ssl.wrap_socket

and since version 3.10: SSLContext without protocol argument is deprecated.

check: https://docs.python.org/3.10/library/ssl.html#ssl.SSLContext

from http.server import HTTPServer,SimpleHTTPRequestHandler
import ssl

httpd = HTTPServer(('localhost', 1443), SimpleHTTPRequestHandler)
# Since version 3.10: SSLContext without protocol argument is deprecated. 
# sslctx = ssl.SSLContext()
sslctx = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
sslctx.check_hostname = False # If set to True, only the hostname that matches the certificate will be accepted
sslctx.load_cert_chain(certfile='certificate.pem', keyfile="private.pem")
httpd.socket = sslctx.wrap_socket(httpd.socket, server_side=True)
httpd.serve_forever()

2 Comments

Thanks! With your code now we can use sslcontext. A simple fix: ssl_ctx.wrap_sockert -> sslctx.wrapsocket
ssl.SSLContext() is now also deprecated. Use ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) instead

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.