Skip to content

Instantly share code, notes, and snippets.

@meganehouser
Created April 14, 2015 00:23
Show Gist options
  • Save meganehouser/271852d192e64c9e688e to your computer and use it in GitHub Desktop.
Save meganehouser/271852d192e64c9e688e to your computer and use it in GitHub Desktop.
Simple Markdown Server inherited from SimpleHTTPRequestHandler. When '.md' is opening, the parsed html opens.
"""
usage: mdiew.py [-h] [--bind ADDRESS] [--file FILE] [--open] [port]
positional arguments:
port Specify alternate port [default: 8000]
optional arguments:
-h, --help show this help message and exit
--bind ADDRESS, -b ADDRESS
Specify alternate bind address [default: loopback
address]
--file FILE, -f FILE Specify markdown file [default: none]
--open, -o Specify whether to open the browser [default: False]
requirements: markdwon
"""
from http.client import HTTPConnection
from http.server import SimpleHTTPRequestHandler, test
from io import BytesIO
import os
import urllib
import threading
import webbrowser
import time
import argparse
import markdown
class MDiewRequestHandler(SimpleHTTPRequestHandler):
def send_head(self):
path = self.translate_path(self.path)
f = None
if os.path.isdir(path):
parts = urllib.parse.urlsplit(self.path)
if not parts.path.endswith('/'):
# redirect browser - doing basically what apache does
self.send_response(301)
new_parts = (parts[0], parts[1], parts[2] + '/',
parts[3], parts[4])
new_url = urllib.parse.urlunsplit(new_parts)
self.send_header("Location", new_url)
self.end_headers()
return None
for index in "index.html", "index.htm":
index = os.path.join(path, index)
if os.path.exists(index):
path = index
break
else:
return self.list_directory(path)
ctype = self.guess_type(path)
try:
if self.path.endswith('.md'):
ctype = 'text/html'
f = open(path, 'rt', encoding='utf-8-sig')
fs = os.fstat(f.fileno())
md = markdown.markdown(f.read(), extensions=['markdown.extensions.extra'])
bs = md.encode()
length = len(bs)
f = BytesIO(bs)
else:
f = open(path, 'rb')
fs = os.fstat(f.fileno())
length = str(fs[6])
except OSError:
self.send_error(404, "File not found")
return None
try:
self.send_response(200)
self.send_header("Content-type", ctype)
self.send_header("Content-Length", length)
self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
self.end_headers()
return f
except:
f.close()
raise
def boot(bind, port, filepath):
while True:
try:
con = HTTPConnection(bind, port)
con.request('HEAD', '/')
res = con.getresponse()
if res.status == 200:
webbrowser.open('http://{}:{}/{}'.format(bind, port, filepath))
break
else:
time.sleep(1)
except ConnectionRefusedError:
pass
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('--bind', '-b', default='127.0.0.1', metavar='ADDRESS',
help='Specify alternate bind address '
'[default: loopback address]')
parser.add_argument('port', action='store', default=8000, type=int,
nargs='?',
help='Specify alternate port [default: 8000]')
parser.add_argument('--file', '-f', default='', metavar='FILE',
help='Specify markdown file [default: none]')
parser.add_argument('--open', '-o', action='store_true', default=False,
help='Specify whether to open the browser [default: False]')
args = parser.parse_args()
handler = MDiewRequestHandler
if args.open:
threading.Thread(target=boot, daemon=True, args=(args.bind, args.port, args.file)).start()
test(HandlerClass=handler, port=args.port, bind=args.bind)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment