-3

I recently made a code that works just like an Apache server without any index.html

Apache server without any index.html

The problem is that my code is really buggy, I get different errors (that's why I didn't write them in the title)

Down here there is a photo of my work

My work

A photo of the structure (This is located in C:\Users\YourUsername\Documents\webserver\)

structure

As I said earlier I get different errors:

  1. When going into two folders or deeper and then trying going back using the browser arrow and then clicking on any file/folder I get FileNotFoundError
  2. When going into two folders or deeper and then trying to use the 'up folder' button ([ .. ]) gives me the equivalent of abort(404)

The syntax of the .CSS files is a bit particular but the content is just standard CSS

{
    color: black;
}


Now we have the main code, webserver.py

# -*- coding: utf-8 -*-

from flask import Flask, redirect, url_for, send_from_directory
from getpass import getuser
import os

### VARS ###

app = Flask('__main__')

SEP = os.sep

FOLDER_HOME = f'C:{SEP}Users{SEP}{getuser()}{SEP}Documents{SEP}webserver{SEP}'
FOLDER_STYLE = f'{FOLDER_HOME}styles{SEP}'
ONLINE_PATH = f''
app.config["ABS_PATH"] = f'C:{SEP}Users{SEP}{getuser()}{SEP}Documents{SEP}webserver{SEP}online{SEP}'

with open(f'{FOLDER_STYLE}STYLE_HTML.css', 'r', encoding='utf-8') as file: STYLE = " ".join(''.join(file.readlines()).split())
with open(f'{FOLDER_STYLE}STYLE_A.css', 'r', encoding='utf-8') as file: STYLE_A = " ".join(''.join(file.readlines()).split())
with open(f'{FOLDER_STYLE}STYLE_CLASS_ERROR.css', 'r', encoding='utf-8') as file: STYLE_ERROR = " ".join(''.join(file.readlines()).split())
with open(f'{FOLDER_STYLE}STYLE_CLASS_PDBTM.css', 'r', encoding='utf-8') as file: STYLE_PADDING_BOTTOM = " ".join(''.join(file.readlines()).split())
with open(f'{FOLDER_STYLE}STYLE_CLASS_HOME.css', 'r', encoding='utf-8') as file: STYLE_CLASS_HOME = " ".join(''.join(file.readlines()).split())

index_def1 = ['<!DOCTYPE html>', '<html>', '<head>', '<meta charset="utf-8">', f'<style type="text/css">html{STYLE} a{STYLE_A} .error{STYLE_ERROR} .pdbtm{STYLE_PADDING_BOTTOM} .home{STYLE_CLASS_HOME}</style>', f'<title>Index of /{ONLINE_PATH.replace(f"{SEP}", "/")}</title>', '</head>', '<body>', f'<h1 align="center">Index of /{ONLINE_PATH.replace(f"{SEP}", "/")}</h1>', '<br>', '<ul>', '[<a class="home pdbtm" href="/">HOME</a>]<br>', f'[<a class="home pdbtm" href="/{ONLINE_PATH}"> .. </a>]<br>']
index_file = []
index_def2 = ['</ul>', '</body>', '</html>']

### END ###

### FUNCTIONS ###

def process_html(dirs_list, files_list):
    body = []
    body.append('<br> --- Directorys --- </br>')
    if dirs_list == []: body.append('<h2 class="error">No dirs found</h2>')
    else:
        for dirs in dirs_list:
            body.append(f'<li class="pdbtm"><a href="/{dirs}">{dirs}/</a></li>')
    body.append('<br> --- Files --- </br>')
    if files_list == []: body.append('<h2 class="error">No files found</h2>')
    else:
        for files in files_list:
            body.append(f'<li class="pdbtm"><a href="{files}">{files}</a></li>')
    return body

def process_all(path, listed_directory):
    dirs = []
    files = []
    for item in listed_directory:
        if os.path.isfile(f'{path}{item}') == True: files.append(item)
        else: dirs.append(item)
    return dirs, files

### END ###

### ROUTES ###

@app.route('/')
def main():
    global index_file
    global ONLINE_PATH
    global index_def1
    ONLINE_PATH = ''
    index_def1 = ['<!DOCTYPE html>', '<html>', '<head>', '<meta charset="utf-8">', f'<style type="text/css">html{STYLE} a{STYLE_A} .error{STYLE_ERROR} .pdbtm{STYLE_PADDING_BOTTOM} .home{STYLE_CLASS_HOME}</style>', f'<title>Index of /{ONLINE_PATH.replace(f"{SEP}", "/")}</title>', '</head>', '<body>', f'<h1 align="center">Index of /{ONLINE_PATH.replace(f"{SEP}", "/")}</h1>', '<br>', '<ul>', '[<a class="home pdbtm" href="/">HOME</a>]<br>', f'[<a class="home pdbtm" href="/{ONLINE_PATH}"> .. </a>]<br>']
    app.config["ABS_PATH"] = f'C:{SEP}Users{SEP}{getuser()}{SEP}Documents{SEP}webserver{SEP}online{SEP}'
    list_of_files = os.listdir(app.config["ABS_PATH"])
    dirs, files = process_all(app.config["ABS_PATH"], list_of_files)
    index_file = process_html(dirs, files)
    index_comp = [index_def1, index_file, index_def2]
    index = [item for sublist in index_comp for item in sublist]
    return ''.join(index)

@app.route("/<path>")
def get_file(path):
    while True:
        try: 
            return send_from_directory(app.config["ABS_PATH"], filename=path, as_attachment=True)
        except:
            global index_file
            global ONLINE_PATH
            global index_def1

            if path not in ONLINE_PATH: ONLINE_PATH += f'{path}{SEP}'
            else: ONLINE_PATH = f'{path}{SEP}'
            xyz = ONLINE_PATH.replace(path, '')
            xyz = xyz[:-1]
            xyz = ''.join(xyz)
            index_def1 = ['<!DOCTYPE html>', '<html>', '<head>', '<meta charset="utf-8">', f'<style type="text/css">html{STYLE} a{STYLE_A} .error{STYLE_ERROR} .pdbtm{STYLE_PADDING_BOTTOM} .home{STYLE_CLASS_HOME}</style>', f'<title>Index of /{ONLINE_PATH.replace(f"{SEP}", "/")}</title>', '</head>', '<body>', f'<h1 align="center">Index of /{ONLINE_PATH.replace(f"{SEP}", "/")}</h1>', '<br>', '<ul>', '[<a class="home pdbtm" href="/">HOME</a>]<br>', f'[<a class="home pdbtm" href="/{xyz}"> .. </a>]<br>']
            app.config["ABS_PATH"] = f'C:{SEP}Users{SEP}{getuser()}{SEP}Documents{SEP}webserver{SEP}online{SEP}{ONLINE_PATH}'

            list_of_files = os.listdir(app.config["ABS_PATH"])
            dirs, files = process_all(app.config["ABS_PATH"], list_of_files)
            index_file = process_html(dirs, files)
            index_comp = [index_def1, index_file, index_def2]
            index = [item for sublist in index_comp for item in sublist]
            return ''.join(index)

### END ###

app.run(host='0.0.0.0', port=80, debug=True)

Can anyone help me with those errors, or simply by improving my code? Thanks

roganjosh
  • 12,594
  • 4
  • 29
  • 46
user321985
  • 41
  • 8
  • 3
    What on Earth is going on in this code? What do you intend all the `with open()` context managers being stacked up to do? Please take a step back here and use something like the [mega tutorial](https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world) and you would do well revisiting some of the fundamentals. With respect, it looks like you've skipped some touch-stones of knowledge and got yourself tangled up – roganjosh Jan 29 '20 at 21:41
  • 1
    Okay... There is a lot going on here. The CSS you've posted is completely irrelevant as are the images. They just clutter up the post. A lot of work is needed. I'll create an answer with some tips. – blueteeth Jan 29 '20 at 21:41
  • Thanks @roganjosh for the tip, I know that my code is a mess, but I didn't think it was that bad. I'm definitely going to watch that link – user321985 Jan 29 '20 at 21:50
  • You're handling all the template logic on the backend. Flask comes with [jinja2](https://www.palletsprojects.com/p/jinja/) and you can make use of that to build your template. Specifically (though not exclusively) with something like [`render_template`](https://flask.palletsprojects.com/en/1.1.x/api/#template-rendering) – roganjosh Jan 29 '20 at 21:51
  • Thanks @blueteeth for the suggestion, I'm not good at posting questions on SO, I have a lot to learn – user321985 Jan 29 '20 at 21:52
  • @roganjosh yes, I tried `render_template` but it didn't worked with the variables – user321985 Jan 29 '20 at 21:54
  • This is why I think you would be better taking a step back. Thank you for reading my comment as genuine; I'm just trying to make you re-evaluate because I think this has gone quite a bit off-course for you. I highly recommend the tutorial I linked – roganjosh Jan 29 '20 at 21:56
  • Please do not trash your own question. It invalidates the answer you were given. Once it's posted and you get an answer, it would be unfair on the person that answered for you to just wipe the context; SO has never been about individuals – roganjosh Jan 29 '20 at 22:07

1 Answers1

1

This needs a lot of work. I can't answer the question in this state, but I can give you some tips:

  1. Do not generate HTML from a string. Use templates instead: https://flask.palletsprojects.com/en/1.1.x/tutorial/templates/
    • Template parameters are your friend. You could store the files in the current directory as a list. Or even better, create an abstraction for a path, and give a list of those.
    • That will also allow you to get rid of all these random CSS files.
  2. Don't use globals. There is almost never a need for them in Python.
  3. pathlib would really help you here rather than os.path: https://docs.python.org/3/library/pathlib.html
  4. You don't need 2 routes. You need just one /<path>. If it's blank load the root directory, otherwise load whatever is at that path.

Perhaps follow a guide about how to create a flask app. This one is very good: https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-world

You don't have to follow it all the way through.

Good luck! Feel free to post again when you have the next version.

blueteeth
  • 3,330
  • 1
  • 13
  • 23