Tiny and simple webserver for Basico

While developing the Dashboard module I had problems to display charts generated with Pygal. Charts can only be saved as SVG format (they can be saved as PNG files but I haven’t found any portable library to use easily in Windows).

The first solution I came up with was to create an HTML file and then point to the SVG file but WebKit doesn’t allow to do that if you aren’t using a Webserver (it is all about security policies).

So the next step was to implement a tiny webserver based on Python 3 core standard library. After a few research looking for simple implementations I found one very simple. At first, it worked but then Basico became unstable:

– After stopping Basico, the next execution returns errors due to the webserver isn’t stopped successfully and the port remains binded.
– Another issue: you can’t run the webserver and GTK application in the same thread because then the application freezes.

After a little bit more of research I was able to rewrite the module to overcome these problems and keep the compatibility in both platforms, Linux and Windows.

Finally, I was able to load my webpage from my tiny and simple webserver and embed it into my GTK application using WebKit:

The code used to do this:

#!/usr/bin/python
# -*- coding: utf-8 -*-
# File: webserver.py
# Author: Tomás Vírseda
# License: GPL v3
# Description: Simple and tiny WebServer service for Basico

import os
import time
import threading
from http.server import HTTPServer, SimpleHTTPRequestHandler
import socketserver

from .service import Service
from .env import LPATH

# FIXME: make PORT dynamic via configuration
PORT = 8763 # Custom Port. Could be any above 1024.
WEBROOT = LPATH['WWW']

class LoggingRequestHandler(SimpleHTTPRequestHandler):
    '''Custom class based on SimpleHTTPRequestHandler which disables
    logging
    '''
    def log_message(self, format, *args):
        return


class WebServer(Service):
    def initialize(self):
        os.chdir(WEBROOT)
        self.webserver = HTTPServer(('localhost', PORT), LoggingRequestHandler)


    def run(self):
        self.thread = threading.Thread(target = self.webserver.serve_forever)
        self.thread.daemon = True
        self.thread.start()
        self.log.debug("Basico WebServer Document Root: %s" % WEBROOT)
        self.log.debug('Basico WebServer listening on port: {}'.format(self.webserver.server_port))


    def halt(self):
        self.webserver.shutdown()
        self.thread.join()


    def finalize(self):
        self.halt()

The HTML code:

<html>
<head></head>
<body>
    <h1>SAP Components</h1>
    <h3>Number of SAP Notes for each SAP Component in your database</h3>
<object id="svg1" data="chart.svg" type="image/svg+xml"></object>
</body>
</html>

 

 

Leave a Reply

Your email address will not be published. Required fields are marked *