Release notes

HAProxy Data Plane API 3.4 release notes

The HAProxy Data Plane API 3.4 release rewrites the API server from go-swagger to a chi router with oapi-codegen generated handlers (OpenAPI 3) and adds full configuration support for HAProxy 3.4. Endpoint paths, methods, parameters and success responses are unchanged, but a small number of client-visible behavior changes are described below.

This release supports HAProxy 3.4 and newer versions.

New features Jump to heading

New features in this release include the following:

  • Added support for the force-be-switch frontend directive, with a registered handler and parser/configuration support.

  • Added full CRUD support for the HAProxy healthcheck section, including handlers and oapi-codegen specification and configuration, parser and specification support.

  • Added HAProxy 3.4 proxy options: option use-small-buffers (defaults, listen, backend) with optional queue, l7-retries and check modes; and stats show-version (defaults, frontend, listen, backend) for the stats page.

  • Added HAProxy 3.4 global process options: cpu-affinity, max-threads-per-group, and stats calculate-max-counters.

  • Added HAProxy 3.4 global tunable options: tune.bufsize.large, tune.cli.max-payload-size, tune.h2.be.max-frames-at-once, tune.h2.fe.max-frames-at-once, tune.h2.fe.max-rst-at-once, tune.h2.log-errors, tune.lua.openlibs, tune.quic.fe.stream.max-total, tune.defaults.purge, tune.h1.be.glitches-threshold, tune.h1.fe.glitches-threshold, and tune.ssl.certificate-compression.

  • Added the HTTP actions add-headers-bin, del-headers-bin, and set-headers-bin.

  • Added the filter-sequence directive and comp-req / comp-res filters.

  • Extended set-timeout, do-log and filter trace for HAProxy 3.4.

  • Added the quic-cc-algo server directive.

  • Added the shards and tcp-ss bind options.

  • Added the fd-hard-limit global option.

  • Allowed HAProxy variables in the format ${VAR} in peer entries, nameservers, mailer entries, userlist groups/users, and frontend log_tag.

  • Removed the deprecated req_ssl_sni, replaced by req.ssl_sni.

  • Extended ACME support:

    • Added support for the dns-persist-01 ACME challenge.
    • Added the profile ACME keyword.
    • Added new ACME keywords for HAProxy 3.4: challenge-ready, dns-delay, and dns-timeout.
    • Allowed setting the DNS TTL via acme-vars.

    For a tutorial, see Enable TLS by using the ACME protocol.

  • Updated runtime behavior:

    • Added all supported server parameters to the runtime server handler.
    • Added all fields for the runtime server, added server weight and made the address editable.
    • Improved HAProxy runtime version checks and allowed ExecuteRaw to run multiple commands at once.
  • Updated server and request handling:

    • Added a configurable request body size limit via --max-body-size (default 1 GiB).
    • Stream multipart uploads instead of buffering them in memory.
    • Exposed the client-native validate_files_after and validate_files_before options.

Major changes Jump to heading

Major changes in this release include the following:

  • Replaced the go-swagger generated DataPlaneAPI server with a chi router and oapi-codegen generated handlers (OpenAPI 3). Where chi’s defaults differ from the old server, the router carries explicit code to keep the wire behavior unchanged:

    • JSON bodies for router-level errors: chi answers unmatched paths and disallowed methods with plain-text bodies (404 page not found); custom handlers restore the JSON shape the go-swagger server returned ({"code": 404, "message": "path ... was not found"}). They are registered on both the root router and the mounted /v3 sub-router.
    • The Allow header on 405 responses: RFC 9110 requires a 405 response to list the methods the resource supports, and the go-swagger server did so; chi does not expose the matched route’s allowed methods to a custom 405 handler, so the handler rebuilds the list by probing the router with each standard method for the requested path.
    • Trailing slashes are ignored: Requests are routed as if a trailing slash were absent (chi’s StripSlashes middleware), so /v3/.../maps and /v3/.../maps/ hit the same handler.
    • Reload-ID header spelling: The specification spells the reload header Reload-ID, while the server sends the canonical Reload-Id form — exactly as the old go-swagger server did, since Go’s http.Header canonicalizes header names on write. Header names are case-insensitive, so clients should treat the two spellings as equal.
  • Migrated all handlers to oapi-codegen and moved the path specification out of client-native into dataplaneapi, with new specification-generation tooling.

  • Removed the now unused operations folder and deprecated generation code.

Bug fixes Jump to heading

This release includes the following bug fixes:

  • Trigger a reload when replacing an http-errors section.
  • Fixed data races, a goroutine leak and reconnect logic in the events listener.
  • Fixed a nil-dereference panic in the events listener Stop().
  • ACME: fixed saving certificates into a crt-store.
  • ACME: increased the default TTL to 1 minute.
  • Fixed ACME DNS-01 propagation checks.
  • Return the correct error code when adding duplicates into a map file.
  • Ignore empty runtime API commands.
  • Fixed crashes and non-idempotent serialization.
  • Order the fcgi-app section before proxies.
  • Set the log-profile metadata comment on the right section.
  • Preserve quoting of log-profile step sd/format.
  • Fixed serialization of the ACME provider-name.
  • Added " to name regexes to support variable names.
  • Dropped the RSA-only bits minimum for ACME.
  • Fixed read-only fields for the SSL certificate resource.
  • Generate the specification with the proper template.
  • Fixed a typo in specification description fields.
  • Fixed force-be-switch rule parsing and parts condition.
  • crt_store: fixed the section to match the v3 URL structure.
  • userlists: fixed ordering of users in serialization.
  • dgram-bind: fixed IPv6 address parsing and serialization.
  • server: don’t set the port to 0 when it isn’t set.
  • Fixed a typo and a boolean type in the runtime server.
  • raw: use the custom validation command on validate-only.
  • Ensure heredoc payloads have a blank-line terminator.
  • Fixed a data race on lastError causing a nil-pointer panic.
  • Fixed an EventListener Close() deadlock and channel panic.
  • Reject special characters in file names.
  • Get the real storage name of certificates.

Other Changes Jump to heading

Other changes in this release include the following.

Build and dependencies Jump to heading

  • Upgraded Go to 1.26.
  • Upgraded golangci-lint and fixed the resulting linting errors.
  • Upgraded the client-native library to v6.4.0.
  • Updated AWS SDK, golang.org/x, go-openapi and gRPC packages.
  • Added specification-generation support and updated codegen dependencies.
  • client-native: upgraded go-method-gen to v0.1.4 and handled interface types in the struct-equal generator.

Testing Jump to heading

  • Migrated e2e fixtures to log_targets.
  • Added e2e and unit tests for the healthcheck section, the auth middleware, and the respond helpers.
  • Fixed stale endpoint paths and assertions; raw endpoints no longer send JSON; moved crt-list tests to the proper URL.
  • Fixed a flaky SSL storage test and a syntax error in the e2e groups test.

CI/CD Jump to heading

  • Require pipelines-check for all jobs and added JUnit reporting.
  • Added check-dependencies and check-committer jobs.
  • Use the latest-alpine golang image; removed the check-large-files job; bumped the commit-check version.

Breaking changes Jump to heading

This release introduces the following breaking changes:

  • Validation failures that previously carried go-swagger internal codes in the body (e.g. {"code": 606} with HTTP 422) now return the HTTP status in the body ({"code": 422}). Clients matching on the old 6xx body codes must switch to the HTTP status.

  • Raw configuration endpoints are text-only. POST /services/haproxy/configuration/raw accepts only text/plain bodies; the previous (accidental) JSON-encoded-string body is no longer accepted, and error responses are now application/json instead of text/plain.

  • Unmatched paths require authentication. Basic auth is enforced in front of the router, so an unauthenticated request to a non-existent path now returns 401 instead of 404.

  • SSL certificate DELETE can return 204. DELETE /services/haproxy/storage/ssl_certificates/{name} without skip_reload/force_reload now removes via the HAProxy Runtime API and returns 204 on success, falling back to 202 with a Reload-ID header. Treat both as success.

  • Request bodies are capped at 1 GiB by default. Bodies exceeding the limit are rejected with 413. This is configurable via --max-body-size (max_body_size); A 0 value disables it.

  • Replacing acme, log_profiles, crt_stores, mailers_section and http_errors_sections now triggers a reload. These PUT endpoints previously wrote the change without scheduling a reload; they now follow the standard pattern (202 with Reload-ID, or 200 with force_reload=true).

  • Removed deprecated process-manager (program) endpoints, following the removal of the program section from HAProxy.

  • Removed unused cluster endpoints.

  • Removed deprecated --log-* / --syslog-* CLI options and the persisted log storage section, superseded by the log_targets configuration. When no log targets are configured, the API defaults to a stdout target.

Contributors Jump to heading

Thank you to those who contributed to HAProxy Data Plane API 3.4!

Contributor Area
AdamJCrawford FEATURE
ahusic FEATURE, BUILD, TEST
Andjelko Iharos BUG
Dario Tranchitella BUG
Dinko Korunic BUG
Helene Durand FEATURE
Ivan Matmati FEATURE, BUILD
Marko Juraga FEATURE, BUG, BUILD, CLEANUP, DOC, TEST
Olivier Duclos FEATURE, BUG, BUILD, TEST
Pierre-Alain SIMON FEATURE
Robert Maticevic FEATURE, BUG, BUILD, CLEANUP, DOC, REORG, TEST
Zlatko Bratkovic FEATURE, BUILD

Do you have any suggestions on how we can improve the content of this page?