Super simple web server for wifi-based micro-controllers that support MicroPython (ie. NodeMCU ESP8266)
- Table of Contents
- Features
- Changelog
- Requirements
- μWeb vs. μWeb-uasyncio
- Installation
- Quick Start
- Using uWeb-uasyncio
- Template Rendering
- Layout Rendering
- Documentation
- Simple URL routing to actions
- Render templates with layouts to the client
- Super simple HTML templating
- HTTP request parsing
- Send files and json to client
- Parse headers and body from client
- Optional asynchronous version (based on uasyncio)
uWeb
v1.1 - 5/19/20
- layout rendering
- send appropriate Content-Type headers when sending files
- version attribute
v1.0 - 7/6/19
- First release!
uWeb-uasyncio
v1.0 - 5/20/20
- First release!
- Microcontroller that supports micropython(such as NodeMCU ESP8266)
- USB cable(possibly)
- Wi-Fi connection
MicroPython Libraries:
- ujson
- usocket
- uasyncio(for uasyncio version)
This repo contains both uWeb and uWeb-uasyncio. Both versions have their own use cases
;-; | μWeb | μWeb-uasyncio |
---|---|---|
concurrency | synchronous, uses usocket(blocking sockets) | asynchronous, uses uasyncio(non-blocking sockets) |
when to use | when you need a simple web server to serve HTML or send data | when endpoints call functions that take time to run and having the server still be able to respond to requests is important |
use cases | simple API that serves static files or sends some JSON data(concurrency not required) | app where a request to an endpoint invokes a function that sleeps for some time but still needs to respond to incoming requests |
TLDR; uWeb can be used when concurrency is not important. uWeb-uasyncio can be used when concurrency is important
- Install micropython on your board of choice(ESP8266 installation)
- Copy the μWeb project files to your board over the web using MicroPython's WebREPL or through a serial connection with Adafruit's ampy
- chose either
uWeb.py
oruWeb_uasyncio.py
depending on your needs
- chose either
- If your version of MicroPython does not come with ujson, usocket or uasyncio(if needed) precompiled, copy them from micropython-lib
- Along with the μWeb project files, make sure you have a boot.py for the initial setup of your board(ie: connecting to wifi) and main.py for the main μWeb code.
- Power up your board and enjoy!
No MicroPython board? No problem!
You can run uWeb with the MicroPython unix port
- Build the unix MicroPython port (here) or get the prebuild executable (here)
- Run
micropython uWeb_example.py
ormicropython uWeb_uasyncio_example.py
in your console.
from uWeb import uWeb, loadJSON
server = uWeb("0.0.0.0", 8000) #init uWeb object
def home(): #render HTML page
vars = {
'name': 'MicroPython',
'answer': (1+1)
}
server.render('content.html', variables=vars)
def header(): #send headers to client
server.sendStatus(server.OK)
server.sendHeaders({
'header1': 'one',
'header2': 'two',
'header3': 'three',
})
def post(): #print JSON body from client
print(loadJSON(server.request_body).items())
def jsonn(): #send JSON to client
server.sendJSON({'status':'okkk'})
#configure routes
server.routes(({
(uWeb.GET, "/"): home,
(uWeb.POST, "/post"): post,
(uWeb.GET, "/json"): jsonn,
(uWeb.GET, "/header"): header
}))
#start server
server.start()
import uasyncio
from uWeb_uasyncio import uWeb_uasyncio as uWeb
from uWeb_uasyncio import loadJSON
server = uWeb("0.0.0.0", 8000) #init uWeb object
def home(): #render HTML page
vars = {
'name': 'MicroPython',
'answer': (1+1)
}
await server.render('content.html', variables=vars)
def printTen(): # counts to ten while still accepting incoming requests
await server.sendStatus(server.OK)
for i in range(10):
print(i)
await uasyncio.sleep(1)
def header(): #send headers to client
await server.sendStatus(server.OK)
await server.sendHeaders({
'header1': 'one',
'header2': 'two',
'header3': 'three',
})
def post(): #print JSON body from client
print('Payload: ', loadJSON(server.request_body))
await uasyncio.sleep(0)
def jsonn(): #send JSON to client
await server.sendJSON({'status':'okkk'})
#configure routes
server.routes(({
(uWeb.GET, "/"): home,
(uWeb.GET, "/ten"): printTen,
(uWeb.POST, "/post"): post,
(uWeb.GET, "/json"): jsonn,
(uWeb.GET, "/header"): header
}))
#start server
server.start()
- when configuring routes, endpoint functions are treated as asynchronous so they must have an
await
statement in its body - uWeb class methods can be preceded with
await
- when using other functions that aren't
await
able,await uasyncio.sleep(0)
can be used (as seen in the example) - more info about using
uasyncio
: uasyncio docs
- μWeb comes loaded with a simple template rendering system that can render HTML with python variables.
- To replace a variable in the HTML template, surround the variable name with
{{ }}
. Then, render the template with the variables argument.
Example:
content.html
<h1>Hello from {{name}}!</h1>
<h3>1 + 1 = {{answer}}</h3>
example.py
vars = {
'name': 'MicroPython',
'answer': (1+1)
}
server.render('content.html', variables=vars)
will render as:
<h1>Hello from MicroPython!</h1>
<h3>1 + 1 = 2</h3>
- Template rendering can be combined with layout rendering so that templates can share the same layout
- The default layout is
layout.html
- Specify a specific layout to render your template with using the
layout
argument in therender
function - Use
{{yield}}
to specify where in the layout you want the content to render
Using the example from above:
content.html
<h1>Hello from {{name}}!</h1>
<h3>1 + 1 = {{answer}}</h3>
cool-layout.html
<head>
<title>cool site</title>
</head>
<body>
<h1>this is a cool layout dude</h1>
{{yield}}
</body>
example.py
vars = {
'name': 'MicroPython',
'answer': (1+1)
}
server.render('content.html', layout='cool-layout.html', variables=vars) # if you are using layout.html, the layout argument may be left out
will render as:
<head>
<title>cool site</title>
</head>
<body>
<h1>this is a cool layout dude</h1>
<h1>Hello from MicroPython!</h1>
<h3>1 + 1 = 2</h3>
</body>