{"id":15170195,"url":"https://github.com/rumpelrausch/microasyncweb","last_synced_at":"2026-01-24T14:43:31.225Z","repository":{"id":243698469,"uuid":"813176369","full_name":"rumpelrausch/microAsyncWeb","owner":"rumpelrausch","description":"A MicroPython web server using async. Does not block REPL/WebREPL. Code size is less than 9KB. Tested on ESP32.","archived":false,"fork":false,"pushed_at":"2024-06-10T16:16:20.000Z","size":6,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-06T11:50:05.269Z","etag":null,"topics":["asyncio","esp32","http","micropython","server","uasyncio","web","webserver"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rumpelrausch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-10T16:00:37.000Z","updated_at":"2024-06-10T19:30:24.000Z","dependencies_parsed_at":"2024-06-10T19:07:42.179Z","dependency_job_id":"7d787e53-2a1e-464a-9cb2-300be50e3cc2","html_url":"https://github.com/rumpelrausch/microAsyncWeb","commit_stats":null,"previous_names":["rumpelrausch/microasyncweb"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rumpelrausch%2FmicroAsyncWeb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rumpelrausch%2FmicroAsyncWeb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rumpelrausch%2FmicroAsyncWeb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rumpelrausch%2FmicroAsyncWeb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rumpelrausch","download_url":"https://codeload.github.com/rumpelrausch/microAsyncWeb/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":231234350,"owners_count":18345237,"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":["asyncio","esp32","http","micropython","server","uasyncio","web","webserver"],"created_at":"2024-09-27T08:00:48.424Z","updated_at":"2026-01-24T14:43:31.215Z","avatar_url":"https://github.com/rumpelrausch.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# microAsyncWeb\n\nA MicroPython web server using async.\u003cbr\u003e\nDoes not block REPL/WebREPL.\u003cbr\u003e\nCode size is less than 9KB.\n\nBased upon https://github.com/hugokernel/micropython-nanoweb.\n\n## Features\n\n- Runs fully async via MicroPython `uasyncio`.\n- Also works as Thread, e.g. on second ESP32 core.\n- Does not block REPL/WebREPL when started as thread.\u003cbr\u003e\n    Can be run together with other REPL tools like Thonny.\n- Runs in parallel with pure async ftp servers (as long as RAM lasts).\n- Automatically handles basic mime types.\n- Automatically handles file delivery from a definable web root directory.\n- Routes are configurable as lists or decorated functions.\n- Extracts route parameters.\n\n## Async invocation\n```python\nimport asyncio\nfrom micropAsyncWeb import MicropAsyncWeb, Response\n\nwebserver = MicropAsyncWeb()\n\n# ...define your routes...\n\nloop = asyncio.get_event_loop()\nloop.create_task(webserver.runAsync())\n# add any other async tasks\nloop.run_forever()\n```\n\n## Threaded async invocation\n```python\nimport asyncio\nfrom micropAsyncWeb import MicropAsyncWeb, Response\nfrom _thread import start_new_thread\n\nwebserver = MicropAsyncWeb()\n\n# ...define your routes...\n\ndef runThread():\n    loop = asyncio.get_event_loop()\n    loop.create_task(webserver.runAsync())\n    # add any other _thread compatible async tasks\n    loop.run_forever()\n\nstart_new_thread(runThread, ())\n```\n\n## Examples\n\n### Basic setup\n\n```python\nfrom micropAsyncWeb import MicropAsyncWeb, Response\n\n# Automatically handles \"/\" and \"/*\" routes (deliver files from webroot).\nwebserver = MicropAsyncWeb(webroot=\"./webroot\", indexFile=\"index.htm\")\n\n@webserver.route(\"/ping\")\nasync def _route_ping(request):\n    await Response.start(request, 200, \"OK\")\n    await Response.startBody(request)\n    await request.write(\"pong\")\n```\n\n### Routes as list\n```python\n@webserver.route(\"/ping\")\nasync def _route_ping(request):\n    await Response.start(request, 200, \"OK\")\n    await Response.startBody(request)\n    await request.write(\"pong\")\n\nasync def _route_info(request):\n    await Response.sendJson(request, {\"version\": \"0.0.1\"})\n\n# appendRoutes and decorators can be mixed\nwebserver.appendRoutes(\n    [\n        [\"/api/v1/info\", _route_info]\n    ]\n)\n```\n\n### Request methods and parameters\nDecorated:\n```python\n@webserver.route(\"/api/v1/led/*/*\", \"POST\")\nasync def _route_set_led(request):\n    ledNum = int(request.params[0])\n    ledState = int(request.params[0])\n    result = myLedClass.setLed(ledNum, ledState)\n    await Response.sendJson(request, result)\n```\n\nUsing `appendRoutes`:\n```python\nasync def _route_set_led(request):\n    ledNum = int(request.params[0])\n    ledState = int(request.params[0])\n    result = myLedClass.setLed(ledNum, ledState)\n    await Response.sendJson(request, result)\n\nwebserver.appendRoutes(\n    [\n        [\"/api/v1/led/*/*\", _route_set_led, \"POST\"]\n    ]\n)\n```\n\n## Reference\n\n### Route definitions\n\nRoutes used in `.appendRoutes` are defined as _lists_ with two or three\nentries:\n\n0. `\u003cstr\u003e` Route string\n1. `\u003ccallable\u003e` Route handler\n2. `\u003cstr\u003e` _optional_ Allowed http methods (comma separated list)\n\nRoutes used in decorators are defined by one or two positional\nparameters:\n\n0. `\u003cstr\u003e` Route string\n1. `\u003cstr\u003e` _optional_ Allowed http methods (comma separated list)\n\nIf the http methods aren't defined \"GET\" will be assumed.\n\n### Route syntax\n\n- A route must begin with slash \"/\".\n- A route may contain positional parameter placeholders as as single\n  asterisk (\"*\").\n- An asterisk placeholder must stand alone; `/some/route/px*` or\n  `/route/**/a` are not allowed.\n- Placeholders may be succeeded by additional paths, e.g.\n  `/some/feature/*/detail/*`\n\n### Route hierarchy\n\nRoutes are sorted automatically by their complexity.\nIf you need to define a specific route order you'll have to remove\nthe call to `self.sortRoutes()` at the end of the file.\n\n### Class MicropAsyncWeb\n\n#### Constructor\n`(self, port=80, address=\"0.0.0.0\", webroot=\".\", indexFile=\"index.html\")`\n\nThere is no list of index files; You need to explicitely specify it.\n\n#### appendRoutes\n`.appendRoutes(\u003clist\u003e)`\n\nSee examples.\n\n### Class Request\n\nMicropAsyncWeb passes an instance of `Request` to the route handler.\nIt is set up with these members:\n\n- `\u003cstr\u003e` **`url`**\u003cbr\u003e\n    The full requested URL.\n- `\u003cstr\u003e` **`path`**\u003cbr\u003e\n    The path part without query parameters and hashes.\n- `\u003cstr\u003e` **`method`**\u003cbr\u003e\n    The requested http method.\n- `\u003cdict\u003e` **`header`**\u003cbr\u003e\n    Incoming request headers. The allowed header list is filtered, see\n    source code.\n- `\u003clist\u003e` **`params`**\u003cbr\u003e\n    Each \"*\" in a given route is parsed as positional parameter and\n    added to `.params`. See examples.\n- `\u003ccallable\u003e` **`write`**\u003cbr\u003e\n    Write directly to response stream.\n\n### Class Response\n\nThis class is never instantiated; It's methods are static.\n\n`start(request, statusCode, statusText)`\u003cbr\u003e\nStarts a response; The header section remains open.\n\n`startBody(request)`\u003cbr\u003e\nEnds the header section.\n\n`sendJson(request, dict)`\u003cbr\u003e\nSends a full JSON response form a given dictionary, including response\nstart, header and body sections.\n\n`sendFile(request, filename)`\u003cbr\u003e\nSends a file. Uses the file name extension as hint for content-type\nmime mapping.\n\n`write(request, data)`\u003cbr\u003e\nWrites out an UTF-8 encoded string. Does not invoke `start()` or\n`startBody()`.\n\n`error(request, code, reason)`\u003cbr\u003e\nSends a full error response, including response start, header and body\nsections.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frumpelrausch%2Fmicroasyncweb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frumpelrausch%2Fmicroasyncweb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frumpelrausch%2Fmicroasyncweb/lists"}