Skip to content

Instantly share code, notes, and snippets.

@vgel
Created July 9, 2012 14:16
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save vgel/3076825 to your computer and use it in GitHub Desktop.
Save vgel/3076825 to your computer and use it in GitHub Desktop.
A very basic HTTP file server in 13 lines of python. Assumes all requests are GETs, and it vulnerable to directory traversal (Run it in ~ and localhost:8080/../../ will ls root), so don't use it online. Will correctly list files in directories.
import sys, os, socket
s = socket.socket()
s.bind((sys.argv[1], int(sys.argv[2])))
s.listen(5)
try:
while True:
conn, addr = s.accept()
path = os.path.join(os.getcwd(), "./"+conn.recv(4096).split("\n")[0].split(" ")[1])
conn.send((open(path).read() if os.path.isfile(path) else reduce(lambda x,s:x+"\n"+s+("/" if os.path.isdir(s) else ""),sorted(os.listdir(path)),"Directory "+path+" ls")) if os.path.exists(path) else '404: '+path)
conn.close()
finally:
s.close()
#!/bin/env python
#pretty version
import sys, os, socket
s = socket.socket() #set up out socket
s.bind((sys.argv[1], int(sys.argv[2]))) #bind (I usually pass in localhost 8080, you will need root for a port < 1000)
s.listen(5) #start listening, drop all connection if we have > 5 waiting connections
try:
while True: #listen loop
conn, addr = s.accept() #block for a connection
request = conn.recv(4096) #read up to 4 kb, I figure no get request should be more than this
first_line = request.split("\n")[0] #get the GET <path> HTTP/1.1 line, this should be "\r\n" but it doesn't make a difference for this
requested_file = first_line.split(" ")[1] #the the <path> part
path = os.path.join(os.getcwd(), "./" + requested_file) #join to current directory. THIS DOES NOT PROTECT AGAINST DIRECTORY TRAVERSAL!!
if os.path.exists(path): #checks to see is we have a file, obviously
if os.path.isfile(path):
conn.send(open(path).read()) #read that file. Seems to fail on very large files.
else:
conn.send("Directory " + path + " ls\n") #send the header
for p in sorted(os.listdir(path)): #sort, does not put directories first like most file servers
if os.path.isdir(p):
conn.send(p + "/\n") #append a forward slash
else:
conn.send(p + "\n")
else:
conn.send("404: " + path) #meh
conn.close() #we're done here
finally:
s.close() #close the socket, freeing the port so we can relaunch on it
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment