diff --git a/README.md b/README.md
index d6888ed1..6a2526ac 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,4 @@
-CMPUT404-assignment-webserver
-=============================
+# CMPUT404-assignment-webserver
CMPUT404-assignment-webserver
@@ -7,20 +6,49 @@ See requirements.org (plain-text) for a description of the project.
Make a simple webserver.
-Contributors / Licensing
-========================
+# Contributors / Licensing
Generally everything is LICENSE'D under the Apache 2 license by Abram Hindle.
server.py contains contributions from:
-* Abram Hindle
-* Eddie Antonio Santos
-* Jackson Z Chang
-* Mandy Meindersma
+- Abram Hindle
+- Eddie Antonio Santos
+- Jackson Z Chang
+- Mandy Meindersma
+- Ferdous Adit
But the server.py example is derived from the python documentation
-examples thus some of the code is Copyright © 2001-2013 Python
+examples thus some of the code is Copyright © 2001-2023 Python
Software Foundation; All Rights Reserved under the PSF license (GPL
compatible) http://docs.python.org/2/library/socketserver.html
+- root.png
+- deep.png
+
+Screenshots are derivative works and as such subject to the copyright of
+the displayed content, may it be a video, television program, or a computer
+program. Thus, screenshots must not be uploaded to Wikimedia Commons unless
+all content in them is under a https://en.wikipedia.org/wiki/Free_license or
+in the public domain.
+
+# Credit or References
+
+- BogoToBogo
+https://www.bogotobogo.com/python/python_network_programming_socketserver_framework_for_network_servers.php
+Network Programming III - SocketServer
+
+- Tech With Tim
+https://www.youtube.com/@TechWithTim
+Python Socket Programming Tutorial
+https://youtu.be/3QiPPX-KeSc
+Youtube
+
+- jbx
+https://stackoverflow.com/users/340088/jbx
+https://stackoverflow.com/a/53070496
+Stackoverflow
+
+- PyMOTW
+http://pymotw.com/2/SocketServer/
+SocketServer – Creating network servers
diff --git a/deep.png b/deep.png
new file mode 100644
index 00000000..6366ad69
Binary files /dev/null and b/deep.png differ
diff --git a/root.png b/root.png
new file mode 100644
index 00000000..c9801750
Binary files /dev/null and b/root.png differ
diff --git a/server.py b/server.py
index bc5a725c..d7ce49b9 100644
--- a/server.py
+++ b/server.py
@@ -1,14 +1,17 @@
-# coding: utf-8
+# coding: utf-8
import socketserver
+import os
-# Copyright 2013 Abram Hindle, Eddie Antonio Santos
-#
+# Copyright 2023 Abram Hindle, Eddie Antonio Santos
+#
+# Updated by Ferdous Adit, 1538839.
+#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
-#
+#
# http://www.apache.org/licenses/LICENSE-2.0
-#
+#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -17,7 +20,7 @@
#
#
# Furthermore it is derived from the Python documentation examples thus
-# some of the code is Copyright © 2001-2013 Python Software
+# some of the code is Copyright © 2001-2023 Python Software
# Foundation; All Rights Reserved
#
# http://docs.python.org/2/library/socketserver.html
@@ -28,11 +31,177 @@
class MyWebServer(socketserver.BaseRequestHandler):
-
+ extension_code = {
+ 'NOTHING': None,
+ 'INDEX_PAGE': 'index.html',
+ 'NOT_FOUND': '404'
+ }
+ SPACE = '\r\n'
+ END = '\r\n\r\n'
+ NOT_OKAY = -1
+ OKAY = 1
+
def handle(self):
self.data = self.request.recv(1024).strip()
- print ("Got a request of: %s\n" % self.data)
- self.request.sendall(bytearray("OK",'utf-8'))
+ print("Got a request of: %s\n" % self.data)
+
+ # Now that we have the response. We need to parse it. parse_request
+ # already decodes the data.
+ request_is_good = self.parse_request(self.data)
+
+ if request_is_good == self.NOT_OKAY: # handling any POST/PUT/DELETE request
+ self.request.sendall(bytearray(
+ f"HTTP/1.1 405 METHOD NOT ALLOWED{self.SPACE}Content-Type: 'text/html'{self.SPACE}Content-Length: 42{self.SPACE} encoding=utf-8{self.END}405 METHOD NOT ALLOWED", 'utf-8'))
+ return
+
+ elif self.extension == 'index.html': # directed to default index.html
+ self.serve_default_index()
+ return
+
+ elif self.extension == 'deep_index.html':
+ self.serve_deep_index()
+ return
+
+ elif self.extension == 'base.css':
+ self.serve_default_css()
+ return
+
+ elif self.extension == 'hardcode_index.html':
+ self.serve_hardcode_index()
+ return
+
+ elif self.extension == 'hardcode_deep_index.html':
+ self.serve_hardcode_deep_index()
+ return
+
+ elif self.parse_redirect() == 1:
+ self.serve_redirect(1)
+ return
+
+ elif self.extension == '404':
+ self.request.sendall(bytearray(
+ f"HTTP/1.1 404 NOT FOUND\r\ncontent-Type: text/html; encoding=utf-8\r\n\r\nThis works!", 'utf-8'))
+ return
+
+ def parse_request(self, data):
+ self.data = data.decode('utf-8')
+ # Is the message anything other than GET?
+ if self.data[:3] != 'GET':
+ return -1
+
+ self.extension = ''
+ # If root or directly requesting index.html
+ if self.parse_request_default_html():
+ self.extension = 'index.html'
+ elif self.parse_request_deep_html():
+ self.extension = 'deep_index.html'
+ elif self.parse_request_default_css():
+ self.extension = 'base.css'
+ elif self.parse_request_hardcode_html():
+ self.extension = 'hardcode_index.html'
+ elif self.parse_request_hardcode_deep_html():
+ self.extension = 'hardcode_deep_index.html'
+
+ # elif self.data[]
+
+ else: # request is okay but cannot find the extension requested.
+ self.extension = '404'
+ return 1
+
+ """
+ Parse the request path methods. ---------------------------------
+ """
+
+ def parse_request_default_html(self):
+ if self.data[4:6] == '/ ' \
+ or self.data[4:17] == '/index.html/ ' \
+ or self.data[4:16] == '/index.html ':
+ return True
+ return False
+
+ def parse_request_deep_html(self):
+ end = self.data.find("HTTP")
+ if self.data[4:end] == '/deep/ ' \
+ or self.data[4:end] == '/deep/index.html '\
+ or self.data[4:end] == '/deep/index.html/ ':
+ return True
+ return False
+
+ def parse_request_hardcode_html(self):
+ end = self.data.find("HTTP")
+ end = end - 1
+ if self.data[4:end] == '/hardcode/'\
+ or self.data[4:end] == '/hardcode/index.html'\
+ or self.data[4:end] == '/hardcode/index.html/':
+ return True
+ return False
+
+ def parse_request_hardcode_deep_html(self):
+ end = self.data.find("HTTP")
+ end = end - 1
+ if self.data[4:end] == '/hardcode/deep/'\
+ or self.data[4:end] == '/hardcode/deep/index.html'\
+ or self.data[4:end] == '/hardcode/deep/index.html/':
+ return True
+ return False
+
+ def parse_redirect(self):
+ end = self.data.find("HTTP")
+ end = end - 1
+ if self.data[4:end] == '/deep':
+ return 1
+
+ def parse_request_default_css(self):
+ end = self.data.find("HTTP")
+ if self.data[4:end] == '/base.css ' \
+ or self.data[4:end] == '/base.css/ ':
+ return True
+ return False
+
+ """
+ Serve the page methods. ----------------------------------------
+ """
+
+ def serve_default_css(self):
+ with open(os.getcwd() + "/www/base.css", 'r') as file:
+ f_holder = file.read()
+ f_holder = f_holder.replace('\n', '')
+ self.request.sendall(bytearray(
+ f"HTTP/1.1 200 OK{self.SPACE}Content-Type: text/css{self.SPACE}{self.END}{f_holder}", 'utf-8'))
+
+ def serve_redirect(self, value):
+ if value == 1:
+ self.request.sendall(bytearray(
+ f"HTTP/1.1 301 MOVED PERMANENTLY{self.SPACE}Location: http://127.0.0.1:8080/deep/{self.SPACE}{self.END}", 'utf-8'))
+
+ def serve_hardcode_deep_index(self):
+ with open(os.getcwd() + "/www/hardcode/deep/index.html", 'r') as file:
+ f_holder = file.read()
+ f_holder = f_holder.replace('\n', '')
+ self.request.sendall(bytearray(
+ f"HTTP/1.1 200 OK{self.SPACE}Content-Type: text/html{self.SPACE}{self.END}{f_holder}", 'utf-8'))
+
+ def serve_deep_index(self):
+ with open(os.getcwd() + "/www/deep/index.html", 'r') as file:
+ f_holder = file.read()
+ f_holder = f_holder.replace('\n', '')
+ self.request.sendall(bytearray(
+ f"HTTP/1.1 200 OK{self.SPACE}Content-Type: text/html{self.SPACE}{self.END}{f_holder}", 'utf-8'))
+
+ def serve_default_index(self):
+ with open(os.getcwd() + "/www/index.html", 'r') as file:
+ f_holder = file.read()
+ f_holder = f_holder.replace('\n', '')
+ self.request.sendall(bytearray(
+ f"HTTP/1.1 200 OK{self.SPACE}Content-Type: text/html{self.SPACE}{self.END}{f_holder}", 'utf-8'))
+
+ def serve_hardcode_index(self):
+ with open(os.getcwd() + "/www/hardcode/index.html", 'r') as file:
+ f_holder = file.read()
+ f_holder = f_holder.replace('\n', '')
+ self.request.sendall(bytearray(
+ f"HTTP/1.1 200 OK{self.SPACE}Content-Type: text/html{self.SPACE}{self.END}{f_holder}", 'utf-8'))
+
if __name__ == "__main__":
HOST, PORT = "localhost", 8080
diff --git a/www/hardcode/deep.css b/www/hardcode/deep.css
new file mode 100644
index 00000000..baafb8d2
--- /dev/null
+++ b/www/hardcode/deep.css
@@ -0,0 +1,4 @@
+h1 {
+ color:green;
+ text-align:center;
+}
diff --git a/www/hardcode/deep/deep.css b/www/hardcode/deep/deep.css
new file mode 100644
index 00000000..baafb8d2
--- /dev/null
+++ b/www/hardcode/deep/deep.css
@@ -0,0 +1,4 @@
+h1 {
+ color:green;
+ text-align:center;
+}
diff --git a/www/hardcode/deep/index.html b/www/hardcode/deep/index.html
new file mode 100644
index 00000000..ca0d6280
--- /dev/null
+++ b/www/hardcode/deep/index.html
@@ -0,0 +1,20 @@
+
+
+