2

I am trying to make a blog and sustain it, on this blog the content will only be in html/css or some images, so I don't need any sophisticated web server, I've tried to write a script that will hold the blog active, but sometimes and that's really frequent, it just goes down and I've tried to get logs of it and at first it was something about broken pipe but I tried to fix that using signal handling, and I don't know how to keep the server up all the time. here is the code:

#!/usr/bin/python
from http.server import HTTPServer, BaseHTTPRequestHandler
import os
from os import curdir, sep, path
from signal import signal, SIGPIPE, SIG_DFL
import logging

HOST = #ip_address
PORT = 8089

class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):

    def do_GET(self):
        self.send_response(200)
        self.end_headers()
        try:
            print(self.path)
            path = self.path
            if ('?' in path):
                path = path.split('?')[0]
            self.path = path
            print(self.path)
            if (self.path == '/'):
                self.path = '/index.html'
            self.path = 'output' + self.path
            if(os.path.isdir(self.path)):
                if(not os.path.exists(self.path + 'index.html')):
                    self.send_response(403)
                    self.wfile.write(str.encode("Listing of directories not permited on this server"))
                else:
                    self.path = self.path + 'index.html'

            f = open(curdir + sep + self.path, 'rb')
            self.wfile.write(f.read())
            f.close()
        except IOError:
            print("File "+self.path+" not found")
            self.send_response(404)


httpd = HTTPServer((HOST, PORT), SimpleHTTPRequestHandler)
httpd.serve_forever()

signal(SIGPIPE, SIG_DFL)
J. Homer
  • 147
  • 1
  • 11

3 Answers3

1

You can solve it by applying a handle like this:

import os
import SocketServer

HOST = 'localhost'
PORT = 8089

class ForkingEchoRequestHandler(SocketServer.BaseRequestHandler):

    def do_GET(self):
        self.send_response(200)
        self.end_headers()
        try:
            print(self.path)
            path = self.path
            if ('?' in path):
                path = path.split('?')[0]
            self.path = path
            print(self.path)
            if (self.path == '/'):
                self.path = '/index.html'
            self.path = 'output' + self.path
            if(os.path.isdir(self.path)):
                if(not os.path.exists(self.path + 'index.html')):
                    self.send_response(403)
                    self.wfile.write(str.encode("Listing of directories not permited on this server"))
                else:
                    self.path = self.path + 'index.html'

            f = open(curdir + sep + self.path, 'rb')
            self.wfile.write(f.read())
            f.close()
        except IOError:
            print("File "+self.path+" not found")
            self.send_response(404)
        except socket.error:
            pass


class ForkingEchoServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):
    pass

if __name__ == '__main__':
    import socket
    import threading

    address = (HOST, PORT) # let the kernel give us a port
    server = ForkingEchoServer(address, ForkingEchoRequestHandler)
    # Start a thread with the server -- that thread will then start one
    # more thread for each request
    server_thread = threading.Thread(target=server.serve_forever)
    # Exit the server thread when the main thread terminates
    server_thread.daemon = True
    server_thread.start()
    print('Server loop running in thread: "%s"' % server_thread.name)
    while True:
        pass
    server.shutdown()

But, maybe this might be a problem since there is a bug in Socket Server, this means that it can't process multiple requests at the same time

Additionally, if you want your HTTP server to process more than one request at a time, you need your server class to use one of the SocketServer.ForkingMixIn and SocketServer.ThreadingMixIn classes. Check the documentation of the SocketServer module for details.

Here is a more specific question that lists most cases about BaseHTTPServer

EDIT

After a chat discussion it was possible to resolve the problem with NGINX using a simple configuration file:


user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;


    server {
        listen 80;
        root /var/www/cristicretan.ro/output/;
        index index.html;
        server_name cristicretan.ro www.cristicretan.ro;
        location / {
        try_files $uri $uri/ =404;
        }
    }
}
Roberto Gonçalves
  • 3,186
  • 4
  • 13
  • 27
0

I highly suggest gunicorn to manage your running process. You can also handle multiple requests and concurrency really well with this tool. I linked to the custom application portion since you're writing your own

Zoidberg
  • 425
  • 3
  • 10
0

We can either ignore the BrokenPipe and continue or catch the exception.

For ignoring, SIGPIPE is used. But according to the python signal documentation,

Do not set SIGPIPE’s disposition to SIG_DFL in order to avoid BrokenPipeError. Doing that would cause your program to exit unexpectedly also whenever any socket connection is interrupted while your program is still writing to it.

So the best way is to catch the BrokenPipeError

import sys, errno
try:
    ### IO operation ###
except IOError as e:
    if e.errno == errno.EPIPE:
        ### Handle error ###