Created
April 14, 2015 00:23
-
-
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.
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
""" | |
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