Skip to content

Commit 87b0e27

Browse files
committed
Updated docs and examples to new Response API, added example of Redirect
1 parent f95781a commit 87b0e27

16 files changed

+172
-98
lines changed

docs/api.rst

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@
2222
.. automodule:: adafruit_httpserver.status
2323
:members:
2424

25-
.. automodule:: adafruit_httpserver.methods
26-
:members:
27-
2825
.. automodule:: adafruit_httpserver.mime_types
2926
:members:
3027

docs/examples.rst

Lines changed: 39 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ In order to save memory, we are unregistering unused MIME types and registering
4949
:linenos:
5050

5151
You can also serve a specific file from the handler.
52-
By default ``Response.send_file()`` looks for the file in the server's ``root_path`` directory, but you can change it.
52+
By default ``FileResponse`` looks for the file in the server's ``root_path`` directory, but you can change it.
5353

5454
.. literalinclude:: ../examples/httpserver_handler_serves_file.py
5555
:caption: examples/httpserver_handler_serves_file.py
56-
:emphasize-lines: 22-23
56+
:emphasize-lines: 22
5757
:linenos:
5858

5959
.. literalinclude:: ../examples/home.html
@@ -74,7 +74,7 @@ a running total of the last 10 samples.
7474

7575
.. literalinclude:: ../examples/httpserver_start_and_poll.py
7676
:caption: examples/httpserver_start_and_poll.py
77-
:emphasize-lines: 25,34
77+
:emphasize-lines: 24,33
7878
:linenos:
7979

8080
Server with MDNS
@@ -91,6 +91,17 @@ In this example, the server is accessible via ``http://custom-mdns-hostname/`` a
9191
:emphasize-lines: 12-14
9292
:linenos:
9393

94+
Get CPU information
95+
-------------------
96+
97+
You can return data from sensors or any computed value as JSON.
98+
That makes it easy to use the data in other applications.
99+
100+
.. literalinclude:: ../examples/httpserver_cpu_information.py
101+
:caption: examples/httpserver_cpu_information.py
102+
:emphasize-lines: 9,27
103+
:linenos:
104+
94105
Handling different methods
95106
---------------------------------------
96107

@@ -107,7 +118,7 @@ In example below, handler for ``/api`` and ``/api/`` route will be called when a
107118

108119
.. literalinclude:: ../examples/httpserver_methods.py
109120
:caption: examples/httpserver_methods.py
110-
:emphasize-lines: 8,15
121+
:emphasize-lines: 8,19,26,30,49
111122
:linenos:
112123

113124
Change NeoPixel color
@@ -129,29 +140,19 @@ Tested on ESP32-S2 Feather.
129140

130141
.. literalinclude:: ../examples/httpserver_neopixel.py
131142
:caption: examples/httpserver_neopixel.py
132-
:emphasize-lines: 25-27,39-40,52-53,61,69
133-
:linenos:
134-
135-
Get CPU information
136-
-------------------
137-
138-
You can return data from sensors or any computed value as JSON.
139-
That makes it easy to use the data in other applications.
140-
141-
.. literalinclude:: ../examples/httpserver_cpu_information.py
142-
:caption: examples/httpserver_cpu_information.py
143-
:emphasize-lines: 28-29
143+
:emphasize-lines: 25-27,39,51,60,66
144144
:linenos:
145145

146146
Chunked response
147147
----------------
148148

149-
Library supports chunked responses. This is useful for streaming data.
150-
To use it, you need to set the ``chunked=True`` when creating a ``Response`` object.
149+
Library supports chunked responses. This is useful for streaming large amounts of data.
150+
In order to use it, you need pass a generator that yields chunks of data to a ``ChunkedResponse``
151+
constructor.
151152

152153
.. literalinclude:: ../examples/httpserver_chunked.py
153154
:caption: examples/httpserver_chunked.py
154-
:emphasize-lines: 21-26
155+
:emphasize-lines: 8,21-26,28
155156
:linenos:
156157

157158
URL parameters and wildcards
@@ -163,7 +164,7 @@ Query/GET parameters are better suited for modifying the behaviour of the handle
163164

164165
Of course it is only a suggestion, you can use them interchangeably and/or both at the same time.
165166

166-
In order to use URL parameters, you need to wrap them inside ``<>`` in ``Server.route``, e.g. ``<my_parameter>``.
167+
In order to use URL parameters, you need to wrap them inside with angle brackets in ``Server.route``, e.g. ``<my_parameter>``.
167168

168169
All URL parameters values are **passed as keyword arguments** to the handler function.
169170

@@ -185,7 +186,7 @@ In both cases, wildcards will not match empty path segment, so ``/api/.../users`
185186

186187
.. literalinclude:: ../examples/httpserver_url_parameters.py
187188
:caption: examples/httpserver_url_parameters.py
188-
:emphasize-lines: 30-34,54-55
189+
:emphasize-lines: 30-34,53-54
189190
:linenos:
190191

191192
Authentication
@@ -206,7 +207,21 @@ In both cases you can check if ``request`` is authenticated by calling ``check_a
206207

207208
.. literalinclude:: ../examples/httpserver_authentication_handlers.py
208209
:caption: examples/httpserver_authentication_handlers.py
209-
:emphasize-lines: 9-15,21-25,33,44,57
210+
:emphasize-lines: 9-15,21-25,33,47,59
211+
:linenos:
212+
213+
Redirects
214+
---------
215+
216+
Sometimes you might want to redirect the user to a different URL, either on the same server or on a different one.
217+
218+
You can do that by returning ``Redirect`` from your handler function.
219+
220+
You can specify wheter the redirect is permanent or temporary by passing ``permanent=...`` to ``Redirect``.
221+
222+
.. literalinclude:: ../examples/httpserver_redirects.py
223+
:caption: examples/httpserver_redirects.py
224+
:emphasize-lines: 14-18,26,38
210225
:linenos:
211226

212227
Multiple servers
@@ -223,7 +238,7 @@ You can share same handler functions between servers or use different ones for e
223238

224239
.. literalinclude:: ../examples/httpserver_multiple_servers.py
225240
:caption: examples/httpserver_multiple_servers.py
226-
:emphasize-lines: 13-14,17,26,35-36,48-49,54-55
241+
:emphasize-lines: 13-14,17,25,33-34,45-46,51-52
227242
:linenos:
228243

229244
Debug mode
@@ -256,8 +271,7 @@ This is the default format of the logs::
256271
{client_ip} -- "{request_method} {path}" {request_size} -- "{response_status}" {response_size}
257272

258273
If you need more information about the server or request, or you want it in a different format you can modify
259-
functions at the bottom of ``adafruit_httpserver/server.py`` and ``adafruit_httpserver/response.py`` that
260-
start with ``_debug_...``.
274+
functions at the bottom of ``adafruit_httpserver/server.py`` that start with ``_debug_...``.
261275

262276
NOTE:
263277
*This is an advanced usage that might change in the future. It is not recommended to modify other parts of the code.*

examples/httpserver_authentication_handlers.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,11 @@ def check_if_authenticated(request: Request):
3232
"""
3333
is_authenticated = check_authentication(request, auths)
3434

35-
with Response(request, content_type="text/plain") as response:
36-
response.send("Authenticated" if is_authenticated else "Not authenticated")
35+
return Response(
36+
request,
37+
body="Authenticated" if is_authenticated else "Not authenticated",
38+
content_type="text/plain",
39+
)
3740

3841

3942
@server.route("/require-or-401")
@@ -43,8 +46,7 @@ def require_authentication_or_401(request: Request):
4346
"""
4447
require_authentication(request, auths)
4548

46-
with Response(request, content_type="text/plain") as response:
47-
response.send("Authenticated")
49+
return Response(request, body="Authenticated", content_type="text/plain")
4850

4951

5052
@server.route("/require-or-handle")
@@ -56,12 +58,15 @@ def require_authentication_or_manually_handle(request: Request):
5658
try:
5759
require_authentication(request, auths)
5860

59-
with Response(request, content_type="text/plain") as response:
60-
response.send("Authenticated")
61+
return Response(request, body="Authenticated", content_type="text/plain")
6162

6263
except AuthenticationError:
63-
with Response(request, status=UNATUHORIZED_401) as response:
64-
response.send("Not authenticated - Manually handled")
64+
return Response(
65+
request,
66+
body="Not authenticated - Manually handled",
67+
content_type="text/plain",
68+
status=UNATUHORIZED_401,
69+
)
6570

6671

6772
server.serve_forever(str(wifi.radio.ipv4_address))

examples/httpserver_authentication_server.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ def implicit_require_authentication(request: Request):
2525
Implicitly require authentication because of the server.require_authentication() call.
2626
"""
2727

28-
with Response(request, content_type="text/plain") as response:
29-
response.send("Authenticated")
28+
return Response(request, body="Authenticated", content_type="text/plain")
3029

3130

3231
server.serve_forever(str(wifi.radio.ipv4_address))

examples/httpserver_chunked.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import socketpool
66
import wifi
77

8-
from adafruit_httpserver import Server, Request, Response
8+
from adafruit_httpserver import Server, Request, ChunkedResponse
99

1010

1111
pool = socketpool.SocketPool(wifi.radio)
@@ -18,12 +18,14 @@ def chunked(request: Request):
1818
Return the response with ``Transfer-Encoding: chunked``.
1919
"""
2020

21-
with Response(request, chunked=True) as response:
22-
response.send_chunk("Adaf")
23-
response.send_chunk("ruit")
24-
response.send_chunk(" Indus")
25-
response.send_chunk("tr")
26-
response.send_chunk("ies")
21+
def body():
22+
yield "Adaf"
23+
yield b"ruit" # Data chunk can be bytes or str.
24+
yield " Indus"
25+
yield b"tr"
26+
yield "ies"
27+
28+
return ChunkedResponse(request, body)
2729

2830

2931
server.serve_forever(str(wifi.radio.ipv4_address))

examples/httpserver_cpu_information.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@
22
#
33
# SPDX-License-Identifier: Unlicense
44

5-
import json
65
import microcontroller
76
import socketpool
87
import wifi
98

10-
from adafruit_httpserver import Server, Request, Response
9+
from adafruit_httpserver import Server, Request, JSONResponse
1110

1211
pool = socketpool.SocketPool(wifi.radio)
1312
server = Server(pool, debug=True)
@@ -25,8 +24,7 @@ def cpu_information_handler(request: Request):
2524
"voltage": microcontroller.cpu.voltage,
2625
}
2726

28-
with Response(request, content_type="application/json") as response:
29-
response.send(json.dumps(data))
27+
return JSONResponse(request, data)
3028

3129

3230
server.serve_forever(str(wifi.radio.ipv4_address))

examples/httpserver_handler_serves_file.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import socketpool
77
import wifi
88

9-
from adafruit_httpserver import Server, Request, Response
9+
from adafruit_httpserver import Server, Request, FileResponse
1010

1111

1212
pool = socketpool.SocketPool(wifi.radio)
@@ -19,8 +19,7 @@ def home(request: Request):
1919
Serves the file /www/home.html.
2020
"""
2121

22-
with Response(request, content_type="text/html") as response:
23-
response.send_file("home.html", root_path="/www")
22+
return FileResponse(request, "home.html", "/www")
2423

2524

2625
server.serve_forever(str(wifi.radio.ipv4_address))

examples/httpserver_mdns.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import socketpool
77
import wifi
88

9-
from adafruit_httpserver import Server, Request, Response
9+
from adafruit_httpserver import Server, Request, FileResponse
1010

1111

1212
mdns_server = mdns.Server(wifi.radio)
@@ -22,8 +22,8 @@ def base(request: Request):
2222
"""
2323
Serve the default index.html file.
2424
"""
25-
with Response(request, content_type="text/html") as response:
26-
response.send_file("index.html")
25+
26+
return FileResponse(request, "index.html", "/www")
2727

2828

2929
server.serve_forever(str(wifi.radio.ipv4_address))

examples/httpserver_methods.py

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,33 +5,66 @@
55
import socketpool
66
import wifi
77

8-
from adafruit_httpserver import Server, Request, Response, GET, POST, PUT, DELETE
8+
from adafruit_httpserver import Server, Request, JSONResponse, GET, POST, PUT, DELETE
99

1010

1111
pool = socketpool.SocketPool(wifi.radio)
1212
server = Server(pool, debug=True)
1313

14+
objects = [
15+
{"id": 1, "name": "Object 1"},
16+
]
17+
1418

1519
@server.route("/api", [GET, POST, PUT, DELETE], append_slash=True)
1620
def api(request: Request):
1721
"""
1822
Performs different operations depending on the HTTP method.
1923
"""
2024

25+
# Get objects
2126
if request.method == GET:
22-
# Get objects
23-
with Response(request) as response:
24-
response.send("Objects: ...")
27+
return JSONResponse(request, objects)
2528

29+
# Upload or update objects
2630
if request.method in [POST, PUT]:
27-
# Upload or update objects
28-
with Response(request) as response:
29-
response.send("Object uploaded/updated")
31+
uploaded_object = request.json()
32+
33+
# Find object with same ID
34+
for i, obj in enumerate(objects):
35+
if obj["id"] == uploaded_object["id"]:
36+
objects[i] = uploaded_object
37+
38+
return JSONResponse(
39+
request, {"message": "Object updated", "object": uploaded_object}
40+
)
41+
42+
# If not found, add it
43+
objects.append(uploaded_object)
44+
return JSONResponse(
45+
request, {"message": "Object added", "object": uploaded_object}
46+
)
3047

48+
# Delete objects
3149
if request.method == DELETE:
32-
# Delete objects
33-
with Response(request) as response:
34-
response.send("Object deleted")
50+
deleted_object = request.json()
51+
52+
# Find object with same ID
53+
for i, obj in enumerate(objects):
54+
if obj["id"] == deleted_object["id"]:
55+
del objects[i]
56+
57+
return JSONResponse(
58+
request, {"message": "Object deleted", "object": deleted_object}
59+
)
60+
61+
# If not found, return error
62+
return JSONResponse(
63+
request, {"message": "Object not found", "object": deleted_object}
64+
)
65+
66+
# If we get here, something went wrong
67+
return JSONResponse(request, {"message": "Something went wrong"})
3568

3669

3770
server.serve_forever(str(wifi.radio.ipv4_address))

0 commit comments

Comments
 (0)