Skip to content

Releases: hoeken/PsychicHttp

v3.1.2

24 Jun 05:03

Choose a tag to compare

Bug Fixes

  • PsychicJsonResponse: fixed compilation against ArduinoJson v6. Added an arduino3-arduinojson6 CI target. Thanks to @oseiler2. (#251)

v3.1.1

13 Jun 21:17

Choose a tag to compare

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 via httpd_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 (default 8, set 0 to disable). Over the cap, sendMessage() drops the frame and returns ESP_ERR_NO_MEM, bounding the heap any single stalled client can consume regardless of broadcast rate. The per-client counter is a shared_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

07 Jun 08:48

Choose a tag to compare

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 reach calloc. 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 (requires PSYCHIC_WS_MAX_FRAME_SIZE) — replace the per-frame calloc/free with a single static buffer (PSYCHIC_WS_MAX_FRAME_SIZE + 1 bytes, MALLOC_CAP_INTERNAL) pre-allocated automatically inside PsychicHttpServer::begin()/start(), while the heap is still fresh. On ESP32 boards without PSRAM the internal SRAM allocator gets fragmented by hundreds of calloc/free cycles, 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 before begin() 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". _code defaulted to 0, but the chunked send path (PsychicFileResponse, PsychicStreamResponse, PsychicJson) calls sendHeaders() directly, bypassing the if (!_code) setCode(200) fallback that only lives in send(). 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 existing urlDecode helper, with the traversal check moved after decoding so encoded sequences like "%2e%2e" can't slip past. (#249)

v3.0.0

01 Jun 19:31

Choose a tag to compare

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

Full Changelog: 2.2.0...3.0.0

v2.2.0

03 May 03:41

Choose a tag to compare

  • 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

26 Apr 07:21

Choose a tag to compare

fix: close _file before PsychicFileResponse to prevent LittleFS remove() failure

v2.1.1

07 Dec 18:26

Choose a tag to compare

Re-added deleted MAX function per #230

v2.1.0

03 Dec 05:23

Choose a tag to compare

  • 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

07 Nov 05:50

Choose a tag to compare

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()
  • Ported URL rewrite functionality from ESPAsyncWS

v1.2.1

14 Aug 21:24

Choose a tag to compare

  • Fix bug with missing include preventing the HTTPS server from compiling.