Giter Club home page Giter Club logo

jczic / microwebsrv2 Goto Github PK

View Code? Open in Web Editor NEW
620.0 28.0 89.0 1.04 MB

The last Micro Web Server for IoTs (MicroPython) or large servers (CPython), that supports WebSockets, routes, template engine and with really optimized architecture (mem allocations, async I/Os). Ready for ESP32, STM32 on Pyboard, Pycom's chipsets (WiPy, LoPy, ...). Robust, efficient and documented!

Home Page: https://github.com/jczic/MicroWebSrv2

License: MIT License

Python 95.50% HTML 4.17% CSS 0.33%
websockets micropython esp32 microwebsrv http ssl wipy pycom hc2 iot

microwebsrv2's Introduction

Also check out the new ESP32 MPY-Jama free IDE below:

New microWebSrv2


Release Size MicroPython Python License


MicroWebSrv2 is the new powerful embedded Web Server for MicroPython and CPython that supports route handlers, modules like WebSockets or PyhtmlTemplate and a lot of simultaneous requests (in thousands!).

Fully asynchronous, its connections and memory management are very optimized and truly fast.

Mostly used on Pycom WiPy, ESP32, STM32 on Pyboard, ... Robust and efficient! (see Features)



                _               __    __     _     __            ____  
      _ __ ___ (_) ___ _ __ ___/ / /\ \ \___| |__ / _\_ ____   _|___ \ 
     | '_ ` _ \| |/ __| '__/ _ \ \/  \/ / _ | '_ \\ \| '__\ \ / / __) |
     | | | | | | | (__| | | (_) \  /\  |  __| |_) _\ | |   \ V / / __/ 
     |_| |_| |_|_|\___|_|  \___/ \/  \/ \___|_.__/\__|_|    \_/ |_____|  JC`zic & HC²



📑  Table of contents


💢  About

This project follows the embedded MicroWebSrv, which is mainly used on microcontrollers such as Pycom, ESP32 and STM32 on Pyboards.

In a need for scalability and to meet the IoT universe, microWebSrv2 was developed as a new project and has been completely redesigned to be much more robust and efficient that its predecessor.

Internal mechanisms works directly at I/O level, are fully asynchronous from end to end, and manages the memory in a highly optimized way.
Also, architecture makes its integration very easy and the source code, MIT licensed, remains really small.


🚀  Features

  • Embed microWebSrv2 into your microcontrollers as a powerful web server.

  • Benefit from a fully asynchronous architecture that allows to process many concurrent requests very quickly.

  • Use multiple worker threads to parallelize simultaneous processes.

  • Adjust settings to fine-tune resources usage and sizing pre-allocated memory.

  • Load additional modules to extend the server's functionalities.

  • Customize the management of centralized logs.

  • Apply SSL/TLS security layer and certificate on web connections (https mode).

  • Define web routes with variable arguments in order to be able to process the targeted requests.

  • Receive any type of request such as GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH, ...

  • Use the route resolver (from the path) and the path builder (from the route) for convenience.

  • Increase loading speed by automatically allowing web clients to cache static files.

  • Receive name/value pairs from URL encoded forms.

  • Send and receive JSON objects and use them to create a RESTful API style.

  • Play with AjAX requests to interact quickly with a web application.

  • Define the origin of resources and allow all values of CORS pre-flight requests.

  • Verify that a request is successfully authenticated by the Basic or Bearer method.

  • Reduce the number of persistent connections per web client with keep-alive mode support.

  • Respond to a request by using a data stream as content, sent with known length or in chunked transfer-encoding.

  • Use a file to respond to a request that will be treated as on-the-fly content or as an attachment to download.

  • Take advantage of the WebSockets module to exchange messages in real time via WS or secured WSS connection.

  • Create .pyhtml pages for an HTML rendering with integrated Python using the PyhtmlTemplate module.


🔌  Install

  • Solution 1 Run:
    pip3 install --user git+https://github.com/jczic/MicroWebSrv2.git#egg=MicroWebSrv2
    git clone https://github.com/jczic/MicroWebSrv2.git
    and run:
    cd MicroWebSrv2 && pip install --user .
  • Solution 3, download the ZIP file and extract it to a folder of your choice.

🚦  Demo

  1. Start the example:

    > python3 main.py
  2. Open your web browser at:

WebSockets Chat


⚙️  Usage

from MicroWebSrv2 import *
from time         import sleep

mws2 = MicroWebSrv2()
mws2.StartManaged()

# Main program loop until keyboard interrupt,
try :
    while True :
        sleep(1)
except KeyboardInterrupt :
    mws2.Stop()

📚  Documentation

  • MicroWebSrv2 package

    The Python package comes with the following files:

    • 🔻 /MicroWebSrv2
      • 🔸 __init__.py
      • 🔸 microWebSrv2.py
      • 🔸 webRoute.py
      • 🔸 httpRequest.py
      • 🔸 httpResponse.py
      • 🔹 /libs
        • 🔸 XAsyncSockets.py
        • 🔸 urlUtils.py
      • 🔹 /mods
        • 🔸 WebSockets.py
        • 🔸 PyhtmlTemplate.py

  • Working with microWebSrv2

    To work with microWebSrv2, you must first import the package as follows:

    from MicroWebSrv2 import *

    There are 5 main elements with which you will work:

    Now, you have everything you need to continue 😎


    • Asynchronous logic

      microWebSrv2 is based on a fully asynchronous I/Os logic.

      This means that many requests and responses can be processed concurrently, allowing other necessary processing at any time within a single thread.

      In addition, it is possible to use several shared workers in order to be able to parallelize processes that could be blocking.

      Finally, memory buffers required for data processing are pre-allocated as best as possible to maximize performance and prevent excessive memory requirements.

      Thus, it is possible to maintain several thousand persistent connections but also, to benefit from a low consumption of resources on embedded platforms.

      microWebSrv2 leans on the XAsyncSockets layer.


    • Configuring web server

      Before starting microWebSrv2 to listen to web requests, it is important to configure it correctly.

      • If you want to change the default server port or bind IP address, you must set the BindAddress property.

        mws2.BindAddress = ('192.168.0.1', 12345)
      • If you want to define an another directory for web files, you must set the RootPath property.

        mws2.RootPath = 'webfiles/root'
      • If you want a secure https web server, you must call the EnableSSL method.

        mws2.EnableSSL(certFile='certificate.crt', keyFile='private-key.key')
      • If you want to redirect resources not found, you must set the NotFoundURL property.

        mws2.NotFoundURL = '/'   # relative or absolute URL
      • If you want to set a pre-configured setting, you can call one of the following methods:

      • If you want to set your custom settings, you can adjust the following properties:

      • If you want to change the default timeout to wait for requests data, you must set the RequestsTimeoutSec property.

        mws2.RequestsTimeoutSec = 10
      • If you want to intercept logs to process them, you must set the OnLogging callback.

        def OnMWS2Logging(microWebSrv2, msg, msgType) :
            print('Log from custom function: %s' % msg)
        
        mws2.OnLogging = OnMWS2Logging

      • Default pages

        Default pages are used as resources when requested paths point to directories.

        Page filename
        index.html
        index.htm
        default.html
        default.htm

        It is possible to add new default pages globally by calling MicroWebSrv2.AddDefaultPage static method.


      • MIME types

        MIME types allow specific files as readable resources and that are transmitted with the corresponding content type.

        Filename extension MIME type
        .txt text/plain
        .htm text/html
        .html text/html
        .css text/css
        .csv text/csv
        .js application/javascript
        .xml application/xml
        .xhtml application/xhtml+xml
        .json application/json
        .zip application/zip
        .pdf application/pdf
        .ts application/typescript
        .woff font/woff
        .woff2 font/woff2
        .ttf font/ttf
        .otf font/otf
        .jpg image/jpeg
        .jpeg image/jpeg
        .png image/png
        .gif image/gif
        .svg image/svg+xml
        .ico image/x-icon

        It is possible to add new MIME types globally by calling MicroWebSrv2.AddMimeType static method.


    • Starting web server

      To start microWebSrv2 server, you must use one of the following methods:

      • Start in a pool:
        The web server uses an existing asynchronous pool.
        If you want to have more than one server, this is the right solution.

        For more documentation, see StartInPool(...) method.
        If you want details about pools, check the GitHub repository of XAsyncSockets library.

      • Start in a managed pool:
        The web server automatically creates a new managed asynchronous pool and uses it.
        If you only need one server without more specific code, this is the right solution.
        However, you will need to define some pool sizing parameters.
        In this mode, a call to mws2.Stop() will release the pool.

        For more documentation, see StartManaged(...) method.

      🌀 Example to start a dual http/https web server:

      from MicroWebSrv2 import *
      from time         import sleep
      
      xasPool  = XAsyncSocketsPool()
      srvHttp  = MicroWebSrv2()
      srvHttps = MicroWebSrv2()
      
      srvHttps.EnableSSL( certFile = 'SSL-Cert/openhc2.crt',
                          keyFile  = 'SSL-Cert/openhc2.key' )
      
      srvHttp .StartInPool(xasPool)
      srvHttps.StartInPool(xasPool)
      
      xasPool.AsyncWaitEvents(threadsCount=1)
      
      try :
          while True :
              sleep(1)
      except KeyboardInterrupt :
          srvHttp .Stop()
          srvHttps.Stop()
          xasPool .StopWaitEvents()

    • Handling web routes

      microWebSrv2 have an easy and efficient web route system.
      A simple handler function with a decorator allows you to process requests.

      🌀 Example of a processing handler:

      @WebRoute(GET, '/test')
      def RequestTest(microWebSrv2, request) :
          request.Response.ReturnOkJSON({
              'ClientAddr' : request.UserAddress,
              'Accept'     : request.Accept,
              'UserAgent'  : request.UserAgent
          })

      For more documentation, see Web Routes section.


    • SSL/TLS security (HTTPS)

      microWebSrv2 allow web server to apply the SSL/TLS security layer.
      In this case, a certificate and its private key must be given (with an optional PEM file).

      If you want to test https mode, uncomment the mws2.EnableSSL(...) call in main.py file.
      After restarting the demo program, open your browser at the following address:
      https://localhost

      ⚠️ The ssl library must be implements SSLContext on Python version to support secured web server.


  • About XAsyncSockets layer

    XAsyncSockets is an efficient Python/MicroPython library of managed asynchronous sockets.

    Available under MIT license on GitHub (same author):
    https://github.com/jczic/XAsyncSockets

    XAsyncSockets layer provides the following features:

    • Managed asynchronous sockets in a pool (up to thousands!)
    • Works directly with I/O to receive and send very quickly
    • Supports very large number of simultaneous TCP connections
    • Supports concurrent synchronous processing operations if necessary (threaded)
    • Implementation of TCP servers
    • Implementation of TCP clients
    • Implementation of UDP datagrams (sender and/or receiver)
    • TCP client can event after a specified size of data or a text line received
    • Each connections and receivings can waiting during a specified time
    • The reasons of TCP client closures are returned
    • Really robust, very fast and easy to use
    • Compatible with MicroPython implementation (sockets layer, FiFo queue, perf counter)

  • MicroWebSrv2 Class

    MicroWebSrv2 is the main class and is needed to create an instance of web server:

    mws2 = MicroWebSrv2()

    • MicroWebSrv2 static methods

      ▶️ MicroWebSrv2.LoadModule(...)

      @staticmethod
      def LoadModule(modName)
      # Loads a global and dedicated module for all instances of MicroWebSrv2.
      #   - Returns the instantiated class of the module.
      #     This instance can be used to configure global parameters and callbacks.
      #   - <modName> is the name of module and must be a not empty string.
      # An exception will be raised if an error occurs.

      ▶️ MicroWebSrv2.HTMLEscape(...)

      @staticmethod
      def HTMLEscape(s)
      # Escapes HTML special characters of a text to use it in HTML code.
      #   - Returns the escaped string of <s>.
      #   - <s> is a text that must be escaped and must be a string.
      # An exception can be raised if <s> is not correct.

      ▶️ MicroWebSrv2.AddDefaultPage(...)

      @staticmethod
      def AddDefaultPage(filename)
      # Adds a new default page that it can be returned when a directory resource is requested.
      # Default pages are searched by order in list and file must be found in the directory.
      # Ex: AddDefaultPage('home.html')
      #   - No return value.
      #   - <filename> is the name of page file that will be searched and must be a not empty string.
      # An exception can be raised if <filename> is not correct.

      ▶️ MicroWebSrv2.AddMimeType(...)

      @staticmethod
      def AddMimeType(ext, mimeType)
      # Adds a new MIME type to support specified file type and response content type.
      # Ex: AddMimeType('.tar', 'application/x-tar')
      #   - No return value.
      #   - <ext> is the file extention including the dot and must be a not empty string.
      #   - <mimeType> is the name of MIME type and must be a not empty string.
      # An exception can be raised if arguments are not correct.

      ▶️ MicroWebSrv2.GetMimeTypeFromFilename(...)

      @staticmethod
      def GetMimeTypeFromFilename(filename)
      # Obtains the name of MIME type corresponding to a filename.
      #   - Returns the name of MIME type found in string, returns None otherwise.
      #   - <filename> is a path to a file and must be a not empty string.

    • MicroWebSrv2 instance methods

      ▶️ mws2.StartInPool(...)

      def StartInPool(self, asyncSocketsPool)
      # Starts the web server in an existing asynchronous pool.
      #   - No return value.
      #   - <asyncSocketsPool> is the asynchronous pool and must be an instantiated class of XAsyncSocketsPool.
      # An exception will be raised if an error occurs.

      ▶️ mws2.StartManaged(...)

      def StartManaged(self, parllProcCount=1, procStackSize=0)
      # Starts the web server in a new and managed asynchronous pool.
      #   - No return value.
      #   - <parllProcCount> is the count of parallel processes and must be a positive integer or zero.
      #   - <procStackSize> is the stack size for each parallelized processes and must be a positive integer or zero.
      # If <parllProcCount> is 0, the calling thread is used and blocked to process all http connections.
      # If <parllProcCount> is 1, only one thread is reserved to process all http connections.
      # If <parllProcCount> is greater than 1, multiple threads are reserved to share and process all http connections.
      # If <procStackSize>  is 0, the default stack size is used on CPython and a value of 8192 is used on MicroPython.
      # A minimum value of 8*1024 is recommended for <procStackSize> but on CPython, the minimum value must be of 32*1024.
      # An exception will be raised if an error occurs.

      ▶️ mws2.Stop(...)

      def Stop(self)
      # Stops the web server.
      # If the server has started in managed mode, this automatically releases the asynchronous pool.
      #   - No return value.

      ▶️ mws2.Log(...)

      def Log(self, msg, msgType)
      # Logs the message of the specified type to the output or by calling the OnLogging callback.
      #   - No return value.
      #   - <msg> is the message to log and will be converted to string.
      #   - <msgType> can take following values:
      #      - MicroWebSrv2.DEBUG
      #      - MicroWebSrv2.INFO
      #      - MicroWebSrv2.WARNING
      #      - MicroWebSrv2.ERROR

      ▶️ mws2.ResolvePhysicalPath(...)

      def ResolvePhysicalPath(self, urlPath)
      # Resolves the specified relative URL path to the physical path.
      #   - Returns the physical path found or None.
      #   - <urlPath> is the relative URL path to resolve and must be a not empty string.
      # An exception can be raised if <urlPath> is not correct.

      ▶️ mws2.EnableSSL(...)

      def EnableSSL(self, certFile, keyFile, caFile=None)
      # Configures the web server to apply the SSL/TLS security layer (https).
      # Warning, the ssl library must be implements SSLContext on Python version to support secured web server.
      #   - No return value.
      #   - <certFile> is the path of the certificate file and must be a not empty string.
      #   - <keyFile> is the path of the private key file and must be a not empty string.
      #   - <caFile> is the path of a PEM file and must be a not empty string or None.
      # If the web server port in BindAddress is 80 (default http), it automatically switches to port 443 (default https).
      # An exception will be raised if an error occurs.

      ▶️ mws2.DisableSSL(...)

      def DisableSSL(self)
      # Configures the web server as SSL/TLS web server (https).
      #   - No return value.
      # If the web server port in BindAddress is 443 (default https), it automatically switches to port 80 (default http).
      # An exception can be raised if an error occurs.

      ▶️ mws2.SetEmbeddedConfig(...)

      def SetEmbeddedConfig(self)
      # Configures the web server with optimized parameters for an embedded deployment.
      #   - No return value.
      # Parameters set:
      #   - ConnQueueCapacity       = 8
      #   - BufferSlotsCount        = 16
      #   - BufferSlotSize          = 1024
      #   - KeepAllocBufferSlots    = True
      #   - MaxRequestContentLength = 16*1024
      # An exception can be raised if an error occurs.

      ▶️ mws2.SetLightConfig(...)

      def SetLightConfig(self)
      # Configures the web server with optimized parameters for a light deployment.
      #   - No return value.
      # Parameters set:
      #   - ConnQueueCapacity       = 64
      #   - BufferSlotsCount        = 128
      #   - BufferSlotSize          = 1024
      #   - KeepAllocBufferSlots    = True
      #   - MaxRequestContentLength = 512*1024
      # An exception can be raised if an error occurs.

      ▶️ mws2.SetNormalConfig(...)

      def SetNormalConfig(self)
      # Configures the web server with optimized parameters for a normal deployment.
      # It is the default configuration when MicroWebSrv2 class is created.
      #   - No return value.
      # Parameters set:
      #   - ConnQueueCapacity       = 256
      #   - BufferSlotsCount        = 512
      #   - BufferSlotSize          = 4*1024
      #   - KeepAllocBufferSlots    = True
      #   - MaxRequestContentLength = 2*1024*1024
      # An exception can be raised if an error occurs.

      ▶️ mws2.SetLargeConfig(...)

      def SetLargeConfig(self)
      # Configures the web server with optimized parameters for a large deployment.
      #   - No return value.
      # Parameters set:
      #   - ConnQueueCapacity       = 512
      #   - BufferSlotsCount        = 2*1024
      #   - BufferSlotSize          = 16*1024
      #   - KeepAllocBufferSlots    = True
      #   - MaxRequestContentLength = 8*1024*1024
      # An exception can be raised if an error occurs.

    • MicroWebSrv2 properties

      Name Type Get Set Description
      IsRunning bool ☑️ - Indicates that the server is running.
      ConnQueueCapacity int ☑️ ☑️ Queue capacity of the TCP server (backlog).
      BufferSlotsCount int ☑️ ☑️ Number of pre-allocated memory buffer slots.
      BufferSlotSize int ☑️ ☑️ Size of each pre-allocated memory buffer slots.
      KeepAllocBufferSlots bool ☑️ ☑️ Maintains the allocation of memory buffer slots.
      MaxRequestContentLength int ☑️ ☑️ Maximum content length who can be processed by a request.
      BindAddress tuple ☑️ ☑️ Local bind address of the TCP server such as a tuple of (str_ip_addr, int_port).
      IsSSLEnabled bool ☑️ - Indicates that SSL/TLS security layer with certificate is currently enabled.
      RootPath str ☑️ ☑️ Path of the root folder that contains the web files.
      RequestsTimeoutSec int ☑️ ☑️ Timeout in seconds to waiting the next data reception of requests.
      NotFoundURL str or None ☑️ ☑️ URL used to redirects requests not found.
      AllowAllOrigins bool ☑️ ☑️ Indicates that all resource origins of requests are allowed.
      CORSAllowAll bool ☑️ ☑️ Allows all CORS values for the pre-flight requests (OPTIONS).
      OnLogging callback or None ☑️ ☑️ Callback function when the server logs information.

      Definition of the above callback functions:

      def OnLogging(microWebSrv2, msg, msgType)
      # <microWebSrv2> is of type MicroWebSrv2
      # <msg> is of type str
      # <msgType> can take following values:
      #    - MicroWebSrv2.DEBUG
      #    - MicroWebSrv2.INFO
      #    - MicroWebSrv2.WARNING
      #    - MicroWebSrv2.ERROR

  • Web Routes

    Web routes allow you to define conditional access paths to specific resources and react to corresponding http requests.
    They also provide the possibility of using freer conditions that can be retrieved as input elements.

    In microWebSrv2, a web route is composed by a processing handler, a requested method, a requested path and an optional name.
    The requested path can also consist of variable parts that can be retrieved as arguments.

    Finally, during an http request, if the method and path match to a route, the processing handler is called with the expected arguments.


    • Route Processing

      A route processing is an handler function decorated by the setting of the route.
      This setting uses the @WebRoute decorator whose definition is as follows:

      @WebRoute(method, routePath, name=None)
      # <method> is the http requested method and must be a not empty string.
      # <routePath> is the http requested path and must be a not empty string.
      # <name> is an optional route name and must be a string or None.

      The handler function definition is as follows:

      @WebRoute(...)
      def RequestHandler(microWebSrv2, request)
      # <microWebSrv2> is of type MicroWebSrv2
      # <request> is of type HttpRequest

      The method argument can be a string but also one of the following constants:
      GET, HEAD, POST, PUT, DELETE, OPTIONS, PATCH

      The routePath argument must always starts by / and specifies the relative URL of the route.

      Note that a route processing handler is global and can be called by any instance of MicroWebSrv2 class.

      🌀 Example of processing handlers:

      @WebRoute(GET, '/my-resource')
      def RequestHandler1(microWebSrv2, request) :
          pass
      @WebRoute(POST, '/test/virtual-page.html', 'myTestRoute')
      def RequestHandler2(microWebSrv2, request) :
          pass
      @WebRoute(OPTIONS, '/')
      def RequestHandler3(microWebSrv2, request) :
          pass

    • Route Arguments

      It is possible to include route arguments that can be retrieved as input elements.
      These arguments are directly defined in the requested path by naming and framing them with <and > as follows:

      @WebRoute(GET, '/users/<id>/profile/<property>')

      In this web route, two arguments are defined: id and property.
      Thus, the route is variable and corresponds to the requested path from which any argument can be used.

      '/users/123/profile/firstname'

      So, the handler function definition is extended as follows:

      @WebRoute(...)
      def RequestHandler(microWebSrv2, request, args)
      # <microWebSrv2> is of type MicroWebSrv2
      # <request> is of type HttpRequest
      # <args> is a dictionary of route arguments

      Now, args can be used like args['id'] or args['property'].
      Note that values can be strings but also integers directly.


    • Route Methods

      ▶️ RegisterRoute(...)

      def RegisterRoute(handler, method, routePath, name=None)
      # Registers a global web route directly, without decorator usage.
      #   - No return value.
      #   - <handler> is the route processing handler and must be a function (see above).
      #   - <method> is the http requested method and must be a not empty string.
      #   - <routePath> is the http requested path and must be a not empty string.
      #   - <name> is an optional route name and must be a string or None.
      # An exception can be raised if arguments are not correct.

      ▶️ ResolveRoute(...)

      def ResolveRoute(method, path)
      # Resolves a web route using a method and a path.
      #   - Returns a RouteResult class if no error occurred and route was found, returns None otherwise.
      #   - <method> is an http method and must be of string type.
      #   - <path> is an http relative path and must be of string type.

      The RouteResult class exposes the following properties:

      Name Type
      Handler processing handler
      Method string
      RoutePath string
      Name string or None
      Args dictionary

      ▶️ PathFromRoute(...)

      def PathFromRoute(routeName, routeArgs={ })
      # Constructs the relative path from the route name and route arguments.
      #   - Returns a string that is the relative path.
      #   - <routeName> is the name of the web route and must be a not empty string.
      #   - <routeArgs> is a dictionary of needed argument names and values.
      # An exception can be raised if arguments are not correct or route was not found.

  • HttpRequest Class

    HttpRequest class represents a received http request by the web server.
    It can be obtained in web route handlers or in modules.
    It also allows you to process the response.


    • HttpRequest instance methods

      ▶️ httpRequest.GetPostedURLEncodedForm(...)

      def GetPostedURLEncodedForm(self)
      # Obtains name/value pairs from an URL encoded form.
      # The http request must have an URL encoded form content.
      #   - Returns a dictionary of name/value pairs (string for both).

      ▶️ httpRequest.GetPostedJSONObject(...)

      def GetPostedJSONObject(self)
      # Obtains the object posted in JSON format.
      # The http request must have a JSON content.
      #   - Returns any type of object or None.

      ▶️ httpRequest.GetHeader(...)

      def GetHeader(self, name)
      # Obtains the value of an http request header.
      #   - Returns always a string value.
      #   - <name> must be a not empty string.
      # An exception can be raised if <name> is not correct.

      ▶️ httpRequest.CheckBasicAuth(...)

      def CheckBasicAuth(self, username, password)
      # Checks if the http request is authenticated with the "Basic" method.
      #   - Returns True if the authentication is correct, returns False otherwise.
      #   - <username> must be a string.
      #   - <password> must be a string.
      # An exception can be raised if arguments are not correct.

      ▶️ httpRequest.CheckBearerAuth(...)

      def CheckBearerAuth(self, token)
      # Checks if the http request is authenticated with the "Bearer" method.
      #   - Returns True if authentication is correct, returns False otherwise.
      #   - <token> is the session token and must be a string.
      # An exception can be raised if <token> is not correct.

    • HttpRequest properties

      Name Type Get Set Description
      UserAddress tuple ☑️ - User remote address of the http connection such as a tuple of (str_ip_addr, int_port).
      IsSSL bool ☑️ - Indicates that the http connection is secured by SSL/TLS security layer with certificate.
      HttpVer str ☑️ - Version of the client protocol of the http connection.
      Method str ☑️ - Name of the method transmitted with this request.
      Path str ☑️ - Path of the resource transmitted with this request.
      QueryString str ☑️ - Full query string transmitted with this request.
      QueryParams dict ☑️ - Parameters of the query string transmitted with this request.
      Host str ☑️ - Hostname transmitted with this request.
      Accept list ☑️ - List of possible content types expected in response to this request.
      AcceptEncodings list ☑️ - List of possible encodings expected in response to this request.
      AcceptLanguages list ☑️ - *List of possible languages expected in response to this request.
      Cookies list ☑️ - List of cookies transmitted with this request.
      CacheControl str ☑️ - Control of cache transmitted with this request.
      Referer str ☑️ - Referer address transmitted with this request.
      ContentType str ☑️ - Type of the content included in this request.
      ContentLength int ☑️ - Length of the content included in this request.
      UserAgent str ☑️ - Name of the client agent transmitted with this request.
      Authorization str ☑️ - Authorization string transmitted with this request.
      Origin str ☑️ - Address of the origin transmitted with this request.
      IsKeepAlive bool ☑️ - Indicates that the http connection can be keep alive.
      IsUpgrade bool ☑️ - Indicates that the http connection must be upgraded.
      Upgrade str ☑️ - Upgrade string transmitted with this request.
      Content memoryview or None ☑️ - Raw data of the content included in this request.
      Response HttpResponse ☑️ - Http response related to this connection.
      XAsyncTCPClient XAsyncTCPClient ☑️ - Asynchronous TCP connection from the XAsyncSockets library.

  • HttpResponse Class

    HttpResponse class is used to manage the reponse of an http request.
    It can be obtained by the Response property of an instantiated HttpRequest.


    • HttpResponse instance methods

      ▶️ httpResponse.SetHeader(...)

      def SetHeader(self, name, value)
      # Set a header to the http response.
      #   - No return value.
      #   - <name> must be a not empty string.
      #   - <value> may be anything but cannot be None.
      # An exception can be raised if arguments are not correct.

      ▶️ httpResponse.SwitchingProtocols(...)

      def SwitchingProtocols(self, upgrade)
      # Sends a special http response to upgrade the connection.
      #   - No return value.
      #   - <upgrade> must be a not empty string.
      # An exception can be raised if <upgrade> is not correct.

      ▶️ httpResponse.ReturnStream(...)

      def ReturnStream(self, code, stream)
      # Sends a stream content to the http response.
      #   - No return value.
      #   - <code> is the http status code and must be a positive integer.
      #   - <stream> must be a readable buffer protocol object.
      # An exception can be raised if arguments are not correct.

      ▶️ httpResponse.Return(...)

      def Return(self, code, content=None)
      # Sends an http response with or without content.
      #   - No return value.
      #   - <code> is the http status code and must be a positive integer.
      #   - <content> must be a string or in bytes or convertible into bytes or None.
      # An exception can be raised if arguments are not correct.

      ▶️ httpResponse.ReturnJSON(...)

      def ReturnJSON(self, code, obj)
      # Sends an http response with a JSON content.
      #   - No return value.
      #   - <code> is the http status code and must be a positive integer.
      #   - <obj> can be anything and will be serialized (stringify process).
      # An exception can be raised if arguments are not correct.

      ▶️ httpResponse.ReturnOk(...)

      def ReturnOk(self, content=None)
      # Sends a success http response with or without content.
      #   - No return value.
      #   - <content> must be a string or in bytes or convertible into bytes or None.
      # An exception can be raised if <content> is not correct.

      ▶️ httpResponse.ReturnOkJSON(...)

      def ReturnOkJSON(self, obj)
      # Sends a success http response with a JSON content.
      #   - No return value.
      #   - <obj> can be anything and will be serialized (stringify process).
      # An exception can be raised if <obj> is not correct.

      ▶️ httpResponse.ReturnFile(...)

      def ReturnFile(self, filename, attachmentName=None)
      # Sends a file to the http response.
      #   - No return value.
      #   - <filename> is the physical path of the file and must be a not empty string.
      #   - <attachmentName> can be the name of the file to save, in string, or None.
      #     If None, the user will see it "on the fly" in his browser, he will can save it otherwise.
      # An exception can be raised if arguments are not correct.

      ▶️ httpResponse.ReturnNotModified(...)

      def ReturnNotModified(self)
      # Sends a not modified http response.
      # Used in resources caching context.
      #   - No return value.

      ▶️ httpResponse.ReturnRedirect(...)

      def ReturnRedirect(self, location)
      # Sends a temporary redirect http response.
      # Used to move the user to a new url.
      #   - No return value.
      #   - <location> is the relative or absolute URL and must be a not empty string.
      # An exception can be raised if <location> is not correct.

      ▶️ httpResponse.ReturnBadRequest(...)

      def ReturnBadRequest(self)
      # Sends a bad request http response.
      # Used for user request error.
      #   - No return value.

      ▶️ httpResponse.ReturnUnauthorized(...)

      def ReturnUnauthorized(self, typeName, realm=None)
      # Sends an unauthorized http response.
      # Used if the user needs to authenticate.
      #   - No return value.
      #   - <typeName> is the name of required authentication and must be a not empty string.
      #   - <realm> is a name for the protected resource and can be a string or None.
      # An exception can be raised if arguments are not correct.

      ▶️ httpResponse.ReturnForbidden(...)

      def ReturnForbidden(self)
      # Sends a forbidden http response.
      # Used to indicate a denied access.
      #   - No return value.

      ▶️ httpResponse.ReturnNotFound(...)

      def ReturnNotFound(self)
      # Sends a not found http response.
      # Used to indicate that the resource does not exist.
      #   - No return value.

      ▶️ httpResponse.ReturnMethodNotAllowed(...)

      def ReturnMethodNotAllowed(self)
      # Sends a method not allowed http response.
      # Used if the method is not supported for resource.
      #   - No return value.

      ▶️ httpResponse.ReturnEntityTooLarge(...)

      def ReturnEntityTooLarge(self)
      # Sends an entity too large http response.
      # Used for an excessive content size.
      #   - No return value.

      ▶️ httpResponse.ReturnInternalServerError(...)

      def ReturnInternalServerError(self)
      # Sends an internal server error http response.
      # Used if an error has occurred.
      #   - No return value.

      ▶️ httpResponse.ReturnNotImplemented(...)

      def ReturnNotImplemented(self)
      # Sends a not implemented http response.
      # Used in case of a non-existent process of the resource.
      #   - No return value.

      ▶️ httpResponse.ReturnServiceUnavailable(...)

      def ReturnServiceUnavailable(self)
      # Sends a service unavailable http response.
      # Used if it is currently impossible to process the request.
      #   - No return value.

      ▶️ httpResponse.ReturnBasicAuthRequired(...)

      def ReturnBasicAuthRequired(self)
      # Sends an http response to indicate that "Basic" authentication is required.
      #   - No return value.

      ▶️ httpResponse.ReturnBearerAuthRequired(...)

      def ReturnBearerAuthRequired(self)
      # Sends an http response to indicate that "Bearer" authentication is required.
      #   - No return value.

    • HttpResponse properties

      Name Type Get Set Description
      Request HttpRequest ☑️ - Http request related to this response.
      UserAddress tuple ☑️ - User remote address of the http connection such as a tuple of (str_ip_addr, int_port).
      IsSSL bool ☑️ - Indicates that the http connection is secured by SSL/TLS security layer with certificate.
      AllowCaching bool ☑️ ☑️ Indicates to the user the possible caching of this response.
      AccessControlAllowOrigin str or None ☑️ ☑️ Indicates to the user the allowed resource origin.
      ContentType str or None ☑️ ☑️ Type of the content of this response.
      ContentCharset str or None ☑️ ☑️ Encoding charset used for the content of this response.
      ContentLength int ☑️ ☑️ Length of the content of this response.
      HeadersSent bool ☑️ - Indicates that response http headers was already sent.
      OnSent callback or None ☑️ ☑️ Callback function when response is fully sent.

      Definition of the above callback functions:

      def OnSent(microWebSrv2, response)
      # <microWebSrv2> is of type MicroWebSrv2
      # <response> is of type HttpResponse

  • Additional modules

    microWebSrv2 supports additional modules that can be called during the processing of a web request and can then decide whether or not to intercept it.
    Modules can simply analyze http requests or responding to them so that they cannot continue their normal pipe-line processing.

    A module file must be placed in the "/mods" directory of the package and must define a class of the same name.
    In addition, this class must implement the OnRequest(...) method that will be called at each http request.

    🌀 Example of a module named "TestMod.py":

    class TestMod :
    
        def OnRequest(self, microWebSrv2, request) :
            print('TestMod: Request received from %s:%s' % request.UserAddress)

    • WebSockets Module

      WebSockets module must be loaded first by microWebSrv2 to process WebSocket connections.
      These are fully managed asynchronous I/Os and really many connections can be processed.
      After module loaded, do not forget to assign the callback OnWebSocketAccepted.
      If you need to select and process a sub-protocol, you must assign the callback OnWebSocketProtocol.

      from MicroWebSrv2 import *
      
      WS_CHAT_SUB_PROTOCOL = 'myGreatChat-v1'
      
      def OnWebSocketProtocol(microWebSrv2, protocols) :
          if WS_CHAT_SUB_PROTOCOL in protocols :
              return WS_CHAT_SUB_PROTOCOL
      
      def OnWebSocketAccepted(microWebSrv2, webSocket) :
          print('New WebSocket (myGreatChat proto) accepted from %s:%s.' % webSocket.Request.UserAddress)
      
      wsMod = MicroWebSrv2.LoadModule('WebSockets')
      wsMod.OnWebSocketProtocol = OnWebSocketProtocol
      wsMod.OnWebSocketAccepted = OnWebSocketAccepted

      • WebSockets module properties

        Name Type Get Set Description
        OnWebSocketProtocol callback or None ☑️ ☑️ Callback function when a new WebSocket connection negociates a sub-protocol.
        OnWebSocketAccepted callback or None ☑️ ☑️ Callback function when a new WebSocket connection is accepted.

        Definition of the above callback functions:

        def OnWebSocketProtocol(microWebSrv2, protocols)
        # <microWebSrv2> is of type MicroWebSrv2
        # <protocols> is a string list of proposed protocols
        # RETURN: If you select a protocol, you must return it (the same as in the list)

        def OnWebSocketAccepted(microWebSrv2, webSocket)
        # <microWebSrv2> is of type MicroWebSrv2
        # <webSocket> is of type WebSocket

      • WebSocket Class

        WebSocket class is automatically instantiated by WebSockets module.
        A WebSocket can be obtained when a new connection is accepted in the callback OnWebSocketAccepted.
        It is also important to assign WebSocket callbacks in order to receive the various events.


        • WebSocket instance methods

          ▶️ webSocket.SendTextMessage(...)

          def SendTextMessage(self, msg)
          # Sends a text message through the WebSocket.
          #   - Returns True or False.
          #   - <msg> must be a not empty string.
          # An exception can be raised if <msg> is not correct.

          ▶️ webSocket.SendBinaryMessage(...)

          def SendBinaryMessage(self, msg)
          # Sends a binary message through the WebSocket.
          #   - Returns True or False.
          #   - <msg> must be in bytes or convertible into bytes and not empty.
          # An exception can be raised if <msg> is not correct.

          ▶️ webSocket.Close(...)

          def Close(self)
          # Closes the WebSocket.
          #   - No return value.

        • WebSocket properties

          Name Type Get Set Description
          Request HttpRequest ☑️ - Http request related to this connection.
          IsClosed bool ☑️ - Indicates that connection is closed.
          WaitFrameTimeoutSec int ☑️ ☑️ Timeout in seconds to waiting next frame.
          MaxRecvMessageLength int or None ☑️ ☑️ Maximum length of messages to receive.
          OnTextMessage callback or None ☑️ ☑️ Callback function to receive text messages.
          OnBinaryMessage callback or None ☑️ ☑️ Callback function to receive binary messages.
          OnClosed callback or None ☑️ ☑️ Callback function when connection is closed.

          Definition of the above callback functions:

          def OnTextMessage(webSocket, msg)
          # <webSocket> is of type WebSocket
          # <msg> is of type str

          def OnBinaryMessage(webSocket, msg)
          # <webSocket> is of type WebSocket
          # <msg> is of type memoryview

          def OnClosed(webSocket)
          # <webSocket> is of type WebSocket

    • PyhtmlTemplate Module

      PyhtmlTemplate module must be loaded first by microWebSrv2 to process .pyhtml pages.
      With it, you will be able to render HTML pages directly integrating Python/MicroPython language.

      from MicroWebSrv2 import *
      
      pyhtmlTemplateMod = MicroWebSrv2.LoadModule('PyhtmlTemplate')
      pyhtmlTemplateMod.ShowDebug = True

      In the pages .pyhtml, you must use the following instructions:

      Instruction Code schema
      PY {{ py }} Python code {{ end }}
      IF {{ if Python condition }} html bloc {{ end }}
      ELIF {{ elif Python condition }} html bloc {{ end }}
      ELSE {{ else }} html bloc {{ end }}
      FOR {{ for identifier in Python iterator }} html bloc {{ end }}
      Expression {{ Python expression }}

      🌀 See the test.pyhtml page for the example:

      Pyhtml Code

      Pyhtml Page


      • PyhtmlTemplate module instance methods

        ▶️ pyhtmlTemplateMod.SetGlobalVar(...)

        def SetGlobalVar(self, globalVarName, globalVar)
        # Defines a global variable accessible by all pyhtml pages.
        #   - No return value.
        #   - <globalVarName> must be a not empty string.
        #   - <globalVar> must be an object or None.
        # An exception can be raised if <globalVarName> is not correct.

        ▶️ pyhtmlTemplateMod.GetGlobalVar(...)

        def GetGlobalVar(self, globalVarName)
        # Retrieves a global variable accessible by all pyhtml pages.
        #   - Returns an object or None.
        #   - <globalVarName> must be a not empty string.
        # An exception can be raised if <globalVarName> is not correct.

      • PyhtmlTemplate module properties

        Name Type Get Set Description
        ShowDebug bool ☑️ ☑️ Enables debugging on web pages.

😉  Author

Jean-Christophe Bos (:fr:)


✴️  License



microwebsrv2's People

Contributors

amotl avatar hecatron avatar jczic avatar julianz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

microwebsrv2's Issues

Cannot start webserver, allocate_lock import error

When I try to start the webserver, I always get the following message on a ESP32 using MicroPython (LoBo version)

Traceback (most recent call last):
File "main.py", line 2, in
File "webServer.py", line 1, in
File "MicroWebSrv2/init.py", line 15, in
File "MicroWebSrv2/libs/XAsyncSockets.py", line 7, in
ImportError: cannot import name allocate_lock
MicroPython ESP32_LoBo_v3.2.24 - 2018-09-06 on ESP32&psRAM board with ESP32
Type "help()" for more information.

Webroutes handler and .pyhtml files are not working on lopy4 with Pysense

I am using lopy4 with Pysense. I have copied all files of project into lopy4. After connecting with lopy4 wifi, I can only access index.htlm and wstest.html pages are not working. I am always getting error loclhost refused to connect. while testing this project on linux and running it through python main.py then it's working fine. But why it's not working on microcontroller lopy4 i have already updated lopy4 to latest version.

Permission error after running it right out of the box

   ---------------------------
   - Python pkg MicroWebSrv2 -
   -      version 2.0.6      -
   -     by JC`zic & HC2     -
   ---------------------------

MWS2-INFO> Stops the managed pool.
Traceback (most recent call last):
File "/Users/johndraper/Documents/Projects/WhisperMagic/MicroWebSrv2-master/MicroWebSrv2/libs/XAsyncSockets.py", line 375, in Create
srvSocket.bind(srvAddr)
PermissionError: [Errno 13] Permission denied

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/Users/johndraper/Documents/Projects/WhisperMagic/MicroWebSrv2-master/MicroWebSrv2/microWebSrv2.py", line 191, in StartInPool
bufSlots = xBufSlots )
File "/Users/johndraper/Documents/Projects/WhisperMagic/MicroWebSrv2-master/MicroWebSrv2/libs/XAsyncSockets.py", line 378, in Create
raise XAsyncTCPServerException('Create : Error to binding the TCP server on this address.')
MicroWebSrv2.libs.XAsyncSockets.XAsyncTCPServerException: Create : Error to binding the TCP server on this address.

I downloaded it, UnZipped it, and without any modifications to the file, this is what I get.
Can someone please tell me what I have to do to deal with this error.

Should my "main.py" module be set for executable.

Websocket packets are buffered and sent per seconds instead of real time

Hi @jczic - great work on this web server, excellent quality docs as well.

I've implemented the server on a Pycom G01 (esp32) and it seems to be running well. I also run a websocket for a specific webUI page displaying real-time data to a driver using gps read-outs.

I need the websocket data to update every 200ms (5hz) and in my code this is easily achievable - however the server seems to be buffering the data and sending as batches.

I've wiresharked it to make sure its not on the client side - and in below image you can see the bundles of packets being sent together every 1 second.

image

Implementation code - pretty much the example code.

 wsMod = MicroWebSrv2.LoadModule('WebSockets')
  wsMod.OnWebSocketAccepted = OnWebSocketAccepted
  # Instanciates the MicroWebSrv2 class,
  mws2 = MicroWebSrv2()
  mws2.RootPath = '/flash/'
  mws2.BindAddress = ('192.168.4.1', 5000)
  # For embedded MicroPython, use a very light configuration,
  mws2.SetEmbeddedConfig()
  
  # All pages not found will be redirected to the home '/',
  mws2.NotFoundURL = '/'
  mws2.StartManaged(parllProcCount=1,procStackSize = 10*1024)

Could really appreciate your thoughts on this.

I've managed to accidentality get it to send data in real time a couple of times while trying to fix the issue - by setting parllProcCount =2 but this causes other instability issues and core dumps.

SSL library

Hello,

I am trying to enable SSL on my ESP32 Micropython latest compiled FW, but unfortunately your following requirements for SSL python library are hard to comply:

The ssl library must be implements SSLContext on Python 
version to support secured web server

The ussl (https://github.com/micropython/micropython-lib/blob/master/ssl/ssl.py) library that Micropython uses doesn't have create_default_context method and SSLContext class and , only wrap_socket method from it.

Same goes for Pycom: https://docs.pycom.io/firmwareapi/micropython/ussl/

The only one I found that has everything, is CPython full implementation of SSL.
https://github.com/python/cpython/blob/master/Lib/ssl.py

But then again, micropython doesn't have all those dependencies to even load it, starting from importing Enum module... Basically it needs to be rewritten how it was done with USSL.

Could you please clarify which library are you using that has that SSLContext class and create_default_context method?

Is it possible to adopt MicroWebSrv2 to comply with Micropython implementation of SSL somehow?

Thanks!

Route Arguments Not Working

I am running into an issue when trying to use Route Arguments. I defined the web route as:

@webroute(GET, '/Key/<key_val>/Data/')

but when a GET request such as:

GET /Key/DATA_UPLOAD_METHOD/Data/LoRa

is sent the program does not recognize it as a valid route. and I get:

MWS2-DEBUG> From 192.168.4.2:51137 GET /Key/DATA_UPLOAD_METHOD/Data/LoRa >> [307] Temporary Redirect

File Upload

Is it possible to receive a file upload via HttpRequest?

Scheduled background task feature request.

I apologize if this is the wrong place or if this is unrelated specifically to MicroWebSrv2.

I will be deploying an ESP32 and was hoping for to be a webserver and found your code.

Like Flask and Celery, is there a way to get MicroWebSrv2 to run scheduled tasks (such as monitoring IO sensors)?

Thanks for your awesome work!

Python functions seem to be called only once on .pyhtml

I have the following (much simplified down) code
{{ py }}
import globals
import adc
{{ end }}

setInterval( update, 2000 ); 

//  Show the readings from the device

function update(){

    {{ adc.ADCRead() }}

    var solar = {{ globals.adcValue }}

}

This will call the python function ADCRead() only once on the first time the loop executes.
Subsequent loops do NOT call the function.

I am sure it is me but.... maybe not

Cannot load module "PyhtmlTemplate".

Hi,

I tried to use the MicroWebSrv2 on my esp32 with the main.py on the MicroWebSrv2-master directory and I get this error

File "main.py", line 148, in
File "MicroWebSrv2/microWebSrv2.py", line 136, in LoadModule
MicroWebSrv2Exception: Cannot load module "PyhtmlTemplate".

I am using uPyCraft and I can see the file inside the mods directory.
I don't understand why it can't load it?

Thanks

Chris

which scripts py copy?

hello congratulations for the work, I'm in doubt about which py scripts to copy to my esp32, or should I copy everything?

pyhtml tot being served in lopy

I have installed the server on lopy But the files apart from index.html are not being served, I get a 404, even the png image is not being loaded (404 from the network tab of chrome dev tools. Is it a file format issue with lopy, is there a fix for this?

MicroWebSrv2.NotFoundURL no effect on ESP32

fake code:

from MicroWebSrv2 import *

server = MicroWebSrv2()
server.RootPath = "web"
server.NotFoundURL = "/"
server.StartManaged()

while server.IsRunning:
    sleep(1)

In ESP32, client connected to server, rqeust root path, server cause 307 redirect, in this time, the default file (index.html etc) is not loaded, and then client will request root path again and server respond a 307 redirect, and loop again, and again....

I'm using MicroPython official lastest firmware of ESP32.

"No response was sent from route" error always raised

The error

MWS2-DEBUG> From 192.168.86.48:61468 GET /test-post >> [200] OK
MWS2-WARNING> No response was sent from route TestPost1/2.
MWS2-DEBUG> From 192.168.86.48:61539   >> [501] Not Implemented

is raised for any route response, for example from the /test-post route in the example server, which calls request.Response.ReturnOk. But this also applies to anything that eventually calls request.Response.Return.

It can be reproduced by running the example server from main.py and navigating to http://localhost/test-post, and observing the server logs.

This supposedly arises from the absence of headers, but ReturnOk generates and transmits headers itself. My browser receives the headers and the content OK. Furthermore, if I add a response-finished callback set under request.Response.OnSent, I can confirm the response is completed successfully (including headers).

Indeed, querying request.Response._hdrSent returns False at any point, and request.Response._headers also returns {}, including after a successfully finished response (querying from within the @WebRoute callback function).

I can remove the error by duplicating the Return call:

request.Response.ReturnOk(content)
request.Response.ReturnOk(content)

What is especially odd is, if I query the HttpResponse object before and after sending a response

    @WebRoute(GET, '/test', name="test")
    def _handler(server, request):
        print('request:', request)
        print('response:', request.Response)
        request.Response.ReturnOkJSON('test')
        print('request:', request)
        print('response:', request.Response) # different memory address than before!

the response object has been recreated at a new spot in memory. This does not make sense to me, since the HttpResponse object is instantiated as part of the HttpRequest object, which in fact does not change throughout the handler.

My connection is currently quite slow, maybe this could be caused by a timeout issue? But based on the observations above, it seems more fundamental.

Add gitignore to skip *.pyc

One minor addition would be a .gitignore to skip the *.pyc files that are generated when running this beautiful piece of software on a Desktop machine (OSX).

Cannot load module

Hi! It's report "Cannot load module "PyhtmlTemplate" or "Cannot load module "WebSockets" if i commented out PyhtmlTemplate loads.
I copied the entire MicroWebSrv2 folder with all content to my ESP32. Python version is newest.

NameError: name 'WebRoute' isn't defined

Hi there,

I've just had a go at running the example on my ESP32 but seem to be failing. I have uploaded the MicroWebSrv2 folder to the device as shown below:

image

Also, I copied the main.py script and added some code inside boot.py to connect the device to my network. However, when the device tries to run main.py I get the following error:

Traceback (most recent call last):
  File "main.py", line 11, in <module>
NameError: name 'WebRoute' isn't defined

Any help or suggestions would be much appreciated. :)

cannot load module websockets

Traceback (most recent call last):
File "", line 148, in
File "MicroWebSrv2/microWebSrv2.py", line 136, in LoadModule
MicroWebSrv2Exception: Cannot load module "WebSockets".

Restarting webserver after soft reboot

Dear Jean-Christophe,

we are very happy about the new release of your fine webserver library. For now, it looks like it works very stable on one of our FiPy devices sitting on our workbench.

We are in the process of porting the Terkin Datalogger [1] to MicroWebSrv2 and experienced this issue after exiting the program using CTRL+C and invoking a soft reboot using CTRL+D.

It looks like the listener does not go away and so, MicroWebSrv2 can do nothing about its IsRunning method suitable for detecting this. The Webserver isn't actually running but it looks like XAsyncSocket does not give up it's listening socket on program termination, so it is obvious it can't bind again to the same port after coming back from the soft reboot.

It currently looks like that for us:

PYB: soft reboot

[...]

   15.6195 [terkin.network.core      ] INFO   : Setting up HTTP API
   15.6389 [terkin.api.http          ] INFO   : Starting HTTP server
MWS2-INFO> Stops the managed pool.
   15.6814 [terkin.network.core      ] ERROR  : Starting HTTP server failed
Traceback (most recent call last):
  File "network/core.py", line 126, in start_services
  File "network/core.py", line 146, in start_httpserver
  File "api/http.py", line 70, in start
  File "MicroWebSrv2/microWebSrv2.py", line 220, in StartManaged
  File "MicroWebSrv2/microWebSrv2.py", line 215, in StartManaged
  File "MicroWebSrv2/microWebSrv2.py", line 215, in StartManaged
  File "MicroWebSrv2/microWebSrv2.py", line 207, in StartManaged
  File "MicroWebSrv2/microWebSrv2.py", line 185, in StartInPool
MicroWebSrv2Exception: Cannot bind server on 0.0.0.0:80.

I believe we had a global variable on the module level to keep a reference to the MicroWebSrv reference, but this eventually stopped working after upgrading to a more recent version of Pycom MicroPython. We might also be wrong on that so MicroWebSrv might have been more graceful to us.

We figure it would be the best thing to invoke MicroWebSrv2 before shutting down, i.e. when quitting the program through CTRL+C or just before the "soft reboot".

So, we are humbly asking whether you would see a way to get around this issue?

With kind regards,
Andreas.

[1] https://github.com/hiveeyes/hiveeyes-micropython-firmware

No module named '_thread'

Hello,

I have Pyboard and TILE SENSA sensor (temperature&humidity) and I would love to interpret values from the sensor to my own webserver and make sort of my own meteostation which I can access from my laptop or smarth phone.

The problem is when I try to start the "main.py" (renamed to "start.py" in my case). The console pops:
ImportError: no module named '_thread'

I tried googling this proble, but I found no answer to my particular problem.
Only thing that cause this issue is Micropython version, but since this is also for Pyboards, it should not be the problem.

Thnaks for any help or answers in advance :]

image

403 when trying to load .pyhtml template?

I know I have been posting about silly path errors here before. It has finally been solved. But there is one thing I can't get to work. I have to .pyhtml-templates, and when I try to load these, I just get a "403 forbidden" error with the kind of strange message "Request forbidden -- authorization will not help.". Authorization is not the option, so what do I do?

Template names:
about.pyhtml and network.pythml
Request URLs:
192.168.4.1/templates/about.pyhtml (same response as mentioned above)
192.168.4.1/templates/network.pyhtml (same response as mentioned above)
Rootpath:
/flash/server/www
The templates are in the "templates" folder, a subfolder of www.

how to prevent escaping HTML tags in GlobalVars?

using PyhtmlTemplate, if I do something like this:

pyhtmlTemplateMod.SetGlobalVar('Header', '<html><head><title>markup as string</title></head><body>')

all my html tags are escaped. is there a way to prevent that? sorry if this is a silly question.

Serve static files from SD card.

Hi! Is there any documentation that shows how to serve web static files (HTML, CSS, JS) from the SD card?

I am sorry if I missed something. I just started playing with this library and MicroPython.

pyboard 'socket' object has no attribute 'fileno'

I found that socket has no attribute fileno when using MicroWebSrv2 on pyboard.

       ---------------------------
       - Python pkg MicroWebSrv2 -
       -      version 2.0.6      -
       -     by JC`zic & HC2     -
       ---------------------------

MWS2-INFO> Stops the managed pool.
Traceback (most recent call last):
  File "main.py", line 39, in <module>
  File "MicroWebSrv2/microWebSrv2.py", line 223, in StartManaged
  File "MicroWebSrv2/microWebSrv2.py", line 215, in StartManaged
  File "MicroWebSrv2/microWebSrv2.py", line 190, in StartInPool
  File "MicroWebSrv2/libs/XAsyncSockets.py", line 381, in Create
  File "MicroWebSrv2/libs/XAsyncSockets.py", line 392, in __init__
  File "MicroWebSrv2/libs/XAsyncSockets.py", line 263, in __init__
  File "MicroWebSrv2/libs/XAsyncSockets.py", line 151, in AddAsyncSocket
  File "MicroWebSrv2/libs/XAsyncSockets.py", line 56, in _addSocket
AttributeError: 'socket' object has no attribute 'fileno'

Event at the end of a response

But I have another question... Please

@webroute(POST, '/test-post', name='TestPost2/2')
def RequestTestPost(microWebSrv2, request) :
data = request.GetPostedURLEncodedForm()
try :

    first = data['Firstname']
    last  = data['Lastname']
    
    f = open('data.txt','w')
    f.write(first+'\n')
    f.write(last)
    f.close()

except :
    request.Response.ReturnBadRequest()
    return
content   = """\
<!DOCTYPE html>
<html>
    <head>
        <title>POST 2/2</title>
    </head>
    <body>
        <h2>MicroWebSrv2 - POST 2/2</h2>
        your information has been saved.. Restrating the microcontroller :)<br />
    </body>
</html>
"""
request.Response.ReturnOk(content)
machine.reset()

After saving the first name and last name to a file. I want to return a response and then I want to reboot the microcontroller. but It is only rebooting the but not showing the response in the browser.

Originally posted by @aqieez in #10 (comment)

memory allocation failed

Hello,

Thank you for your good documented package. I try to run it on a ESP32 with only two other packages, but I get a memory issue for importing HttpResponse

The complete message seems like this:

Traceback (most recent call last):
  File "main.py", line 11, in <module>
  File "/lib/MicroWebSrv2/__init__.py", line 18, in <module>
  File "/lib/MicroWebSrv2/microWebSrv2.py", line 8, in <module>
  File "/lib/MicroWebSrv2/httpRequest.py", line 8, in <module>
MemoryError: memory allocation failed, allocating 136 bytes

Have you an idea? It's every run 136 bytes
In another post I have red, dividing the file in to is possible, but I don't know, how I can divide a class...
Thank you very much!

How to run (in proper way) second function in parallel?

Hello,

Good pice of code! Big up! Thanks for your work.

I have one question. I'm looking for a proper method to run a function in parallel to web server. I would like to check every 30 seconds my temperature and send values to MQTT server. This should be independent of normal web server activity. What is the best way to do this using MicroWebSev2?

Best regards,
MvincM

Serving static files?

I have been trying to get my instance of MWS2 to serve static files, but it doesn't work as I expect.
I have set the mws2.RootPath = "/flash/server/www".
The file contents of this directory include several files. I tried with the exact filename both directly after 192.168.4.1 (like so: 192.168.4.1/figure.svg) and also 192.168.4.1/static/figure.svg (I was unsure which one was right).

What can be wrong here?

AttributeError: 'module' object has no attribute 'CERT_NONE'

I am getting the following error:

>> from MicroWebSrv2  import *

       ---------------------------
       - Python pkg MicroWebSrv2 -
       -      version 2.0.0      -
       -     by JC`zic & HC2     -
       ---------------------------

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "MicroWebSrv2/__init__.py", line 15, in <module>
  File "MicroWebSrv2/libs/XAsyncSockets.py", line 433, in <module>
  File "MicroWebSrv2/libs/XAsyncSockets.py", line 756, in XAsyncTCPClient
AttributeError: 'module' object has no attribute 'CERT_NONE'

This is on an ESP32 (Wroom DevBoard) with the official 1.11 MicroPython installed.

Show real-time data

Hi! Thanks for this micropython tool, I have worked with it and I'm learning a lot!

I need some help, can you send me a example of how show real-time data in a propely way?
I have an analog sensor in my esp8266, I would like to see the data in a page.

Greetings! and thanks in advance

How do I load .pyhtml templates?

This may sound like a silly question - and it probably is, because I should have been able to get this to work by now.

I want/need to include a .pyhtml file in the application I am making.
I looked in the source code, and the PyHTML extension should automatically send and render the template when I go to a page with the name of my PyHTML and .pyhtml in the end, correct?

So, if I have a file named "page.pyhtml", I should simply be able to visit /page.pyhtml?
Because, that gives me a 404 error.

I have initialized the PyHTML addon and I have enabled debugging, but I did not get any output from the debugger.

Server redirects too many times.

I am using lopy4 with Pysense. I have copied all files of the project into lopy4. After connecting with lopy4 wifi, in my browser url i am typing http://192.168.4.1/ and hitting enter. But i am getting error 192.168.4.1 redirected you too many times. I am having this issue after new update on MicroWebSrv2 This the output i am getting in Atom console.

MWS2-INFO> Server listening on 0.0.0.0:80.
MWS2-INFO> Starts the managed pool to wait for I/O events.
MWS2-DEBUG> From 192.168.4.2:50974 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:50976 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:52594 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:52596 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:52646 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:52656 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:52658 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53452 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53454 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53472 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53474 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53476 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53486 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53488 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53498 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53500 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53510 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53610 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53650 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53672 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53674 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53684 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53686 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53708 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53794 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53804 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53806 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53816 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53818 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53876 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53878 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53888 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53890 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53900 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53908 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53960 GET / >> [307] Temporary Redirect
MWS2-DEBUG> From 192.168.4.2:53962 GET / >> [307] Temporary Redirec
Any idea what is wrong? is it some kinda permission problem or something? Please help.

MicroWebSrv2Exception: Cannot load module "PyhtmlTemplate". (v2.0.3)

I get an exception in modClass = getattr(module, modName)
The exception: 'module' object has no attribute 'PyhtmlTemplate'

Traceback (most recent call last):
File "main.py", line 147, in
File "MicroWebSrv2/microWebSrv2.py", line 133, in LoadModule
MicroWebSrv2Exception: Cannot load module "PyhtmlTemplate".
MicroPython v1.11-580-g973f68780 on 2019-11-20; ESP32 module with ESP32

os.listdir()
['boot.py', 'dev-requirements.txt', 'requirements.txt', 'main.py', 'project.pymakr', 'wifiConfig.json', 'wifiConnect.py', 'lib', 'www', 'MicroWebSrv2']
os.listdir('MicroWebSrv2')
['libs', 'mods', 'httpRequest.py', 'httpResponse.py', 'microWebSrv2.py', 'webRoute.py', 'init.py']
os.listdir('MicroWebSrv2/mods')
['PyhtmlTemplate.py', 'WebSockets.py']

Please help

Timer and webSocket. Is there any conflict?

Websocket runs for about 5 minutes,,,and hangs. my situation is like this:
1: One periodic timer (1000ms), two one-shot timer(200ms) , Timers trigger callback function for UART communication and parse data to json.
2: While json is ready, it would be sent to websocket.

It runs well about 5 minutes, then the periodic timer not trigger callback function any more.
Then, I did the following checks :
1: check the periodic timer status : Timer(3f819ae0; alarm_en=1, auto_reload=1, counter_en=1)
    so, the timer is enabled and auto_reload=1 , counter still running. Timer is no problem
2: check the browser's socket,  I opened 4 tabs , 4 sockets' status are ESTB .
   so, browser side is ok too.
3: ESP32's socket number is 4 . also correct.

But the timer just doesn't trigger callback function. and MicroWebSrv2 stop serving new connection.

Could you help to solve this problem?

Default pages and directory resources

Can't get default pages for directory resources to work.

It is ok to directly navigate to /index.html. Unfortunately, can't navigate to index.html by simply using / in the URL.

What am I missing? Thanks.

MicroWebSrv2Exception: Not enough memory to allocate slots.

Error messages is as below: "not enough memory" . I have used MicroWebSrv version 1. It never has this problem,, Could you tell me how to avoid not engough memeory problem? thanks

and the second issue: MicroWebSrv can not coexist with mqtt


from MicroWebSrv2 import *

   ---------------------------
   - Python pkg MicroWebSrv2 -
   -      version 2.0.3      -
   -     by JC`zic & HC2     -
   ---------------------------

mws = MicroWebSrv2()
mws.StartManaged()
MWS2-INFO> Stops the managed pool.
Traceback (most recent call last):
File "", line 1, in
File "MicroWebSrv2/microWebSrv2.py", line 221, in StartManaged
File "MicroWebSrv2/microWebSrv2.py", line 213, in StartManaged
File "MicroWebSrv2/microWebSrv2.py", line 184, in StartInPool
MicroWebSrv2Exception: Not enough memory to allocate slots.

MicroWebSrv2 : Server is too slow

Hello, I am using a Wipy(Firmware 1.20.1.r2):
I created a server with MicroWebSrv2 from jzic.
My settings are:

procStackSize=8*1024
The same as mws2.SetEmbeddedConfig()

ConnQueueCapacity = 8 BufferSlotsCount = 16 BufferSlotSize = 1024 KeepAllocBufferSlots = True MaxRequestContentLength = 16*1024

When , I go in the website, i just asking 2 jsons files every 10 secs , but with the time flying, the responses make too much time to come.
If somebody here have a solution, or a better configuration for the Wipy.
:)

MicroWebSrv2Exception: Cannot load module "PyhtmlTemplate"

Hello.
I found if the MicroWebSrv2 folder in another place, the system can't found the module in the mods folder.
When I use MicroWebSrv2.LoadModule('PyhtmlTemplate')
The traceback is
src.MicroWebSrv2.microWebSrv2.MicroWebSrv2Exception: Cannot load module "PyhtmlTemplate".


Change the code in microWebSrc2.py can fix this error in my case. But this way is not good.

@staticmethod
    def LoadModule(modName) :
        if not isinstance(modName, str) or len(modName) == 0 :
            raise ValueError('"modName" must be a not empty string.')
        if modName in MicroWebSrv2._modules :
            raise MicroWebSrv2Exception('Module "%s" is already loaded.' % modName)
        try :
            # old
            # module   = __import__('MicroWebSrv2.mods.%s' % modName, { }, { }, [modName])
            # new
            module = __import__('src.MicroWebSrv2.mods.%s' % modName, {}, {}, [modName])
            modClass = getattr(module, modName)
            if type(modClass) is not type :
                raise Exception
            modInstance = modClass()
            MicroWebSrv2._modules[modName] = modInstance
            return modInstance
        except :
            raise MicroWebSrv2Exception('Cannot load module "%s".' % modName)

XAsyncTCPClientException on ESP32, not reproducable in CPython

Heya,

I created some lightweight code to test an endpoint:

from MicroWebSrv2.microWebSrv2 import MicroWebSrv2, WebRoute, GET
from time import sleep


@WebRoute(GET, "/test")
def testGet(microWebSrv2, request):
    content = """
    <!DOCTYPE html>
    <html>
    <head><title>Hello World</title></head>
    <body><p>hello world</p></body>
    </html>
    """
    print("Received Request")
    print(request)
    request.Response.Return(200, content=content)


mws2 = MicroWebSrv2()
mws2.BindAddress = ("0.0.0.0", 8080)
mws2.SetEmbeddedConfig()
mws2.StartManaged()

try:
    while True:
        sleep(1)
except KeyboardInterrupt:
    mws2.Stop()

Running this code in regular python works fine. However when I load it onto an ESP32 and connect to the web server, this error gets raised every request:

AP set up successfully
('192.168.4.1', '255.255.255.0', '192.168.4.1', '0.0.0.0')

       ---------------------------
       - Python pkg MicroWebSrv2 -
       -      version 2.0.6      -
       -     by JC`zic & HC2     -
       ---------------------------

 + [@WebRoute] GET /test
MWS2-INFO> Server listening on 0.0.0.0:80.
MWS2-INFO> Starts the managed pool to wait for I/O events.
Received Request
<HttpRequest object at 3ffe6870>
MWS2-ERROR> Exception raised from route GET /test: 'HttpResponse' object has no attribute 'IsSSL'
Unhandled exception in thread started by <bound_method>
Traceback (most recent call last):
  File "MicroWebSrv2/libs/XAsyncSockets.py", line 131, in _processWaitEvents
  File "MicroWebSrv2/libs/XAsyncSockets.py", line 586, in OnReadyForReading
XAsyncTCPClientException: Error when handling the "OnDataRecv" event : 'HttpResponse' object has no attribute 'IsSSL'

Don't know what's causing this - some help fixing this would be appreciated. Cheers

MemoryError: memory allocation failed, allocating 136 bytes

tried now multiple versions of MicroPython, up to 1.13. But always get the same error on my ESP32 NodeMCU...
Already split my files as much as possible, but the problem is the MicroWebSrv2 code...
Also tried to compile the MicroWebSrv2 code via mpy-cross, but placing them into the same MicroWebSrv2 directory doesn't work - and don't know where to move them instead. I use MacOS 10.15.6 by the way.
Traceback (most recent call last) File "boot.py", line 46, in <module> File "stripe.py", line 79, in on File "stripe.py", line 30, in start_server File "MicroWebSrv2/__init__.py", line 18, in <module> File "MicroWebSrv2/microWebSrv2.py", line 13, in <module> File "MicroWebSrv2/httpRequest.py", line 8, in <module> MemoryError: memory allocation failed, allocating 136 bytes

MemoryError on PyCom SiPy

Hi! I previously used a library/web framework called picoweb on my PyCom, but I just found this new version of MicroWebSrv which seems much better documented to me!

However, when loading the module on a SiPy and trying to import it, I get a MemoryError:

Traceback (most recent call last):
  File "main.py", line 10, in <module>
  File "serving_static/server.py", line 3, in <module>
  File "/flash/lib/MicroWebSrv2/__init__.py", line 14, in <module>
MemoryError: memory allocation failed, allocating 136 byte
Pycom MicroPython 1.20.0.rc13 [v1.9.4-94bb382] on 2019-08-22; SiPy with ESP32
Type "help()" for more information.

Do you have any recommendations on how to get it to work, since MicroWebSrv2 claims it works on PyCom boards? I already tried using the gc module, but it did not help. Still the same error.

Documentation and info server is down

hc2.fr and microwebsrv2.hc2.fr is down.

I get DNS_PROBE_FINISHED_NXDOMAIN as the error in Chrome and have made sure that I have a working and proper network connection.

filename error by [ ResolvePhysicalPath ]

Hello.
At first, I am no good at English,
So this Issue may contain some grammatical mistakes. Sorry.

I try to use MicroWebSrv2 to create a simple web system.
Today, I found an error in my program.
All files in root-directory (mws2.RootPath) can't find. and return 403.

The same code worked success yesterday, But today it doesn't work.

I found the error occurred in httpRequest.py

    def _processRequest(self) :
        if not self._processRequestModules() :
            if not self.IsUpgrade :
                if not self._processRequestRoutes() :
                    if self._method == 'GET' or self._method == 'HEAD' :
                        filename = self._mws2.ResolvePhysicalPath(self._path)
                        # if filename[-1] == '/':
                        #     filename = filename[:-1]
                        if filename :
                            ct = self._mws2.GetMimeTypeFromFilename(filename)
                            if ct :
                                self._response.AllowCaching = True
                                self._response.ContentType  = ct
                                self._response.ReturnFile(filename)
                            else :
                                self._response.ReturnForbidden()
                        else :
                            self._response.ReturnNotFound()
                    else :
                        self._response.ReturnMethodNotAllowed()
            else :
                self._response.ReturnNotImplemented()

filename = self._mws2.ResolvePhysicalPath(self._path)
return a filename end with /
such as /var/www/html/test.html/

but if filename end with / GetMimeTypeFromFilename and ReturnFile can't work.

when I add this two-line to remove /

if filename[-1] == '/':
    filename = filename[:-1]

webserver worked success.

would you know some more details about this error?

Expected upstream speed

Hello @jczic
I am trying some file transfers over wifi from an SDcard (in SPI mode). MWS2 has been integrated as a module into micropython. I am trying the demo and changed the PDF file for a bigger one to make some speed tests.
I'm seeing 30kB/sec which is ten times under what I was expecting. I don't really understand why it is so slow. Do you have some recommendations or tips to achieve better performances? Do you know where the bottleneck might be? Is there a significant gain from an SD wired with 4 data lines?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.