Skip to content
server.py 3.46 KiB
Newer Older
simeon's avatar
simeon committed
import http.server
import cgi
from urllib.parse import unquote, parse_qs
import re
import subprocess
simeon's avatar
simeon committed

PORT = 8000
URL_FORMAT = re.compile(
    r"^(?:(?:https://)?platform\.physik\.kit\.edu/codimd/)?(?P<id>[\w_-]+)([\?#].*)?$",
)

TMP_MD = "tmp.md"
TMP_PDF = "tmp.pdf"

def remove_if_exists(filename):
    if os.path.isfile(filename):
        os.remove(filename)
    return

def clean_up():
    remove_if_exists(TMP_MD)
    remove_if_exists(TMP_PDF)
    return
simeon's avatar
simeon committed

class CodiToPdfHandler(http.server.SimpleHTTPRequestHandler):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, directory="/app/html", **kwargs)
        return
simeon's avatar
simeon committed

    # forward get requests
    def do_GET(self):
        print(self.path)
        print(self.headers)
        super().do_GET()
        return

    def errored(self, msg):
        _msg = msg.encode("utf-8")

        self.send_response(400)
        self.send_header("Content-Type", "text/plain; charset=UTF-8")
        self.send_header("Content-Length", str(len(_msg)))
        self.end_headers()

        self.wfile.write(_msg)
        return

simeon's avatar
simeon committed
    def do_POST(self):
        try:
            content_length = int(self.headers["Content-Length"])
            _body = self.rfile.read(content_length)
            body = unquote(_body.decode("ASCII"))
            post_data = parse_qs(body)
            pad = post_data["pad"][0]
        except:
            self.errored("Invalid POST request!")
            return

        try:
            pad_id = URL_FORMAT.match(pad).group("id")
        except:
            self.errored("Invalid format for pad id!")
            return

        try:
            subprocess.check_call(["codimd", "export", "--md", pad_id, TMP_MD])
            assert os.path.isfile(TMP_MD)
        except Exception as e:
            if isinstance(e, subprocess.CalledProcessError):
                self.errored("Could not retrieve pad from address!")
            else:
                self.errored("Unknown error")
                print("Unknown error in codimd process:")
                print(e)

            remove_if_exists(TMP_MD)
            return

        try:
            subprocess.check_output(
                [
                    "pandoc",
                    # disable yaml in markdown
                    "-t", "latex-yaml_metadata_block",
                    # limit to 64MiB memory
                    "+RTS", "-M64M", "-RTS",
                    # use a4 paper
                    "-s", "-V", "papersize:a4",
simeon's avatar
simeon committed
                    "-V", "geometry:margin=1in",
                    TMP_MD,
                ],
                stderr=subprocess.STDOUT,
            )
            assert os.path.isfile(TMP_PDF)
        except Exception as e:
            if isinstance(e, subprocess.CalledProcessError):
                self.errored(
                    "Error occured while converting markdown to pdf:\n\n" +
                    e.output.decode("utf-8"),
                )
            else:
                self.errored("Unknown error")
            clean_up()
            return
simeon's avatar
simeon committed

        self.send_response(200)
        self.send_header("Content-Type", "application/pdf")
        #self.send_header("Content-Length", str(len(pdf)))
simeon's avatar
simeon committed
        self.end_headers()

        with open(TMP_PDF, "rb") as pdf_file:
            self.copyfile(pdf_file, self.wfile)
        clean_up()

        #self.wfile.write(pdf)
simeon's avatar
simeon committed
        return

simeon's avatar
simeon committed
with http.server.ThreadingHTTPServer(("", PORT), CodiToPdfHandler) as httpd:
simeon's avatar
simeon committed
    httpd.serve_forever()