{"id":13541944,"url":"https://github.com/jczic/MicroWebSrv","last_synced_at":"2025-04-02T09:33:06.552Z","repository":{"id":41337450,"uuid":"93101683","full_name":"jczic/MicroWebSrv","owner":"jczic","description":"A micro HTTP Web server that supports WebSockets, html/python language templating and routing handlers, for MicroPython (used on Pycom modules \u0026 ESP32)","archived":false,"fork":false,"pushed_at":"2023-01-17T12:18:00.000Z","size":712,"stargazers_count":646,"open_issues_count":12,"forks_count":117,"subscribers_count":49,"default_branch":"master","last_synced_at":"2024-10-11T13:23:05.532Z","etag":null,"topics":["captive-portal","esp32","hc2","http","iot","language-templating","micropython","microwebsrv","pyboard","pycom","pyhtml","routing","support-websockets","template-engine","templating","webserver","websocket","websocket-server","websockets","wipy"],"latest_commit_sha":null,"homepage":"https://github.com/jczic/MicroWebSrv","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jczic.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-06-01T21:38:19.000Z","updated_at":"2024-10-11T07:14:49.000Z","dependencies_parsed_at":"2023-02-10T09:31:30.851Z","dependency_job_id":null,"html_url":"https://github.com/jczic/MicroWebSrv","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jczic%2FMicroWebSrv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jczic%2FMicroWebSrv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jczic%2FMicroWebSrv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jczic%2FMicroWebSrv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jczic","download_url":"https://codeload.github.com/jczic/MicroWebSrv/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":222818707,"owners_count":17042228,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["captive-portal","esp32","hc2","http","iot","language-templating","micropython","microwebsrv","pyboard","pycom","pyhtml","routing","support-websockets","template-engine","templating","webserver","websocket","websocket-server","websockets","wipy"],"created_at":"2024-08-01T10:00:59.218Z","updated_at":"2024-11-03T07:31:29.024Z","avatar_url":"https://github.com/jczic.png","language":"Python","funding_links":[],"categories":["Networking","Python","Libraries","Frameworks for Micropython"],"sub_categories":["Communications","More"],"readme":"\n\u003ch3\u003e\n  \u003cp align=\"center\"\u003e\n    Also check out the new ESP32 MPY-Jama free IDE and the latest MicroWebSrv2 below:\n  \u003c/p\u003e\n\u003c/h3\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/jczic/ESP32-MPY-Jama\"\u003e\u003cimg src=\"https://github.com/jczic/ESP32-MPY-Jama/raw/master/img/ESP32%20MPY-Jama%20NEW.png\" alt=\"New microWebSrv2\" width=\"350\" valign=\"middle\"\u003e\u003c/a\u003e                  \n  \u003ca href=\"https://github.com/jczic/MicroWebSrv2\"\u003e\u003cimg src=\"microWebSrv2.png\" alt=\"New microWebSrv2\" width=\"350\" valign=\"middle\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n\u003cbr /\u003e\n\n### 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. Now supports all variants of [Pyboard D-series](https://store.micropython.org/category/pyboard%20D-series) from the makers of Micropython)\n\n![HC²](hc2.png \"HC²\")\n\nVery easy to integrate and very light with 3 files only :\n- `\"microWebSrv.py\"` - The Web server\n- `\"microWebSocket.py\"` - The optional support of WebSockets\n- `\"microWebTemplate.py\"` - The optional templating language for **.pyhtml** rendered pages\n\nMini tuto in video by rdagger68 :\n- [https://www.youtube.com/watch?v=xscBwC1SrF4](https://www.youtube.com/watch?v=xscBwC1SrF4)\n\nSimple but effective :\n- Use it to embed a cool Web site in yours modules\n- Handle GET, POST, ... requests to interract with user and configure options\n- Exchange in JSON format on HTTP methods to make an embedded fullREST API\n- Serve files on the fly to export any data to the user\n- Use routes and variable route handlers\n- Play with AjAX to interact speedly with a Web application\n- Make it a captive portal simply\n- Use WebSockets for fast and powerful data exchange\n- Make html/python files for rendering more efficient web pages\n\n### Using *microWebSrv* main class :\n\n| Name  | Function |\n| - | - |\n| Constructor | `mws = MicroWebSrv(routeHandlers=None, port=80, bindIP='0.0.0.0', webPath=\"/flash/www\")` |\n| Start Web server | `mws.Start(threaded=True)` |\n| Stop Web server | `mws.Stop()` |\n| Check if Web server is running | `mws.IsStarted()` |\n| Set URL location for not found page | `mws.SetNotFoundPageUrl(url=None)` |\n| Get mime type from file extention | `mws.GetMimeTypeFromFilename(filename)` |\n| Get handler function from route | `(routeHandler, routeArgs) = mws.GetRouteHandler(resUrl, method)` |\n| Callback function to enable and accept WebSockets | `mws.AcceptWebSocketCallback = _acptWS` `_acptWS(webSocket, httpClient) { }` |\n| Maximum length of memory allocated to receive WebSockets data (1024 by default) | `mws.MaxWebSocketRecvLen` |\n| New thread used for each WebSocket connection (True by default) | `mws.WebSocketThreaded` |\n| Escape string to HTML usage | `MicroWebSrv.HTMLEscape(s)` |\n\n### Basic example :\n```python\nfrom microWebSrv import MicroWebSrv\nmws = MicroWebSrv()      # TCP port 80 and files in /flash/www\nmws.Start(threaded=True) # Starts server in a new thread\n```\n\n### Using as captive portal :\n```python\n# To intercept all not found queries and redirect it,\nmws.SetNotFoundPageUrl(\"http://my-device.wifi\")\n```\n- Can be used with [MicroDNSSrv](http://microdnssrv.hc2.fr) easily.\n\n### Using route handlers example :\n```python\n\nrouteHandlers = [\n  ( \"relative_url_route_1\", \"METHOD\", handlerFunc_1 ),\n  ( \"relative_url_route_2\", \"METHOD\", handlerFunc_2 ),\n  ( ... )\n]\n```\n```python\ndef handlerFunc_1(httpClient, httpResponse, routeArgs=None) :\n  print(\"In HTTP handler 1\")\n\ndef handlerFunc_2(httpClient, httpResponse, routeArgs=None) :\n  print(\"In HTTP handler 2\")\n```\n\n### Using directly route handlers decorators example :\n```python\n@MicroWebSrv.route('/get-test')\ndef handlerFuncGet(httpClient, httpResponse) :\n  print(\"In GET-TEST HTTP\")\n\n@MicroWebSrv.route('/post-test', 'POST')\ndef handlerFuncPost(httpClient, httpResponse) :\n  print(\"In POST-TEST HTTP\")\n```\n\n### Using variable routes example :\n```python\nrouteHandlers = [\n  ( \"/edit/\u003ctestid\u003e/\u003ctestpath\u003e\", \"GET\", handlerFuncEdit ),\n  ( ... )\n]\ndef handlerFuncEdit(httpClient, httpResponse, routeArgs) :\n  print(\"In EDIT HTTP variable route :\")\n  print(\" - testid   = %s\" % routeArgs['testid'])\n  print(\" - testpath = %s\" % routeArgs['testpath'])\n```\n\nOr direclty with route handler decorator :\n\n```python\n@MicroWebSrv.route('/edit/\u003ctestid\u003e/\u003ctestpath\u003e')\ndef handlerFuncEdit(httpClient, httpResponse, routeArgs) :\n  print(\"In EDIT HTTP variable route :\")\n  print(\" - testid   = %s\" % routeArgs['testid'])\n  print(\" - testpath = %s\" % routeArgs['testpath'])\n```\n\n### Using *httpClient* class in a route handler function :\n\n| Name  | Function |\n| - | - |\n| Get MicroWebSrv class | `httpClient.GetServer()` |\n| Get client address as tuple | `httpClient.GetAddr()` |\n| Get client IP address | `httpClient.GetIPAddr()` |\n| Get client TCP port | `httpClient.GetPort()` |\n| Get client request method | `httpClient.GetRequestMethod()` |\n| Get client request total path | `httpClient.GetRequestTotalPath()` |\n| Get client request ressource path | `httpClient.GetRequestPath()` |\n| Get client request query string | `httpClient.GetRequestQueryString()` |\n| Get client request query parameters as list | `httpClient.GetRequestQueryParams()` |\n| Get client request headers as list | `httpClient.GetRequestHeaders()` |\n| Get client request content type | `httpClient.GetRequestContentType()` |\n| Get client request content length | `httpClient.GetRequestContentLength()` |\n| Get client request content | `httpClient.ReadRequestContent(size=None)` |\n| Get client request form data as list | `httpClient.ReadRequestPostedFormData()` |\n| Get client request as JSON object | `httpClient.ReadRequestContentAsJSON()` |\n\n### Using *httpResponse* class in a route handler function :\n\n| Name  | Function |\n| - | - |\n| Write switching protocols response | `httpResponse.WriteSwitchProto(upgrade, headers=None)` |\n| Write generic response | `httpResponse.WriteResponse(code, headers, contentType, contentCharset, content)` |\n| Write PyHTML rendered response page | `httpResponse.WriteResponsePyHTMLFile(filepath, headers=None, vars=None)` |\n| Write file directly as response | `httpResponse.WriteResponseFile(filepath, contentType=None, headers=None)` |\n| Write attached file as response | `httpResponse.WriteResponseFileAttachment(filepath, attachmentName, headers=None)` |\n| Write OK response | `httpResponse.WriteResponseOk(headers=None, contentType=None, contentCharset=None, content=None)` |\n| Write JSON object as OK response | `httpResponse.WriteResponseJSONOk(obj=None, headers=None)` |\n| Write redirect response | `httpResponse.WriteResponseRedirect(location)` |\n| Write error response | `httpResponse.WriteResponseError(code)` |\n| Write JSON object as error response | `httpResponse.WriteResponseJSONError(code, obj=None)` |\n| Write bad request response | `httpResponse.WriteResponseBadRequest()` |\n| Write forbidden response | `httpResponse.WriteResponseForbidden()` |\n| Write not found response | `httpResponse.WriteResponseNotFound()` |\n| Write method not allowed response | `httpResponse.WriteResponseMethodNotAllowed()` |\n| Write internal server error response | `httpResponse.WriteResponseInternalServerError()` |\n| Write not implemented response | `httpResponse.WriteResponseNotImplemented()` |\n\n### Using route handler function example :\n\n```python\ndef _httpHandlerTestPost(httpClient, httpResponse) :\n  formData  = httpClient.ReadRequestPostedFormData()\n  firstname = formData[\"firstname\"]\n  lastname  = formData[\"lastname\"]\n  content   = \"\"\"\\\n  \u003c!DOCTYPE html\u003e\n  \u003chtml\u003e\n    \u003chead\u003e\n      \u003cmeta charset=\"UTF-8\" /\u003e\n      \u003ctitle\u003eTEST POST\u003c/title\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n      \u003ch1\u003eTEST POST\u003c/h1\u003e\n      Firstname = %s\u003cbr /\u003e\n      Lastname = %s\u003cbr /\u003e\n    \u003c/body\u003e\n  \u003c/html\u003e\n  \"\"\" % ( MicroWebSrv.HTMLEscape(firstname),\n          MicroWebSrv.HTMLEscape(lastname) )\n  httpResponse.WriteResponseOk( headers         = None,\n                                contentType     = \"text/html\",\n                                contentCharset  = \"UTF-8\",\n                                content         = content )\n```\n\n### Known mime types (content types) :\n\n| File extension | Mime type |\n| - | - |\n| .txt   | text/plain |\n| .htm   | text/html |\n| .html  | text/html |\n| .css   | text/css |\n| .csv   | text/csv |\n| .js    | application/javascript |\n| .xml   | application/xml |\n| .xhtml | application/xhtml+xml |\n| .json  | application/json |\n| .zip   | application/zip |\n| .pdf   | application/pdf |\n| .ts    | application/typescript |\n| .woff  | font/woff |\n| .woff2 | font/woff2 |\n| .ttf   | font/ttf |\n| .otf   | font/otf |\n| .jpg   | image/jpeg |\n| .jpeg  | image/jpeg |\n| .png   | image/png |\n| .gif   | image/gif |\n| .svg   | image/svg+xml |\n| .ico   | image/x-icon |\n\n### Default index pages order (for http://hostname/) :\n\n| Filename |\n| - |\n| index.pyhtml |\n| index.html |\n| index.htm |\n| default.pyhtml |\n| default.html |\n| default.htm |\n\n### Using optional module *microWebSocket* to connect WebSockets :\n\n- File `\"microWebSocket.py\"` must be present to activate WebSockets support\n\n### Enable and accept WebSockets :\n```python\nfrom microWebSrv import MicroWebSrv\nmws = MicroWebSrv()                                    # TCP port 80 and files in /flash/www\nmws.MaxWebSocketRecvLen     = 256                      # Default is set to 1024\nmws.WebSocketThreaded       = False                    # WebSockets without new threads\nmws.AcceptWebSocketCallback = _acceptWebSocketCallback # Function to receive WebSockets\nmws.Start(threaded=True)                               # Starts server in a new thread\n```\n\n| Name  | Function |\n| - | - |\n| Callback function to receive text message | `ws.RecvTextCallback = func(webSocket, msg)` |\n| Callback function to receive binary data | `ws.RecvBinaryCallback = func(webSocket, data)` |\n| Callback function when connection was closed | `ws.ClosedCallback = func(webSocket)` |\n| Send a text message | `ws.SendText(msg)` |\n| Send a binary message | `ws.SendBinary(data)` |\n| Check connection state | `ws.IsClosed()` |\n| Close the connection | `ws.Close()` |\n\n### Basic example of callback functions :\n```python\ndef _acceptWebSocketCallback(webSocket, httpClient) :\n  print(\"WS ACCEPT\")\n  webSocket.RecvTextCallback   = _recvTextCallback\n  webSocket.RecvBinaryCallback = _recvBinaryCallback\n  webSocket.ClosedCallback     = _closedCallback\n\ndef _recvTextCallback(webSocket, msg) :\n  print(\"WS RECV TEXT : %s\" % msg)\n  webSocket.SendText(\"Reply for %s\" % msg)\n\ndef _recvBinaryCallback(webSocket, data) :\n  print(\"WS RECV DATA : %s\" % data)\n\ndef _closedCallback(webSocket) :\n  print(\"WS CLOSED\")\n```\n\n### Using optional module *microWebTemplate* for *.pyhtml* rendered pages :\n\n- File `\"microWebTemplate.py\"` must be present to activate **.pyhtml** pages\n- Pages will be rendered in HTML with integrated MicroPython code\n\n| Instruction | Schema |\n| - | - |\n| PY      | `{{ py }}` *MicroPython code* `{{ end }}` |\n| IF      | `{{ if` *MicroPython condition* `}}` *html bloc* `{{ end }}` |\n| ELIF    | `{{ elif` *MicroPython condition* `}}` *html bloc* `{{ end }}` |\n| ELSE    | `{{ else }}` *html bloc* `{{ end }}` |\n| FOR     | `{{ for` *identifier* `in` *MicroPython iterator* `}}` *html bloc* `{{ end }}` |\n| INCLUDE | `{{ include` *pyhtml_filename* `}}` |\n| ?       | `{{` *MicroPython expression* `}}` |\n\n\n### Using {{ py }} :\n\n```python\n{{ py }}\n  import machine\n  from utime import sleep\n  test = 123\n  def testFunc(x) :\n    return 2 * x\n{{ end }}\n```\n\n### Using {{ if ... }} :\n\n```python\n{{ if testFunc(5) \u003c= 3 }}\n  \u003cspan\u003etiti\u003c/span\u003e\n{{ elif testFunc(10) \u003e= 15 }}\n  \u003cspan\u003etata\u003c/span\u003e\n{{ else }}\n  \u003cspan\u003eI like the number {{ test }} !\u003c/span\u003e\n{{ end }}\n```\n\n### Using {{ for ... }} :\n\n```python\n{{ for toto in range(testFunc(3)) }}\n  \u003cdiv\u003etoto x 10 equal {{ toto * 10 }}\u003c/div\u003e\n  \u003chr /\u003e\n{{ end }}\n```\n\n### Using {{ include ... }} :\n\n```python\n{{ include myTemplate.pyhtml }}\n```\n\n### Example of a .pyhtml file :\n\n```html\n\u003chtml\u003e\n  \u003chead\u003e\n    \u003ctitle\u003eTEST PYHTML\u003c/title\u003e\n  \u003c/head\u003e\n  \u003cbody\u003e\n    \u003ch1\u003eBEGIN\u003c/h1\u003e\n    {{ py }}\n      def _testFunction(x) :\n        return \"IN TEST FUNCTION %s\" % x\n    {{ end }}\n    \u003cdiv style=\"background-color: black; color: white;\"\u003e\n      {{ for toto in range(3) }}\n        This is an HTML test...\u003cbr /\u003e\n        TOTO = {{ toto + 1 }} !\u003cbr /\u003e\n        {{ for toto2 in range(3) }}\n          TOTO2 = {{ _testFunction(toto2) }}\n        {{ end }}\n        Ok good.\u003cbr /\u003e\n      {{ end }}\n    \u003c/div\u003e\n    {{ _testFunction(100) }}\u003cbr /\u003e\n    \u003cbr /\u003e\n    {{ if 2+5 \u003c 3 }}\n      IN IF (1)\n    {{ elif 10+15 != 25 }}\n      IN ELIF (2)\n    {{ elif 10+15 == 25 }}\n      IN ELIF (3)\n    {{ else }}\n      IN ELSE (4)\n    {{ end }}\n  \u003c/body\u003e\n\u003c/html\u003e\n```\n\n\u003ca name=\"author\"\u003e\u003c/a\u003e\n## :wink: \u0026nbsp;Author\n\n  **Jean-Christophe Bos** (:fr:)\n  - GitHub: *[@jczic](https://github.com/jczic)*\n  - Email:  *\u003cjczic.bos@gmail.com\u003e*\n  - Profil: *[LinkedIn](https://www.linkedin.com/in/jczic)*\n  - Music:  *[SoundCloud](https://soundcloud.com/jczic/sets/electro-pulse)*\n            *[Spotify](https://open.spotify.com/album/5fUd57GcAIcdUn9NX3fviG)*\n            *[YouTube](https://www.youtube.com/playlist?list=PL9CsGuMbcLaU02VKS7jtR6LaDNpq7MZEq)*\n\n\n### By JC`zic for [HC²](https://www.hc2.fr) ;')\n\n*Keep it simple, stupid* :+1:\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjczic%2FMicroWebSrv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjczic%2FMicroWebSrv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjczic%2FMicroWebSrv/lists"}