Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 37 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,54 @@
CMPUT404-assignment-webserver
=============================
# CMPUT404-assignment-webserver

CMPUT404-assignment-webserver

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<br />
https://www.bogotobogo.com/python/python_network_programming_socketserver_framework_for_network_servers.php<br />
Network Programming III - SocketServer<br />

- Tech With Tim<br />
https://www.youtube.com/@TechWithTim<br />
Python Socket Programming Tutorial<br />
https://youtu.be/3QiPPX-KeSc<br />
Youtube<br />

- jbx<br />
https://stackoverflow.com/users/340088/jbx<br />
https://stackoverflow.com/a/53070496<br />
Stackoverflow<br />

- PyMOTW<br />
http://pymotw.com/2/SocketServer/<br />
SocketServer – Creating network servers<br />
Binary file added deep.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added root.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
187 changes: 178 additions & 9 deletions server.py
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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
Expand All @@ -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
Expand Down
4 changes: 4 additions & 0 deletions www/hardcode/deep.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
h1 {
color:green;
text-align:center;
}
4 changes: 4 additions & 0 deletions www/hardcode/deep/deep.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
h1 {
color:green;
text-align:center;
}
20 changes: 20 additions & 0 deletions www/hardcode/deep/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<title>Deeper Example Page</title>
<meta http-equiv="Content-Type"
content="text/html;charset=utf-8"/>
<!-- check conformance at http://validator.w3.org/check -->
<link rel="stylesheet" type="text/css" href="deep.css">
</head>

<body>
<div class="eg">
<h1>An Example of a Deeper Page</h1>
<ul>
<li>It works?</li>
<li><a href="../index.html">A page below!</a></li>
</ul>
</div>
</body>
</html>
20 changes: 20 additions & 0 deletions www/hardcode/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html>
<head>
<title>Deeper Example Page</title>
<meta http-equiv="Content-Type"
content="text/html;charset=utf-8"/>
<!-- check conformance at http://validator.w3.org/check -->
<link rel="stylesheet" type="text/css" href="deep.css">
</head>

<body>
<div class="eg">
<h1>An Example of a Deeper Page</h1>
<ul>
<li>It works?</li>
<li><a href="../index.html">A page below!</a></li>
</ul>
</div>
</body>
</html>