Search code examples
pythonhtmlsocketswebserver

Image won't load on python-based webserver


I've built a simple web server that gets a request and send a response. So when the server gets an invalid request, like "localhost/not-a-page", the server will send a response with the content of the HTML file "404.html" the webpage should display an image. So far, so good.

But when the 404 page loads up, the page can't find the image. The HTML part is correct and works offline. I've tried to move the image to serval locations, relative to the Python script, relative to the HTML. But it just can't find it. Hi I'm trying to make the server as low-level as I can, I want to learn how servers work. So I'm not using any server-related libraries. I'm using only the socket library of Python.

I'll appreciate any help to resolve this problem without using other libraries,

EDIT Here is the relevant Python part :

import socket

import threading

import os



default_error_page = """\

<!DOCTYPE HTML>

<html>

<head>

<meta http-equiv="Content-Type" content="text/html;charset=utf-8">

<title>Error response</title>

</head>

<body>

<center>

<h1>Response</h1>

<p>Error code: %(code)d</p>

<p>Message: %(status)s.</p>

</center>

</body>

</html>

"""


default_header_status = "HTTP/1.1 %(code)d %(status)s\r\n"

default_header_content_type = "Content-Type: text/html; charset=utf-8\r\n\r\n"

buffer_size = 1024



def get_page(code):

    page = default_error_page

    if code == 200:

        pass

    else:

        file = open(os.path.dirname(__file__) + "/www/not-found.html", 'r')

        page = file.read()

    return page


class BaseServer:


    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    server_name = ""

    host_name = ""

    host_port = 8000 # default port

    is_shutdown = False


    def __init__(self, name):

        self.server_name = name


    def start_server(self):

        thread = threading.Thread(target=self.run_server(), name=self.server_name)

        thread.start()


    def run_server(self):

        self.server_socket.bind((self.host_name, self.host_port)) # bind to host

        self.server_socket.listen()

        while not self.is_shutdown:

            conn, addr = self.server_socket.accept()

            self.handle_request(conn, addr)


    def handle_request(self, connection, address):

        print(str(address[0]) + " Connected! (port " + str(address[1]) + ")")

        result = self.parse_request(connection.recv(buffer_size))

        if result == 0:

            page = self.parse_response(200)

        else:

            page = self.parse_response(404)

        connection.sendall(bytes(page))


    def parse_request(self, data):

        if len(data) == 0:

            return

        strings = str(bytes(data).decode('utf-8')).split('\r\n')

        command, path, version = strings[0].split()

        print("command - " + command)

        print("path - " + path)

        print("version - " + version)


        status = 1


        if path == "/":

            status = 0


        return status


    def parse_response(self, code):

        status = "ERROR"

        if code == 200:

            status = "OK"

        elif code == 404:

            status = "NOT FOUND"


        base_header = (default_header_status % {'code': code, 'status': status})

        base_content_type = default_header_content_type

        # page = (default_error_page % {'code': code, 'status': status})

        page = str(get_page(code))

        return_string = str(base_header + base_content_type + page).encode('utf-8')

        print(return_string)

        return return_string



def main():

    server = BaseServer("Home Server")

    server.start_server()




if __name__ == "__main__":

    main()

And this is the HTML:

<html>


<head>

<link rel="stylesheet" type="text/css" href="/style/main.css"/>

<style>

    *{

    padding:0;

    margin:0;

}

body{

    background-color:#ffe6b3;

}

h1{

    margin-top:30px;

    background-color:#ffcc66;

    font-size:3em;

    display:inline-block;

    color:#3a0000;

}

p{

    margin-top:80px;

    font-size:2em;

    color:#3a0000;

}

#img404{

    background-image:url(../images/404.gif);

    width:100%;

    height:50%;

    background-repeat:no-repeat;

    background-position:center 20%;

}

</style>

</head>


<body>

    <center>

        <div class=top>

            <h1>ERROR 404</h1>

        </div>

        <p>

         Sorry, we could not find the page :(

        </p>

        <div id="img404">


        </div>

    </center>

</body>


</html>

Sorry if it's not very readable, but I'm on the phone.

Dima.


Solution

  • Figured out my problem. After I saw the logs, I realized that the browser sends another request, for the image. And silly me, my code is:

    if path ="/":
        status = 0
    else:
        status = 1
    

    So for every request which is not root("/") the server will return 404.

    Oops