The Pico In MicroPython: HTTP Client
Written by Harry Fairhead & Mike James   
Monday, 02 January 2023
Article Index
The Pico In MicroPython: HTTP Client
A Custom Server
A Temperature Sensor Client

A Custom Server

The problem with writing HTTP examples is that how they are handled depends on the sever in use. Not all HTTP servers implement the same range of requests. A simple solution to this problem is to write a custom server and Python makes this very easy. Before you try any of the following examples, create the following Python program on a suitable machine on your local network. Notice that this code is in Python, not MicroPython:

from http.server import HTTPServer, 
BaseHTTPRequestHandler
from io import BytesIO
class SimpleHTTPRequestHandler(BaseHTTPRequestHandler):
def sendResponse(self, cmd):
content_length =
int(self.headers['Content-Length'])
body = self.rfile.read(content_length)
self.send_response(200)
self.end_headers()
response = BytesIO()
response.write(b'This is a '+bytes(cmd, 'utf-8')+
b' request. ')
response.write(b'Received: ')
response.write(body)
self.wfile.write(response.getvalue())
def do_GET(self):
self.send_response(200)
self.end_headers()
self.wfile.write(b'Hello, world!')
def do_HEAD(self):
self.send_response(200)
self.end_headers()

def do_POST(self):
self.sendResponse("POST")
def do_PUT(self):
self.sendResponse("PUT")

def do_DELETE(self):
self.sendResponse("DELETE")
def do_PATCH(self):
self.sendResponse("PATCH")

httpd = HTTPServer(('', 8080), SimpleHTTPRequestHandler)
httpd.serve_forever()

This server implements simple methods to respond to GET, HEAD, PUT, POST, DELETE and PATCH requests. If you want to support a custom request simply include a method that is called do_request where request is the command you want to use. Notice that this custom request is unlikely to be serviced by a standard server, but there is nothing stopping you from implementing your own. In the case of GET, the server sends fixed data – “Hello World” - and for the other it sends back whatever was sent to it by the client, with the exception of HEAD that sends nothing at all except for the headers.

If you install this program on a remote machine on the same network as the Pico then you can use it to test HTTP request programs. With a little work you can also turn it into a server that supports you Pico app in the real world. You can even convert it into an SSL server for HTTPS connections using the Python SSL module.

The urequests Module

The urequests module implements the GET, PUT, POST, PATCH, HEAD and DELETE requests. The most commonly used is GET to retrieve data from a server. All of the methods return a Response object which contains details of the server’s response. This supports a subset of the Python Response object’s properties/methods:

status_code

Integer HTTP status code

reason

Text from of HTTP status code

headers

Dictionary of headers sent by server

content

Data returned by server as bytes

text

Data returned by server as a string

raw 

Data returned by server as a file-like object

json

Data returned by server as a JSON object

encoding

Encoding to be used to convert raw to text utf-8 by default

close

Release Response object

It also has a set of methods – one for each type of request:

head(url)
get(url)
post(url,data=data to send)
put(url,data=data to send)
patch(url,data=data to send)
delete(url)

There is also a single general-purpose method which implements any type of request, including custom requests. It is used by the earlier request methods:

request(
    method,
    url,
    data=None,
    json=None,
    headers={},
    stream=None,
    auth=None,
    timeout=None,
    parse_headers=True,
)

So for example, a call to get(url) is translated into:

request(url,”GET”)

The request method will supply the basic HTTP/HTTPS header and the Host header if these are not provided in the headers dictionary. You can include a user name and password as a tuple for the auth parameter and these are passed to the server in an Authorization header. You can also set json=object as an alternative to using data and have the urequests module send a JSON encoded string, see later. All of the specific request methods will pass on any keyword parameters you include to the general request method.

Notice that the urequests module works with both HTTP and HTTPS and you don’t have to do anything to make HTTPS work. However at the time of writing the support only extends to encrypting the data transfer, the server’s certificate is not checked for validity.

For example, to download a web page using HTTPS you might use:

import urequests
r = urequests.get("https://www.example.com")
print(r.content)
r.close()

This assumes that you already have a WiFi connection. The site www.example.com provides a test server which works with HTTP and HTTPS. If you run this program you will see the HTML that makes up its standard web page.

If you target the Python custom server then you can see all of the request methods in action:

import urequests
url="http://192.168.253.45:8080"
r = urequests.get(url)
print(r.content)
r.close()
buf= b'Hello World'
r=urequests.post(url,data=buf)
print(r.content)
r.close()
r=urequests.put(url,data=buf)
print(r.content)
r.close()
r=urequests.patch(url,data=buf)
print(r.content)
r.close()
r=urequests.head(url)
print(r.content)
print(r.headers)
r.close()
r=urequests.delete(url,data=buf)
print(r.content)
r.close()

Of course, to make this work you have to substitute the IP address of the machine running the Python custom server. Notice that the custom server only supports HTTP, but it is relatively easy to convert it to HTTPS.

If you run this program you will see something like:

b'Hello, world!'
b'This is a POST request. Received: Hello World'
b'This is a PUT request. Received: Hello World'
b'This is a PATCH request. Received: Hello World'
b''
{'Server': 'BaseHTTP/0.6 Python/3.9.2', 
                'Date': 'Thu, 17 Nov 2022 18:20:42 GMT'}
b'This is a DELETE request. Received: Hello World'

If you run this with a standard web server it is unlikely you will see anything other than error messages. The response of a standard web server has to be configured to respond to anything but a simple GET. Usually you have to install a CGI script to deal with anything that sends data to the server.

You should be able to see now that the only difference between an HTTP client and server is that the client initiates the connection and the request. The server simply responds to the client, but it can send data to and receive data from the client. Using this it is possible to implement a simple sensor feeding data to a central server.



Last Updated ( Monday, 02 January 2023 )