diff --git a/generate_html.py b/generate_html.py
new file mode 100644
index 0000000..7d14364
--- /dev/null
+++ b/generate_html.py
@@ -0,0 +1,97 @@
+import urllib.parse
+
+import bs4
+
+# generate_nav(*, soup) → nav_tag
+def generate_nav(*, soup):
+ # TODO: Don't generate link to a board if we're at the index
+ nav_tag = soup.new_tag('nav')
+
+ for board in ['a', 'b', 'his', 'g']:
+ url = '/' + urllib.parse.quote(board, safe = '') + '/'
+ a_tag = soup.new_tag('a', href = url)
+ a_tag.string = '/' + board + '/'
+ nav_tag.append(a_tag)
+
+ return nav_tag
+
+# generate_header(*, page_title, soup) → header_tag
+def generate_header(*, page_title, soup):
+ header_tag = soup.new_tag('header')
+
+ h1_tag = soup.new_tag('h1')
+ h1_tag.string = page_title
+ header_tag.append(h1_tag)
+
+ return header_tag
+
+# generate_footer(*, soup) → footer_tag
+def generate_footer(*, soup):
+ # TODO: Add footer generation
+ return soup.new_tag('footer')
+
+# page_skeleton(*, page_title, contents, soup) → html
+# Given page title (string) and contents (iteratable of beautifulsoup tags), create the html
+# Since most pages have same basic structure, it makes sense to factor this out from page creation functions
+def page_skeleton(*, page_title, contents, soup):
+ # Doctype and head are more or less the same for each page, no need to do anything fancy when adding them
+ soup.append(bs4.Doctype('html'))
+
+ head_tag = soup.new_tag('head')
+ title_tag = soup.new_tag('title')
+ title_tag.string = page_title
+ head_tag.append(title_tag)
+ soup.append(head_tag)
+
+ # Body consists of (more or less same) header and footer, and varying content
+ body_tag = soup.new_tag('body')
+
+ body_tag.append(generate_nav(soup = soup))
+ body_tag.append(generate_header(page_title = page_title, soup = soup))
+
+ # contents is an iterable that can contain several tags
+ for tag in contents:
+ body_tag.append(tag)
+
+ body_tag.append(generate_footer(soup = soup))
+
+ soup.append(body_tag)
+
+ # Use .prettify() to generate nice-looking HTML
+ # We are probably never going to serve enough pages for the additional whitespace to count for data usage
+ return soup.prettify()
+
+# new_soup() → soup
+# Since we need a soup object to create tags, split this from page_skeleton
+def new_soup():
+ # Use python's built-in parser for portability
+ # We'll be constructing the document programmatically, so start with empty tree
+ soup = bs4.BeautifulSoup('', 'html.parser')
+
+ return soup
+
+# board() → html
+# Creates the board index page
+def board(board_name):
+ # TODO: Creae a board index page
+ soup = new_soup()
+
+ page_title = '/' + board_name + '/'
+
+ return page_skeleton(page_title = page_title, contents = [], soup = soup)
+
+# index() → html
+# Create the site index
+def index():
+ # TODO: Create an index page
+ soup = new_soup()
+ return page_skeleton(page_title = 'Buranun', contents = [], soup = soup)
+
+# error_404(path) → html
+def error_404(path):
+ soup = new_soup()
+
+ p_tag = soup.new_tag('p')
+ p_tag.string = path + ' does not exist'
+
+ return page_skeleton(page_title = '404 Not Found', contents = [p_tag], soup = soup)
diff --git a/server.py b/server.py
index a7dc25f..56d90a2 100644
--- a/server.py
+++ b/server.py
@@ -1,27 +1,46 @@
import http.server
import urllib.parse
+import generate_html
+
class HTTPRequestHandler(http.server.BaseHTTPRequestHandler):
server_version = 'Buranun/0.0'
protocol_version = 'HTTP/1.1'
- def __send_plaintext(self, string):
- if string[-1:] != '\n':
- string += '\n'
-
- encoded = string.encode('utf-8')
+ def __send_html(self, html, *, status_code = 200):
+ encoded = html.encode('utf-8')
length = len(encoded)
- self.send_response(200)
- self.send_header('Content-Type', 'text/plain; charset=utf-8')
+ self.send_response(status_code)
+ self.send_header('Content-Type', 'text/html; charset=utf-8')
self.send_header('Content-Length', length)
self.end_headers()
self.wfile.write(encoded)
+ def __send_404(self, path):
+ html = generate_html.error_404(path)
+ self.__send_html(html, status_code = 404)
+
def do_GET(self):
path = urllib.parse.unquote(self.path)
- self.__send_plaintext(path)
+
+ path_components = [component for component in path.split('/') if component != '']
+
+ if len(path_components) == 0:
+ # Path of format / → index
+ html = generate_html.index()
+ self.__send_html(html)
+
+ elif len(path_components) == 1:
+ # Path of format /foo/ → board index
+ board_name = path_components[0]
+ html = generate_html.board(board_name)
+ self.__send_html(html)
+
+ else:
+ # Path not understood, send 404
+ self.__send_404(path)
def main():
httpd = http.server.HTTPServer(('', 8000), HTTPRequestHandler)