On a recent IoT-Project I did, when working with the ESP32 and the associated WiFi-Chip, I found myself struggling to correctly decode and interpret the submitted URL, especially the URL-parameters. To make lives easier, I decided to write a quick post about how I decode and interpret URLs on an ESP32 in my projects.

First, we’ll define the header file and the API we want to expose:

// decode.h

#include <string.h>
#include <ctype.h>

void url_decode(char *source, char *target);

The caller has to allocate and provide both the source- and target-string. We also include ctype.h and string.h for functions we need later on. The function itself is pretty straight forward: We iterate over the source-string and start filling the target string with either the byte from the source-string or, if we encounter an encoded section, the correctly decoded byte.

// decode.c

#include "decode.h"

void url_decode(char *source, char *target)
{
    while (*source)
    {
        if (*source == '%')
        {
            if (source[1] && source[2])
            {
                *target++ = from_hex(source[1]) << 4 | from_hex(source[2]);
                source += 2;
            }
        }
        else if (*source == '+')
        {
            *target++ = ' ';
        }
        else
        {
            *target++ = *source;
        }
        source++;
    }
    *target = '\0';
}

The from_hex-function looks like this:

// decode.c
char from_hex(char ch)
{
    return isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10;
}

It returns the correct character based on the hex-byte it was given. If we encounter %23 in the source-string, from_hex will first return 0b00000010 and then 0b00000011, resulting in # if put together (0b0010 + 0b0011).