Is this a bug? "Unable to convert message in HTX ..."

I think it is a bug, but a pretty minor one. I wanted to check here before I create a ticket unnecessarily. To start, I created a reference repository: https://github.com/ingshtrom/haproxy-htx-conversion-issue

You can clone it and run ./test.sh. Essentially what it does is have a single backend which uses the errorfile directive to serve a file. There are two configs and two error files to load. The only difference in the configs is the file path. The difference in the error files is that the bad one includes an extra space prior to the newline on line 6. I will include a bad error file for convenience below:

HTTP/1.1 429 Too Many Requests
Cache-Control: no-cache
Connection: close
Content-Type: text/plain
Retry-After: 60
 
Too Many Requests (HAP429).

Bad Config:

backend 429_tarpit
  errorfile 500 /etc/haproxy/429-bad.http

When I run the test script in the repository, it shows the difference in behavior between the two error files:

You need docker to continue
Running the failure test...
[ALERT] 262/011446 (1) : config: backend '429_tarpit': Unable to convert message in HTX for HTTP return code 500.
[ALERT] 262/011446 (1) : Fatal errors found in configuration.
Failed test finished!
Running the success test...
Configuration file is valid
Good test finished!

I’m really just using the 2.0.5 docker image, but here is the haproxy -vv output if you would like:

docker run --rm --name haproxy -v $(pwd)/haproxy:/usr/local/etc/haproxy:ro -v $(pwd)/haproxy-errors:/etc/haproxy/static/errors:ro haproxy:2.0.5 haproxy -vv HA-Proxy version 2.0.5 2019/08/16 - https://haproxy.org/
Build options :
  TARGET  = linux-glibc
  CPU     = generic
  CC      = gcc
  CFLAGS  = -O2 -g -fno-strict-aliasing -Wdeclaration-after-statement -fwrapv -Wno-format-truncation -Wno-unused-label -Wno-sign-compare -Wno-unused-parameter -Wno-old-style-declaration -Wno-ignored-qualifiers -Wno-clobbered -Wno-missing-field-initializers -Wno-implicit-fallthrough -Wno-stringop-overflow -Wno-cast-function-type -Wtype-limits -Wshift-negative-value -Wshift-overflow=2 -Wduplicated-cond -Wnull-dereference
  OPTIONS = USE_PCRE2=1 USE_PCRE2_JIT=1 USE_GETADDRINFO=1 USE_OPENSSL=1 USE_LUA=1 USE_ZLIB=1

Feature list : +EPOLL -KQUEUE -MY_EPOLL -MY_SPLICE +NETFILTER -PCRE -PCRE_JIT +PCRE2 +PCRE2_JIT +POLL -PRIVATE_CACHE +THREAD -PTHREAD_PSHARED -REGPARM -STATIC_PCRE -STATIC_PCRE2 +TPROXY +LINUX_TPROXY +LINUX_SPLICE +LIBCRYPT +CRYPT_H -VSYSCALL +GETADDRINFO +OPENSSL +LUA +FUTEX +ACCEPT4 -MY_ACCEPT4 +ZLIB -SLZ +CPU_AFFINITY +TFO +NS +DL +RT -DEVICEATLAS -51DEGREES -WURFL -SYSTEMD -OBSOLETE_LINKER +PRCTL +THREAD_DUMP -EVPORTS

Default settings :
  bufsize = 16384, maxrewrite = 1024, maxpollevents = 200

Built with multi-threading support (MAX_THREADS=64, default=4).
Built with OpenSSL version : OpenSSL 1.1.1c  28 May 2019
Running on OpenSSL version : OpenSSL 1.1.1c  28 May 2019
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports : TLSv1.0 TLSv1.1 TLSv1.2 TLSv1.3
Built with Lua version : Lua 5.3.3
Built with network namespace support.
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND
Built with zlib version : 1.2.11
Running on zlib version : 1.2.11
Compression algorithms supported : identity("identity"), deflate("deflate"), raw-deflate("deflate"), gzip("gzip")
Built with PCRE2 version : 10.32 2018-09-10
PCRE2 library supports JIT : yes
Encrypted password support via crypt(3): yes
Built with the Prometheus exporter as a service

Available polling systems :
      epoll : pref=300,  test result OK
       poll : pref=200,  test result OK
     select : pref=150,  test result OK
Total: 3 (3 usable), will use epoll.

Available multiplexer protocols :
(protocols marked as <default> cannot be specified using 'proto' keyword)
              h2 : mode=HTX        side=FE|BE     mux=H2
              h2 : mode=HTTP       side=FE        mux=H2
       <default> : mode=HTX        side=FE|BE     mux=H1
       <default> : mode=TCP|HTTP   side=FE|BE     mux=PASS

Available services :
        prometheus-exporter

Available filters :
        [SPOE] spoe
        [COMP] compression
        [CACHE] cache
        [TRACE] trace

What do you think?

Your 429-bad.http file has no empty line between header and body, so the message is not a valid http response. What looks like an empty line actually starts with a space character. HTX enabled requires that the errorfile is a valid http message, header and body included.

1 Like

Oh gotchya. I saw the extra space, but didn’t know that was invalid for HTTP. Thank you for taking a look!