Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
a minimal http server in python. Responds to GET, HEAD, POST requests, but will fail on anything else.
#!/usr/bin/env python
"""
Very simple HTTP server in python.
Usage::
./dummy-web-server.py [<port>]
Send a GET request::
curl http://localhost
Send a HEAD request::
curl -I http://localhost
Send a POST request::
curl -d "foo=bar&bin=baz" http://localhost
"""
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import SocketServer
class S(BaseHTTPRequestHandler):
def _set_headers(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
def do_GET(self):
self._set_headers()
self.wfile.write("<html><body><h1>hi!</h1></body></html>")
def do_HEAD(self):
self._set_headers()
def do_POST(self):
# Doesn't do anything with posted data
self._set_headers()
self.wfile.write("<html><body><h1>POST!</h1></body></html>")
def run(server_class=HTTPServer, handler_class=S, port=80):
server_address = ('', port)
httpd = server_class(server_address, handler_class)
print 'Starting httpd...'
httpd.serve_forever()
if __name__ == "__main__":
from sys import argv
if len(argv) == 2:
run(port=int(argv[1]))
else:
run()
@mhchia

This comment has been minimized.

Show comment Hide comment
@mhchia

mhchia Jun 24, 2016

Is import SocketServer unneeded ?!

mhchia commented Jun 24, 2016

Is import SocketServer unneeded ?!

@dneyirp

This comment has been minimized.

Show comment Hide comment
@dneyirp

dneyirp Aug 8, 2016

No import SocketServer is not needed and can be removed.

dneyirp commented Aug 8, 2016

No import SocketServer is not needed and can be removed.

@dneyirp

This comment has been minimized.

Show comment Hide comment
@dneyirp

dneyirp Aug 8, 2016

Nice project.

Just one thing to add to it, if you want access to the POSTed data you do so like this:

def do_POST(self):
        # Doesn't do anything with posted data
        content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
        post_data = self.rfile.read(content_length) # <--- Gets the data itself
        self._set_headers()
        self.wfile.write("<html><body><h1>POST!</h1></body></html>")

dneyirp commented Aug 8, 2016

Nice project.

Just one thing to add to it, if you want access to the POSTed data you do so like this:

def do_POST(self):
        # Doesn't do anything with posted data
        content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
        post_data = self.rfile.read(content_length) # <--- Gets the data itself
        self._set_headers()
        self.wfile.write("<html><body><h1>POST!</h1></body></html>")
@qianguozheng

This comment has been minimized.

Show comment Hide comment
@qianguozheng

qianguozheng Aug 26, 2016

Great job, this it what I finding, print the post data

Great job, this it what I finding, print the post data

@arvindsree

This comment has been minimized.

Show comment Hide comment
@arvindsree

arvindsree Nov 21, 2016

Nice

Nice

@scorpiodawg

This comment has been minimized.

Show comment Hide comment
@scorpiodawg

scorpiodawg Dec 6, 2016

Oh, and to print the POSTed data:

    def do_POST(self):
        # Doesn't do anything with posted data
        content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
        post_data = self.rfile.read(content_length) # <--- Gets the data itself
        self._set_headers()
        self.wfile.write("<html><body><h1>POST!</h1><pre>" + post_data + "</pre></body></html>")

Oh, and to print the POSTed data:

    def do_POST(self):
        # Doesn't do anything with posted data
        content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
        post_data = self.rfile.read(content_length) # <--- Gets the data itself
        self._set_headers()
        self.wfile.write("<html><body><h1>POST!</h1><pre>" + post_data + "</pre></body></html>")
@pincioc

This comment has been minimized.

Show comment Hide comment
@pincioc

pincioc Jan 6, 2017

def do_POST(self):
    # Doesn't do anything with posted data
    content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
    post_data = self.rfile.read(content_length) # <--- Gets the data itself
    print post_data # <-- Print post data
    self._set_headers()

pincioc commented Jan 6, 2017

def do_POST(self):
    # Doesn't do anything with posted data
    content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
    post_data = self.rfile.read(content_length) # <--- Gets the data itself
    print post_data # <-- Print post data
    self._set_headers()
@ml693

This comment has been minimized.

Show comment Hide comment
@ml693

ml693 Feb 4, 2017

Nice, I would welcome very much if someone could answer the following:

suppose I post .txt file to this server. How to make server save this file in its local directory?
What's the extra code inside do_POST(self) for that?

ml693 commented Feb 4, 2017

Nice, I would welcome very much if someone could answer the following:

suppose I post .txt file to this server. How to make server save this file in its local directory?
What's the extra code inside do_POST(self) for that?

@tarvos21

This comment has been minimized.

Show comment Hide comment
@tarvos21

tarvos21 Mar 15, 2017

Great script, thanks! Is there a Python3 version?

tarvos21 commented Mar 15, 2017

Great script, thanks! Is there a Python3 version?

@derdigge

This comment has been minimized.

Show comment Hide comment
@derdigge

derdigge Apr 12, 2017

@tarvos21:

just stumbled in here by google result. That one works 4 me in python3

#!/usr/bin/python3

import socket
from http.server import BaseHTTPRequestHandler, HTTPServer
import time

hostName = ""
hostPort = 80

class MyServer(BaseHTTPRequestHandler):

	#	GET is for clients geting the predi
	def do_GET(self):
		self.send_response(200)
		self.wfile.write(bytes("<p>You accessed path: %s</p>" % self.path, "utf-8"))

	#	POST is for submitting data.
	def do_POST(self):

		print( "incomming http: ", self.path )

		content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
		post_data = self.rfile.read(content_length) # <--- Gets the data itself
		self.send_response(200)

		client.close()

		#import pdb; pdb.set_trace()


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))```

derdigge commented Apr 12, 2017

@tarvos21:

just stumbled in here by google result. That one works 4 me in python3

#!/usr/bin/python3

import socket
from http.server import BaseHTTPRequestHandler, HTTPServer
import time

hostName = ""
hostPort = 80

class MyServer(BaseHTTPRequestHandler):

	#	GET is for clients geting the predi
	def do_GET(self):
		self.send_response(200)
		self.wfile.write(bytes("<p>You accessed path: %s</p>" % self.path, "utf-8"))

	#	POST is for submitting data.
	def do_POST(self):

		print( "incomming http: ", self.path )

		content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
		post_data = self.rfile.read(content_length) # <--- Gets the data itself
		self.send_response(200)

		client.close()

		#import pdb; pdb.set_trace()


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))```
@vmrekhate

This comment has been minimized.

Show comment Hide comment
@vmrekhate

vmrekhate Apr 21, 2017

Any help to make this work for HTTPS as well?
I explored SSL and wrote some sample code using the examples here: SSL Python3 docs. I can capture the data in connstream, but still not sure how to handle the path in GET/POST requests.

Any help to make this work for HTTPS as well?
I explored SSL and wrote some sample code using the examples here: SSL Python3 docs. I can capture the data in connstream, but still not sure how to handle the path in GET/POST requests.

@parijatmukherjee

This comment has been minimized.

Show comment Hide comment
@parijatmukherjee

parijatmukherjee May 30, 2017

Thanks a lot. Saved my couple of hours :)

Thanks a lot. Saved my couple of hours :)

@tkavitharaj

This comment has been minimized.

Show comment Hide comment
@tkavitharaj

tkavitharaj Jun 25, 2017

Thanks for the code.
is there a way i can send chunked data using this code.
i want to send data of different chunk sizes.

Thanks for the code.
is there a way i can send chunked data using this code.
i want to send data of different chunk sizes.

@AnnaPanov

This comment has been minimized.

Show comment Hide comment
@AnnaPanov

AnnaPanov Jul 28, 2017

to make it work in python 3, the imports should be:

from http.server import BaseHTTPRequestHandler, HTTPServer

, and do_GET + do_POST change into:

def do_GET(self):
    self._set_headers()
    self.wfile.write("got".encode("utf-8"))

def do_POST(self):
    # Doesn't do anything with posted data
    self._set_headers()
    self.wfile.write("posted".encode("utf-8")) `

AnnaPanov commented Jul 28, 2017

to make it work in python 3, the imports should be:

from http.server import BaseHTTPRequestHandler, HTTPServer

, and do_GET + do_POST change into:

def do_GET(self):
    self._set_headers()
    self.wfile.write("got".encode("utf-8"))

def do_POST(self):
    # Doesn't do anything with posted data
    self._set_headers()
    self.wfile.write("posted".encode("utf-8")) `
@bmcculley

This comment has been minimized.

Show comment Hide comment
@bmcculley

bmcculley Aug 16, 2017

my forked version works on both python 2 and 3

my forked version works on both python 2 and 3

@hgfeaon

This comment has been minimized.

Show comment Hide comment
@hgfeaon

hgfeaon Aug 30, 2017

useful for debugging the HTTP client & proxy on a raw machine

hgfeaon commented Aug 30, 2017

useful for debugging the HTTP client & proxy on a raw machine

@f41ardu

This comment has been minimized.

Show comment Hide comment
@f41ardu

f41ardu Sep 8, 2017

Nice script following the KISS principle. But I tried to process incoming data using i.e. matplotlib and this still didn't work.
What is the best strategy to pass incoming post data into other functions/processes?
Solved, I'll post my code as soon as possible.

Update: Code works fine on my Raspberry but not on my Windows 8.1 PC.

f41ardu commented Sep 8, 2017

Nice script following the KISS principle. But I tried to process incoming data using i.e. matplotlib and this still didn't work.
What is the best strategy to pass incoming post data into other functions/processes?
Solved, I'll post my code as soon as possible.

Update: Code works fine on my Raspberry but not on my Windows 8.1 PC.

@j796160836

This comment has been minimized.

Show comment Hide comment
@j796160836

j796160836 Sep 26, 2017

Nice script! That is exactly what I want. Thanks.

Nice script! That is exactly what I want. Thanks.

@TheNilesh

This comment has been minimized.

Show comment Hide comment
@TheNilesh

TheNilesh Oct 9, 2017

How to return headers and http response code in response ?

How to return headers and http response code in response ?

@psankar

This comment has been minimized.

Show comment Hide comment
@psankar

psankar Oct 12, 2017

@6f0 Your link is broken.

psankar commented Oct 12, 2017

@6f0 Your link is broken.

@soulfly

This comment has been minimized.

Show comment Hide comment
@soulfly

soulfly Oct 23, 2017

This is actually awesome, thank you!

soulfly commented Oct 23, 2017

This is actually awesome, thank you!

@ArrrNeo

This comment has been minimized.

Show comment Hide comment
@ArrrNeo

ArrrNeo Nov 27, 2017

this is exactly what I needed... i was able to complete a home project of mine with this, thanks :)

ArrrNeo commented Nov 27, 2017

this is exactly what I needed... i was able to complete a home project of mine with this, thanks :)

@lily524

This comment has been minimized.

Show comment Hide comment
@lily524

lily524 Nov 28, 2017

both python 2 and 3 works for me. Many thanks.

lily524 commented Nov 28, 2017

both python 2 and 3 works for me. Many thanks.

@pspangler

This comment has been minimized.

Show comment Hide comment
@pspangler

pspangler Dec 3, 2017

Great simple utility here. Very helpful!

Great simple utility here. Very helpful!

@HelloTan

This comment has been minimized.

Show comment Hide comment
@HelloTan

HelloTan Dec 31, 2017

self.__http_response = self.__http.getresponse()

self.__http_response = self.__http.getresponse()

AttributeError: HTTPS instance has no attribute 'getresponse'

How to fix python2.7?? in thttpclient.py

self.__http_response = self.__http.getresponse()

self.__http_response = self.__http.getresponse()

AttributeError: HTTPS instance has no attribute 'getresponse'

How to fix python2.7?? in thttpclient.py

@lukapaunovic

This comment has been minimized.

Show comment Hide comment
@lukapaunovic

lukapaunovic Jan 14, 2018

This is USEFUL! :)

This is USEFUL! :)

@reillychase

This comment has been minimized.

Show comment Hide comment
@reillychase

reillychase Apr 20, 2018

HTTPS support?

HTTPS support?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment