Releases: hoeken/PsychicHttp
v3.1.2
v3.1.1
Bug Fix - Memory Exhaustion
- WebSocket send backpressure (
PsychicWebSocket): bound the internal heap a stalled client can consume.sendMessage()copies every outgoing frame and queues it viahttpd_ws_send_data_async(), freeing the copy only when the send completes. Previously there was no limit on frames in flight per client, so a client whose TCP connection stalls (WiFi roam, out of range, half-open socket) stops draining its queue while a frequently-broadcasting app piles up queued frames until internal heap is exhausted — at which point unrelated subsystems (e.g. the WiFi stack mid-reconnect) fail on tiny allocations and the device aborts. (#250)PSYCHIC_WS_MAX_PENDING_FRAMES— cap in-flight frames per client (default8, set0to disable). Over the cap,sendMessage()drops the frame and returnsESP_ERR_NO_MEM, bounding the heap any single stalled client can consume regardless of broadcast rate. The per-client counter is ashared_ptr<atomic<int>>so an in-flight async send can safely outlive the client object, which is destroyed on disconnect while callbacks may still be pending on the httpd task.PSYCHIC_WS_PSRAM_PAYLOAD(opt-in) — allocate the per-frame payload copy from PSRAM, falling back to internal heap on boards without it, keeping queued frames out of the scarce internal pool WiFi/lwip depend on.sendAll(): a failed send now continues to the remaining clients instead of breaking the loop, so one client at its cap can't abort the broadcast.
v3.1.0
3.1.0
New API
- WebSocket opt-in static RX buffer + max-frame guard (
PsychicWebSocket): two build-flag-gated optimisations for no-PSRAM or otherwise heap-constrained boards. Both guards compile out when the flags are not defined, so default behaviour is unchanged.-
PSYCHIC_WS_MAX_FRAME_SIZE— reject incoming WS frames larger than the given byte count before they reachcalloc. Without the cap, a single oversized frame (a rogue client or firmware bug) triggers a large allocation that may fail or fragment SRAM on tight boards. -
PSYCHIC_WS_RX_STATIC_BUFFER(requiresPSYCHIC_WS_MAX_FRAME_SIZE) — replace the per-framecalloc/freewith a single static buffer (PSYCHIC_WS_MAX_FRAME_SIZE + 1bytes,MALLOC_CAP_INTERNAL) pre-allocated automatically insidePsychicHttpServer::begin()/start(), while the heap is still fresh. On ESP32 boards without PSRAM the internal SRAM allocator gets fragmented by hundreds ofcalloc/freecycles, eventually producing spurious WS disconnects even with healthy total free heap; a single pre-allocated buffer eliminates the fragmentation. A mutex serialises concurrent WS clients through the single buffer. No application code is required beyond the build flags — a lazy fallback also covers any path that receives a frame beforebegin()has run.// In build flags (e.g. platformio.ini): // -D PSYCHIC_WS_MAX_FRAME_SIZE=2048 // -D PSYCHIC_WS_RX_STATIC_BUFFER // That's it — the buffer is allocated for you in server.begin().
-
Bug Fixes
PsychicResponse: chunked responses emitted the HTTP status"0 unknown"instead of"200 OK"._codedefaulted to 0, but the chunked send path (PsychicFileResponse,PsychicStreamResponse,PsychicJson) callssendHeaders()directly, bypassing theif (!_code) setCode(200)fallback that only lives insend(). The constructor default was restored to 200 (regression from prior versions). (#248)PsychicStaticFileHandler::_getFile(): strip query strings and URL-decode the request path. The handler previously used the raw URI tail verbatim, so requests with a query string (e.g."app.css?v=2") or percent-encoded names (e.g."my%20file.txt") failed to resolve. It now drops everything after the first'?'and URL-decodes via the existingurlDecodehelper, with the traversal check moved after decoding so encoded sequences like"%2e%2e"can't slip past. (#249)
v3.0.0
What's Changed
- Sync espidf branch fixes from fork (IDF 4.4/5/6 CI and compatibility) by @simonttp78 in #246
- Release candidate 3.0.0-rc.1: native ESP-IDF support and API parity updates by @simonttp78 in #245
New Contributors
- @simonttp78 made their first contribution in #246
Full Changelog: 2.2.0...3.0.0
v2.2.0
- fix: memory leaks — add PsychicEndpoint destructor to delete handler; removeEndpoint/removeHandler/removeRewrite now delete removed objects; reset() deletes middleware chain
- fix: stale endpoint state — removeEndpoint now cleans up _esp_idf_endpoints so WebSocket entries are properly unregistered across server restarts
- fix: HTTPS server now syncs max_uri_handlers and stack_size from config before starting (both were silently ignored before)
- fix: path traversal attack blocked in static file handler (#security)
- fix: redirect response code was initialized wrong, breaking redirects (#239)
- fix: correct integer comparisons in indexOf() checks, char overflow in auth buffer, and format specifiers for size_t
- fix: urlDecode bounds-checks before reading past a trailing %
- fix: regex URI matching now catches invalid patterns instead of crashing
- fix: closeCallback guards against null handler before calling checkForClosedClient
- fix: improper delegation call in PsychicJSONResponse
- feat: removed urlencode external dependency — pulled into repository as src/UrlEncode.cpp
- feat: replaced WiFi.h/ETH.h dependencies with generic esp_netif API; isConnected(), ON_STA_FILTER, and ON_AP_FILTER now work on all interface types including ESP32-P4
- feat: esp_netif compatibility — use esp_netif_next loop for older ESP-IDF versions (#235)
- feat: added warning when registering WebSocket handler after start() call (#233)
- feat: ESP-IDF v5.5 support added; v6.0 removed pending Arduino support
- fix: NTP/DHCP handling for ESP-IDF
- examples: increased stack size to fix multipart file upload issues; added start() call to HTTPS redirect server example
v2.1.2
v2.1.1
v2.1.0
- send to all clients, not bail on the first one.
- Fix issue whereby H2 encoding ignores method and defaults to HTTP_GET. (#202)
- now using the stable version of pioarduino.
- V2 dev rollup: update PsychicFileResponse (set status and content type before chunked responses), fix getCookie, and add pong reply to ping. (#228, #207, #209, #222)
- Update async_worker.cpp to fix compatibility with Arduino ESP32 3.3.0. (#225)
- fixed a mistake from the pull merge.
- Moved setting content type and response code into sendHeaders(). (PR #220)
- Check if content size is 0 before sending a response. (#218)
- Fix crash with Event Source and update CI / IDF examples. (#221)
- fixed EventSource error with missing headers (content type, cache-control, keep-alive).
- fixed the CI to use the latest stable versions.
- ugh. CI so annoying.
- bump to v2.1.0.
v2.0.0
I apologize for sitting on this release for so long. Its been almost a year and life just sort of got away from me. I'd like to get this release out and then start working through the backlog of pull requests and issues. v2.0 has been very stable for me, so I think its best to release it get some momentum building.
- Huge amount of work was done to add MiddleWare and some more under the hood updates
- Modified the request handling to bring initial url matching and filtering into PsychicHttpServer itself.
- Fixed a bug with filter() where endpoint is matched, but filter fails and it doesn't continue matching further endpoints on same uri (checks were in different codebases)
- HTTP_ANY support
- unlimited endpoints (no more need to manually set config.max_uri_handlers)
- much more flexibility for future
- Endpoint Matching Updates
- Endpoint matching functions can be set on server level (
server.setURIMatchFunction()) or endpoint level (endpoint.setURIMatchFunction()) - Added convenience macros MATCH_SIMPLE, MATCH_WILDCARD, and MATCH_REGEX
- Added regex matching of URIs, enable it with define PSY_ENABLE_REGEX
- On regex matched requests, you can get match data with request->getRegexMatches()
- Endpoint matching functions can be set on server level (
- Ported URL rewrite functionality from ESPAsyncWS