Parse URI of HTTP request

Hey guys,

I am using the ESP8266WebServer class for a Apple Homekit / Homebridge automation project.
I have a device calling my API with something like

http://a.b.c.d/brightness/76

This would set the brightness to 76%.

I can't figure out how to add a wildcard to my code.

server.on("/brightness/<WILDCARD NEEDED HERE>", [](){
    server.send(200, "text/plain", server.uri());
  });

What ideas to you guys have to get you hands on what comes behind the "/brightness/" part of the URI?

Thanks,
Phillip

Use the source, Luke!

https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WebServer/src/ESP8266WebServer.cpp

void ESP8266WebServer::on(const String &uri, HTTPMethod method, ESP8266WebServer::THandlerFunction fn, ESP8266WebServer::THandlerFunction ufn) {
  _addRequestHandler(new FunctionRequestHandler(fn, ufn, uri, method));
}

void ESP8266WebServer::addHandler(RequestHandler* handler) {
    _addRequestHandler(handler);
}

You should be able to create your own RequestHandler implementation that does this stuff, hopefully extending the existing implementation to make things easier.

The existing ones are located at

#include "detail/RequestHandlersImpl.h"

So we go there next.

Basically - just implement the request handler class.

class MyHandler : public RequestHandler {
 bool canHandle(HTTPMethod method, String uri) { 
   return uri != null && uri.startsWith("/brightness/");
 }

  bool handle(ESP8266WebServer& server, HTTPMethod requestMethod, String requestUri) {   
    /* do brighness stuff here */
  }
} myHandler;

void setup() {
  server.addHandler(&myHandler);
}

If you need a lot of different ones, then alter the class to take a closure and a uri prefix in the constructor.

To handle a URL starting with "/brightness" you just need:
server.on("/brightness", myBrightnessHandler);

In the function myBrightnessHandler() you must parse the URL, say using the indexOf() method of the String class. Google for Arduino parse querystring for examples.

PaulMurrayCbr's reply got there first as I was typing this.

That is my issue!

"curl http://a.b.c.d/brightness" triggers the server.on("/brightness", myBrightnessHandler);

But "curl http://a.b.c.d/brightness/100" triggers the server.onNotFound(handleNotFound);

Where do I change what seem to be an exact match to "start with"?
I also tried a regex instead of the string, but that won't work as well.

(My programming skills are very weak btw. I don't think I understand PaulMurrayCbr's post :slight_smile: ).

Thanks,
Phillip

OK. Is entering the URL something like this acceptable to you, which is how a GET request would be presented? That should work with your existing server.on construct:

http://a.b.c.d/brightness?level=100

Unfortunately, I can't change the way Apple Homekit is triggering the device. :frowning:

OK. If the server.on() construct is too inflexible, then you have got PaulMurrayCbr's solution, or you could use a cruder method of explicitly analyzing everything the browser client is sending like in the code example here: Arduino Project Hub

I implemented PaulMurrayCbr's solution. Although there is way too much "{{{}}}" going on and I don't understand the code, it works :slight_smile:

Thanks PaulMurrayCbr and 6v6gt!

Although there is way too much "{{{}}}" going on

Nonsense. There are exactly the right number of curly braces.