# MicroWebSrv **Repository Path**: youxinweizhi/MicroWebSrv ## Basic Information - **Project Name**: MicroWebSrv - **Description**: A micro HTTP Web server that supports WebSockets, html/python language templating and routing handlers, for MicroPython (used on Pycom modules & ESP32) - **Primary Language**: Python - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 1 - **Created**: 2021-09-07 - **Last Updated**: 2025-06-17 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## MicroWebSrv is a micro HTTP Web server that supports WebSockets, html/python language templating and routing handlers, for MicroPython (principally used on ESP32 and [Pycom](http://www.pycom.io) modules) ![HC²](hc2.png "HC²") Very easy to integrate and very light with 3 files only : - `"microWebSrv.py"` - The Web server - `"microWebSocket.py"` - The optional support of WebSockets - `"microWebTemplate.py"` - The optional templating language for **.pyhtml** rendered pages Mini tuto in video by rdagger68 : - [https://www.youtube.com/watch?v=xscBwC1SrF4](https://www.youtube.com/watch?v=xscBwC1SrF4) Simple but effective : - Use it to embed a cool Web site in yours modules - Handle GET, POST, ... requests to interract with user and configure options - Exchange in JSON format on HTTP methods to make an embedded fullREST API - Serve files on the fly to export any data to the user - Use routes and variable route handlers - Play with AjAX to interact speedly with a Web application - Make it a captive portal simply - Use WebSockets for fast and powerful data exchange - Make html/python files for rendering more efficient web pages ### Using *microWebSrv* main class : | Name | Function | | - | - | | Constructor | `mws = MicroWebSrv(routeHandlers=None, port=80, bindIP='0.0.0.0', webPath="/flash/www")` | | Start Web server | `mws.Start(threaded=True)` | | Stop Web server | `mws.Stop()` | | Check if Web server is running | `mws.IsStarted()` | | Set URL location for not found page | `mws.SetNotFoundPageUrl(url=None)` | | Get mime type from file extention | `mws.GetMimeTypeFromFilename(filename)` | | Get handler function from route | `(routeHandler, routeArgs) = mws.GetRouteHandler(resUrl, method)` | | Callback function to enable and accept WebSockets | `mws.AcceptWebSocketCallback = _acptWS` `_acptWS(webSocket, httpClient) { }` | | Maximum length of memory allocated to receive WebSockets data (1024 by default) | `mws.MaxWebSocketRecvLen` | | New thread used for each WebSocket connection (True by default) | `mws.WebSocketThreaded` | | Escape string to HTML usage | `MicroWebSrv.HTMLEscape(s)` | ### Basic example : ```python from microWebSrv import MicroWebSrv mws = MicroWebSrv() # TCP port 80 and files in /flash/www mws.Start(threaded=True) # Starts server in a new thread ``` ### Using as captive portal : ```python # To intercept all not found queries and redirect it, mws.SetNotFoundPageUrl("http://my-device.wifi") ``` - Can be used with [MicroDNSSrv](http://microdnssrv.hc2.fr) easily. ### Using route handlers example : ```python routeHandlers = [ ( "relative_url_route_1", "METHOD", handlerFunc_1 ), ( "relative_url_route_2", "METHOD", handlerFunc_2 ), ( ... ) ] ``` ```python def handlerFunc_1(httpClient, httpResponse, routeArgs=None) : print("In HTTP handler 1") def handlerFunc_2(httpClient, httpResponse, routeArgs=None) : print("In HTTP handler 2") ``` ### Using directly route handlers decorators example : ```python @MicroWebSrv.route('/get-test') def handlerFuncGet(httpClient, httpResponse) : print("In GET-TEST HTTP") @MicroWebSrv.route('/post-test', 'POST') def handlerFuncPost(httpClient, httpResponse) : print("In POST-TEST HTTP") ``` ### Using variable routes example : ```python routeHandlers = [ ( "/edit//", "GET", handlerFuncEdit ), ( ... ) ] def handlerFuncEdit(httpClient, httpResponse, routeArgs) : print("In EDIT HTTP variable route :") print(" - testid = %s" % routeArgs['testid']) print(" - testpath = %s" % routeArgs['testpath']) ``` Or direclty with route handler decorator : ```python @MicroWebSrv.route('/edit//') def handlerFuncEdit(httpClient, httpResponse, routeArgs) : print("In EDIT HTTP variable route :") print(" - testid = %s" % routeArgs['testid']) print(" - testpath = %s" % routeArgs['testpath']) ``` ### Using *httpClient* class in a route handler function : | Name | Function | | - | - | | Get MicroWebSrv class | `httpClient.GetServer()` | | Get client address as tuple | `httpClient.GetAddr()` | | Get client IP address | `httpClient.GetIPAddr()` | | Get client TCP port | `httpClient.GetPort()` | | Get client request method | `httpClient.GetRequestMethod()` | | Get client request total path | `httpClient.GetRequestTotalPath()` | | Get client request ressource path | `httpClient.GetRequestPath()` | | Get client request query string | `httpClient.GetRequestQueryString()` | | Get client request query parameters as list | `httpClient.GetRequestQueryParams()` | | Get client request headers as list | `httpClient.GetRequestHeaders()` | | Get client request content type | `httpClient.GetRequestContentType()` | | Get client request content length | `httpClient.GetRequestContentLength()` | | Get client request content | `httpClient.ReadRequestContent(size=None)` | | Get client request form data as list | `httpClient.ReadRequestPostedFormData()` | | Get client request as JSON object | `httpClient.ReadRequestContentAsJSON()` | ### Using *httpResponse* class in a route handler function : | Name | Function | | - | - | | Write switching protocols response | `httpResponse.WriteSwitchProto(upgrade, headers=None)` | | Write generic response | `httpResponse.WriteResponse(code, headers, contentType, contentCharset, content)` | | Write PyHTML rendered response page | `httpResponse.WriteResponsePyHTMLFile(filepath, headers=None, vars=None)` | | Write file directly as response | `httpResponse.WriteResponseFile(filepath, contentType=None, headers=None)` | | Write attached file as response | `httpResponse.WriteResponseFileAttachment(filepath, attachmentName, headers=None)` | | Write OK response | `httpResponse.WriteResponseOk(headers=None, contentType=None, contentCharset=None, content=None)` | | Write JSON object as OK response | `httpResponse.WriteResponseJSONOk(obj=None, headers=None)` | | Write redirect response | `httpResponse.WriteResponseRedirect(location)` | | Write error response | `httpResponse.WriteResponseError(code)` | | Write JSON object as error response | `httpResponse.WriteResponseJSONError(code, obj=None)` | | Write bad request response | `httpResponse.WriteResponseBadRequest()` | | Write forbidden response | `httpResponse.WriteResponseForbidden()` | | Write not found response | `httpResponse.WriteResponseNotFound()` | | Write method not allowed response | `httpResponse.WriteResponseMethodNotAllowed()` | | Write internal server error response | `httpResponse.WriteResponseInternalServerError()` | | Write not implemented response | `httpResponse.WriteResponseNotImplemented()` | ### Using route handler function example : ```python def _httpHandlerTestPost(httpClient, httpResponse) : formData = httpClient.ReadRequestPostedFormData() firstname = formData["firstname"] lastname = formData["lastname"] content = """\ TEST POST

TEST POST

Firstname = %s
Lastname = %s
""" % ( MicroWebSrv.HTMLEscape(firstname), MicroWebSrv.HTMLEscape(lastname) ) httpResponse.WriteResponseOk( headers = None, contentType = "text/html", contentCharset = "UTF-8", content = content ) ``` ### Known mime types (content types) : | File 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 | | .jpg | image/jpeg | | .jpeg | image/jpeg | | .png | image/png | | .gif | image/gif | | .svg | image/svg+xml | | .ico | image/x-icon | ### Default index pages order (for http://hostname/) : | Filename | | - | | index.pyhtml | | index.html | | index.htm | | default.pyhtml | | default.html | | default.htm | ### Using optional module *microWebSocket* to connect WebSockets : - File `"microWebSocket.py"` must be present to activate WebSockets support ### Enable and accept WebSockets : ```python from microWebSrv import MicroWebSrv mws = MicroWebSrv() # TCP port 80 and files in /flash/www mws.MaxWebSocketRecvLen = 256 # Default is set to 1024 mws.WebSocketThreaded = False # WebSockets without new threads mws.AcceptWebSocketCallback = _acceptWebSocketCallback # Function to receive WebSockets mws.Start(threaded=True) # Starts server in a new thread ``` | Name | Function | | - | - | | Callback function to receive text message | `ws.RecvTextCallback = func(webSocket, msg)` | | Callback function to receive binary data | `ws.RecvBinaryCallback = func(webSocket, data)` | | Callback function when connection was closed | `ws.ClosedCallback(webSocket)` | | Send a text message | `ws.SendText(msg)` | | Send a binary message | `ws.SendBinary(data)` | | Check connection state | `ws.IsClosed()` | | Close the connection | `ws.Close()` | ### Basic example of callback functions : ```python def _acceptWebSocketCallback(webSocket, httpClient) : print("WS ACCEPT") webSocket.RecvTextCallback = _recvTextCallback webSocket.RecvBinaryCallback = _recvBinaryCallback webSocket.ClosedCallback = _closedCallback def _recvTextCallback(webSocket, msg) : print("WS RECV TEXT : %s" % msg) webSocket.SendText("Reply for %s" % msg) def _recvBinaryCallback(webSocket, data) : print("WS RECV DATA : %s" % data) def _closedCallback(webSocket) : print("WS CLOSED") ``` ### Using optional module *microWebTemplate* for *.pyhtml* rendered pages : - File `"microWebTemplate.py"` must be present to activate **.pyhtml** pages - Pages will be rendered in HTML with integrated MicroPython code | Instruction | Schema | | - | - | | PY | `{{ py }}` *MicroPython code* `{{ end }}` | | IF | `{{ if` *MicroPython condition* `}}` *html bloc* `{{ end }}` | | ELIF | `{{ elif` *MicroPython condition* `}}` *html bloc* `{{ end }}` | | ELSE | `{{ else }}` *html bloc* `{{ end }}` | | FOR | `{{ for` *identifier* `in` *MicroPython iterator* `}}` *html bloc* `{{ end }}` | | INCLUDE | `{{ include` *pyhtml_filename* `}}` | | ?   | `{{` *MicroPython expression* `}}` | ### Using {{ py }} : ```python {{ py }} import machine from utime import sleep test = 123 def testFunc(x) : return 2 * x {{ end }} ``` ### Using {{ if ... }} : ```python {{ if testFunc(5) <= 3 }} titi {{ elif testFunc(10) >= 15 }} tata {{ else }} I like the number {{ test }} ! {{ end }} ``` ### Using {{ for ... }} : ```python {{ for toto in range(testFunc(3)) }}
toto x 10 equal {{ toto * 10 }}

{{ end }} ``` ### Using {{ include ... }} : ```python {{ include myTemplate.pyhtml }} ``` ### Example of a .pyhtml file : ```html TEST PYHTML

BEGIN

{{ py }} def _testFunction(x) : return "IN TEST FUNCTION %s" % x {{ end }}
{{ for toto in range(3) }} This is an HTML test...
TOTO = {{ toto + 1 }} !
{{ for toto2 in range(3) }} TOTO2 = {{ _testFunction(toto2) }} {{ end }} Ok good.
{{ end }}
{{ _testFunction(100) }}

{{ if 2+5 < 3 }} IN IF (1) {{ elif 10+15 != 25 }} IN ELIF (2) {{ elif 10+15 == 25 }} IN ELIF (3) {{ else }} IN ELSE (4) {{ end }} ``` ### By JC`zic for [HC²](https://www.hc2.fr) ;') *Keep it simple, stupid* :+1: