I am trying to make a BaseHTTPServer program. I prefer to use Python 3.3 or 3.2 for it. I find the doc hard to understand regarding what to import but tried changing the import from:
from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
to:
from http.server import BaseHTTPRequestHandler,HTTPServer
and then the import works and the program start and awaits a GET request. BUT when the request arrives an exception is raised:
File "C:\Python33\lib\socket.py", line 317, in write return self._sock.send(b)
TypeError: 'str' does not support the buffer interface
Question: Is there a version of BaseHTTPServer or http.server that works out of the box with Python3.x or am I doing something wrong?
This is "my" program that I try running in Python 3.3 and 3.2:
#!/usr/bin/python
# from BaseHTTPServer import BaseHTTPRequestHandler,HTTPServer
from http.server import BaseHTTPRequestHandler,HTTPServer
PORT_NUMBER = 8080
# This class will handle any incoming request from
# a browser
class myHandler(BaseHTTPRequestHandler):
# Handler for the GET requests
def do_GET(self):
print ('Get request received')
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
# Send the html message
self.wfile.write("Hello World !")
return
try:
# Create a web server and define the handler to manage the
# incoming request
server = HTTPServer(('', PORT_NUMBER), myHandler)
print ('Started httpserver on port ' , PORT_NUMBER)
# Wait forever for incoming http requests
server.serve_forever()
except KeyboardInterrupt:
print ('^C received, shutting down the web server')
server.socket.close()
The Program work partly in Python2.7 but gives this exception after 2-8 requests:
error: [Errno 10054] An existing connection was forcibly closed by the remote host
Your program in python 3.xx does work right out of the box - except for one minor problem. The issue is not in your code but the place where you are writing these lines:
self.wfile.write("Hello World !")
You are trying to write "string" in there, but bytes should go there. So you need to convert your string to bytes.
Here, see my code, which is almost same as you and works perfectly. Its written in python 3.4
from http.server import BaseHTTPRequestHandler, HTTPServer
import time
hostName = "localhost"
hostPort = 9000
class MyServer(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>Title goes here.</title></head>", "utf-8"))
self.wfile.write(bytes("<body><p>This is a test.</p>", "utf-8"))
self.wfile.write(bytes("<p>You accessed path: %s</p>" % self.path, "utf-8"))
self.wfile.write(bytes("</body></html>", "utf-8"))
myServer = HTTPServer((hostName, hostPort), MyServer)
print(time.asctime(), "Server Starts - %s:%s" % (hostName, hostPort))
try:
myServer.serve_forever()
except KeyboardInterrupt:
pass
myServer.server_close()
print(time.asctime(), "Server Stops - %s:%s" % (hostName, hostPort))
Please notice the way I convert them from string to bytes using the "UTF-8" encoding. Once you do this change in your program, your program should work fine.
You can just do like that:
self.send_header('Content-type','text/html'.encode())
self.end_headers()
# Send the html message
self.wfile.write("Hello World !".encode())
Whoever did the python 3 documentation for http.server failed to note the change. The 2.7 documentation states right at the top "Note The BaseHTTPServer module has been merged into http.server in Python 3. The 2to3 tool will automatically adapt imports when converting your sources to Python 3."
You should change wfile argument, because in Python 3 it accept bytes like objects, therefore convert your string to bytes by:
self.wfile.write(b"<h1> Hello </h1>)
Or
self.wfile.write( bytes("<h1> Hello </h1>) )