12#if DETWS_ENABLE_OTA && defined(ARDUINO)
28 const char *path =
nullptr;
38static bool ota_check_auth(
HttpReq *req)
41 if (!h || strncmp(h,
"Basic ", 6) != 0)
45 size_t n =
base64_decode(h + 6, decoded,
sizeof(decoded) - 1);
50 const char *colon = (
const char *)memchr(decoded,
':', n);
53 size_t ulen = (size_t)(colon - (
const char *)decoded);
54 const char *pass = colon + 1;
55 return (ulen == strnlen(s_ota.user,
sizeof(s_ota.user))) && (memcmp(decoded, s_ota.user, ulen) == 0) &&
56 (strcmp(pass, s_ota.pass) == 0);
60static bool ota_stream_begin(
HttpReq *req)
62 if (strcmp(req->
method,
"POST") != 0)
64 if (!s_ota.path || strcmp(req->
path, s_ota.path) != 0)
67 s_ota.authed = ota_check_auth(req);
72 if (Update.begin(UPDATE_SIZE_UNKNOWN))
83static void ota_stream_data(
HttpReq *req,
const uint8_t *data,
size_t len)
86 if (s_ota.authed && s_ota.active && !s_ota.error)
88 if (Update.write((uint8_t *)data, len) != len)
94static void ota_handle(uint8_t slot_id,
HttpReq *req)
96 if (!req->body_streaming)
98 s_ota.server->send(slot_id, 400, DET_MIME_TEXT_PLAIN,
"POST a raw firmware image");
103 s_ota.server->send(slot_id, 401, DET_MIME_TEXT_PLAIN,
"Unauthorized");
106 bool ok = s_ota.active && !s_ota.error && Update.end(
true);
111 s_ota.server->send(slot_id, 400, DET_MIME_TEXT_PLAIN,
"Update failed");
114 s_ota.server->send(slot_id, 200, DET_MIME_TEXT_PLAIN,
"OK - rebooting");
121 s_ota.server = &server;
123 strncpy(s_ota.user, user ? user :
"", sizeof(s_ota.user) - 1);
124 s_ota.user[
sizeof(s_ota.user) - 1] =
'\0';
125 strncpy(s_ota.pass, pass ? pass :
"", sizeof(s_ota.pass) - 1);
126 s_ota.pass[
sizeof(s_ota.pass) - 1] =
'\0';
128 http_parser_set_stream_hooks(ota_stream_begin, ota_stream_data);
#define MAX_AUTH_LEN
Maximum username or password length for HTTP Basic Authentication.
size_t base64_decode(const char *src, uint8_t *dst, size_t dst_cap)
Decode a null-terminated Base64 string.
Single-port HTTP server with deterministic, zero-allocation execution.
void on(const char *path, HttpMethod method, Handler callback)
Register a route handler.
Pluggable monotonic clock for all library timing.
void dwsdelay(uint32_t ms)
Block for at least ms milliseconds - the library's single delay primitive.
Layer 7 (Application) - public HTTP routing API.
@ HTTP_POST
Non-idempotent create / action.
const char * http_get_header(const HttpReq *req, const char *key)
Look up a header value by name (case-insensitive).
Standalone HTTP/1.1 request parser - no transport dependency.
Shared HTTP Content-Type ("MIME") string constants (one source of truth).
void detws_ota_begin(DetWebServer &server, const char *path, const char *user, const char *pass)
Register an authenticated streaming OTA endpoint.
Optional authenticated OTA firmware update (DETWS_ENABLE_OTA).
Fully-parsed HTTP/1.1 request.
char method[DETWS_METHOD_BUF_SIZE]
HTTP method, null-terminated (OPTIONS, or WebDAV methods when enabled).
char path[MAX_PATH_LEN]
URL path, null-terminated; no query string.