Created
August 9, 2013 15:34
-
-
Save nk0t/6194602 to your computer and use it in GitHub Desktop.
simple http server in python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import os.path | |
import socket | |
import threading | |
import subprocess | |
import locale | |
server_string = 'Server: httpy/1.0\r\n' | |
document_root = '' | |
index_page = '' | |
def headers(client): | |
client.send('HTTP/1.0 200 OK\r\n') | |
client.send(server_string) | |
client.send('Content-Type: text/html\r\n') | |
client.send('\r\n') | |
def not_found(client): | |
client.send('HTTP/1.0 404 NOT FOUND\r\n') | |
client.send(server_string) | |
client.send('Content-Type: text/html\r\n') | |
client.send('\r\n') | |
client.send('<HTML><TITLE>Not Found</TITLE>\r\n') | |
client.send('<BODY><P>The server could not fulfill\r\n') | |
client.send('your request because the resource specified\r\n') | |
client.send('is unavailable or nonexistent.\r\n') | |
client.send('</BODY></HTML>\r\n') | |
def bad_request(client): | |
client.send('HTTP/1.0 400 BAD REQUEST\r\n') | |
client.send('Content-type: text/html\r\n') | |
client.send('\r\n') | |
client.send('<P>Your browser sent a bad request, \r\n') | |
client.send('such as a POST without a Content-Length.\r\n') | |
def unimplemented(client, method): | |
client.send('HTTP/1.0 501 Method Not Implemented\r\n') | |
client.send(server_string) | |
client.send('Content-Type: text/html\r\n') | |
client.send('\r\n') | |
client.send('<HTML><HEAD><TITLE>Method Not Implemented\r\n') | |
client.send('</TITLE></HEAD>\r\n') | |
client.send('<BODY><P>HTTP request ') | |
client.send(method) | |
client.send(' method not supported.') | |
client.send('\r\n</BODY></HTML>\r\n') | |
def accept_request(client): | |
request = client.recv(1024) | |
if(len(request) == 0): | |
client.close() | |
return | |
http_request = request.split('\r\n')[0] | |
http_headers = request[len(http_request):] | |
http_method, request_url, _ = http_request.split(' ') | |
if (http_method != 'GET') and (http_method != 'POST'): | |
unimplemented(client, http_method) | |
client.close() | |
return | |
url = request_url.split('?')[0] | |
query_string = request_url[len(url) + 1:] | |
cgi = url[-4:] == '.exe' | |
path = document_root + url | |
if path[-1:] == '/': | |
path = path + index_page | |
if not os.path.exists(path): | |
not_found(client) | |
else: | |
if os.path.isdir(path): | |
path = path + '/' + index_page | |
if cgi: | |
execute_cgi(client, path, http_method, http_headers, query_string) | |
else: | |
serve_file(client, path) | |
client.close() | |
def serve_file(client, filename): | |
headers(client) | |
with open(filename, 'r') as f: | |
for line in f: | |
client.send(line) | |
def execute_cgi(client, path, method, http_headers, query_string): | |
content_length = -1 | |
env = os.environ.copy() | |
env['REQUEST_METHOD'] = method | |
if method == 'GET': | |
env['QUERY_STRING'] = query_string | |
client.send('HTTP/1.0 200 OK\r\n') | |
stdout, stderror = subprocess.Popen(args = [path,], stdout = subprocess.PIPE ,env = env).communicate() | |
client.send(stdout.rstrip()) | |
else: | |
for header in http_headers.split('\r\n'): | |
if header.split(':')[0] == 'Content-Length': | |
content_length = int(header.split(':')[1]) | |
if content_length == -1: | |
bad_request(client) | |
return | |
env['CONTENT_LENGTH'] = str(content_length) | |
content = http_headers[-content_length:] | |
client.send('HTTP/1.0 200 OK\r\n') | |
stdout, stderror = subprocess.Popen(args = [path,], stdout = subprocess.PIPE, stdin = subprocess.PIPE ,env = env).communicate(content) | |
client.send(stdout.rstrip()) | |
def load_config(): | |
global document_root | |
global index_page | |
current_directory = os.getcwd() | |
document_root = '{0}/htdocs'.format(current_directory) | |
index_page = 'index.html' | |
def server_main(): | |
load_config() | |
host = socket.gethostbyname('localhost') | |
port = 12345 | |
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | |
sock.bind((host, port)) | |
sock.listen(1) | |
print 'httpd running on port {0}'.format(port) | |
while True: | |
client, address = sock.accept() | |
thread = threading.Thread(target = accept_request, args = (client,)) | |
thread.start() | |
sock.close() | |
if __name__ == '__main__': | |
server_main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment