varnishtest "H1 authority validation and host normalizarion based on the scheme (rfc3982 6.3.2) or the method (connect)"

feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(2.6-dev0)'"
feature ignore_unknown_macro

barrier b1 cond 2 -cyclic

syslog S1 -level info {
    # C1
    recv
    expect ~ "^.* uri: GET http://toto:poue@hostname/c1 HTTP/1.1; host: {hostname}$"
    barrier b1 sync

    # C2
    recv
    expect ~ "^.* uri: GET http://hostname:8080/c2 HTTP/1.1; host: {hostname:8080}$"
    barrier b1 sync

    # C3
    recv
    expect ~ "^.* uri: GET https://hostname/c3 HTTP/1.1; host: {hostname}$"
    barrier b1 sync

    # C4
    recv
    expect ~ "^.* uri: GET https://hostname:80/c4 HTTP/1.1; host: {hostname:80}$"
    barrier b1 sync

    # C5
    recv
    expect ~ "^.* uri: CONNECT hostname:80 HTTP/1.1; host: {hostname}$"
    barrier b1 sync
    recv
    expect ~ "^.* uri: CONNECT hostname:80 HTTP/1.1; host: {hostname}$"
    barrier b1 sync
    recv
    expect ~ "^.* uri: CONNECT hostname:80 HTTP/1.1; host: {hostname:}$"
    barrier b1 sync

    # C6
    recv
    expect ~ "^.* uri: CONNECT hostname:443 HTTP/1.1; host: {hostname}$"
    barrier b1 sync
    recv
    expect ~ "^.* uri: CONNECT hostname:443 HTTP/1.1; host: {hostname}$"
    barrier b1 sync
    recv
    expect ~ "^.* uri: CONNECT hostname:443 HTTP/1.1; host: {hostname:}$"
    barrier b1 sync

    # C7
    recv
    expect ~ "^.* uri: CONNECT hostname:8443 HTTP/1.1; host: {hostname:8443}$"
    barrier b1 sync

    # C8
    recv
    expect ~ "^.* uri: <BADREQ>; host: $"
    barrier b1 sync

    # C9
    recv
    expect ~ "^.* uri: <BADREQ>; host: $"
    barrier b1 sync

    # C10
    recv
    expect ~ "^.* uri: <BADREQ>; host: $"
    barrier b1 sync

    # C11
    recv
    expect ~ "^.* uri: <BADREQ>; host: $"
    barrier b1 sync

    # C12
    recv
    expect ~ "^.* uri: <BADREQ>; host: $"
    barrier b1 sync

    # C13
    recv
    expect ~ "^.* uri: <BADREQ>; host: $"
    barrier b1 sync

    # C14
    recv
    expect ~ "^.* uri: <BADREQ>; host: $"
    barrier b1 sync

    # C15
    recv
    expect ~ "^.* uri: <BADREQ>; host: $"
    barrier b1 sync

    # C16
    recv
    expect ~ "^.* uri: <BADREQ>; host: $"
    barrier b1 sync

    # C17
    recv
    barrier b1 sync
    expect ~ "^.* uri: <BADREQ>; host: $"

    # C18
    recv
    expect ~ "^.* uri: <BADREQ>; host: $"
    barrier b1 sync

    # C19
    recv
    expect ~ "^.* uri: <BADREQ>; host: $"
    barrier b1 sync

    # C20
    recv
    expect ~ "^.* uri: GET http://hostname/c20 HTTP/1.1; host: {hostname}$"
    barrier b1 sync

    # C21
    recv
    expect ~ "^.* uri: GET https://hostname/c21 HTTP/1.1; host: {hostname}$"
    barrier b1 sync

    # C22
    recv
    expect ~ "^.* uri: GET http://hostname/c22 HTTP/1.1; host: {hostname:80}$"
    barrier b1 sync

    # C23
    recv
    expect ~ "^.* uri: GET https://hostname/c23 HTTP/1.1; host: {hostname:443}$"
    barrier b1 sync

    # C24
    recv
    expect ~ "^.* uri: GET http://hostname/c24 HTTP/1.1; host: {hostname}$"
    barrier b1 sync

    # C25
    recv
    expect ~ "^.* uri: GET https://hostname/c25 HTTP/1.1; host: {hostname}$"
    barrier b1 sync

    # C26
    recv
    expect ~ "^.* uri: GET http://hostname/c26 HTTP/1.1; host: {hostname:}$"
    barrier b1 sync

    # C27
    recv
    expect ~ "^.* uri: GET https://hostname/c27 HTTP/1.1; host: {hostname:}$"
    barrier b1 sync

    # C28
    recv
    expect ~ "^.* uri: GET http://hostname/c28 HTTP/1.1; host: {hostname}$"
    barrier b1 sync

    # C29
    recv
    expect ~ "^.* uri: GET http://hostname/c29 HTTP/1.1; host: {hostname}$"
    barrier b1 sync

    # C30
    recv
    expect ~ "^.* uri: GET https://hostname/c30 HTTP/1.1; host: {hostname}$"
    barrier b1 sync

    # C31
    recv
    expect ~ "^.* uri: GET https://hostname/c31 HTTP/1.1; host: {hostname}$"
    barrier b1 sync

    # C32
    recv
    expect ~ "^.* uri: GET http:/// HTTP/1.1; host: {}$"
    barrier b1 sync

    # C33
    recv
    expect ~ "^.* uri: GET https:/// HTTP/1.1; host: {}$"
    barrier b1 sync

    # C34
    recv
    expect ~ "^.* uri: GET http:/// HTTP/1.1; host: {}$"
    barrier b1 sync

    # C35
    recv
    expect ~ "^.* uri: GET https:/// HTTP/1.1; host: {}$"
    barrier b1 sync

    # C36
    recv
    expect ~ "^.* uri: GET http://hostname/ HTTP/1.1; host: {hostname}$"
    barrier b1 sync

    # C37
    recv
    expect ~ "^.* uri: GET http://hostname/ HTTP/1.1; host: {hostname}$"
    barrier b1 sync

    # C38
    recv
    expect ~ "^.* uri: GET http://hostname/ HTTP/1.1; host: {hostname}$"
    barrier b1 sync

    # C39
    recv
    expect ~ "^.* uri: GET https://hostname/ HTTP/1.1; host: {hostname}$"
    barrier b1 sync

    # C40
    recv
    expect ~ "^.* uri: GET https://hostname/ HTTP/1.1; host: {hostname}$"
    barrier b1 sync

    # C41
    recv
    expect ~ "^.* uri: GET https://hostname/ HTTP/1.1; host: {hostname}$"
    barrier b1 sync

    # C42
    recv
    expect ~ "^.* uri: GET http://hostname:81/ HTTP/1.1; host: {hostname:81}$"
    barrier b1 sync

    # C43
    recv
    expect ~ "^.* uri: GET https://hostname:444/ HTTP/1.1; host: {hostname:444}$"

} -start

haproxy h1 -conf {
    global
    .if feature(THREAD)
        thread-groups 1
    .endif

    defaults
        mode http
        timeout connect "${HAPROXY_TEST_TIMEOUT-5s}"
        timeout client  "${HAPROXY_TEST_TIMEOUT-5s}"
        timeout server  "${HAPROXY_TEST_TIMEOUT-5s}"

    frontend fe
        bind "fd@${fe}"

        http-request capture req.hdr(host) len 512
        log-format "uri: %r; host: %hr"
        log ${S1_addr}:${S1_port} len 2048 local0 debug err

        http-request return status 200
} -start

# default port 80 with http scheme => should be normalized
# Be sure userinfo are skipped
client c1 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://toto:poue@hostname:80/c1" \
      -hdr "host: hostname:80"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# port 8080 with http scheme => no normalization
client c2 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname:8080/c2" \
      -hdr "host: hostname:8080"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# default port 443 with https scheme => should be normalized
client c3 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "https://hostname:443/c3" \
      -hdr "host: hostname:443"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# port 80 with https scheme => no normalization
client c4 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "https://hostname:80/c4" \
      -hdr "host: hostname:80"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# CONNECT on port 80 => should be normalized
client c5 -connect ${h1_fe_sock} {
    txreq \
      -req "CONNECT" \
      -url "hostname:80" \
      -hdr "host: hostname:80"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

client c5 -connect ${h1_fe_sock} {

    txreq \
      -req "CONNECT" \
      -url "hostname:80" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

client c5 -connect ${h1_fe_sock} {

    txreq \
      -req "CONNECT" \
      -url "hostname:80" \
      -hdr "host: hostname:"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# CONNECT on port 443 => should be normalized
client c6 -connect ${h1_fe_sock} {
    txreq \
      -req "CONNECT" \
      -url "hostname:443" \
      -hdr "host: hostname:443"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

client c6 -connect ${h1_fe_sock} {
    txreq \
      -req "CONNECT" \
      -url "hostname:443" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

client c6 -connect ${h1_fe_sock} {
    txreq \
      -req "CONNECT" \
      -url "hostname:443" \
      -hdr "host: hostname:"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# CONNECT on port non-default port => no normalization
client c7 -connect ${h1_fe_sock} {
    txreq \
      -req "CONNECT" \
      -url "hostname:8443" \
      -hdr "host: hostname:8443"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# host miss-match => error
client c8 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname1/" \
      -hdr "host: hostname2"

    rxresp
    expect resp.status == 400
} -run

# Wait matching on log message
barrier b1 sync

# port miss-match => error
client c9 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname:80/" \
      -hdr "host: hostname:81"

    rxresp
    expect resp.status == 400
} -run

# Wait matching on log message
barrier b1 sync

# no host port with a non-default port in abs-uri  => error
client c10 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname:8080/" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 400
} -run

# Wait matching on log message
barrier b1 sync

# non-default host port with a default in abs-uri  => error
client c11 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname/" \
      -hdr "host: hostname:81"

    rxresp
    expect resp.status == 400
} -run

# Wait matching on log message
barrier b1 sync

# miss-match between host headers => error
client c12 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname1/" \
      -hdr "host: hostname1" \
      -hdr "host: hostname2"

    rxresp
    expect resp.status == 400
} -run

# Wait matching on log message
barrier b1 sync

# miss-match between host headers but with a normalization => error
client c13 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname1/" \
      -hdr "host: hostname1:80" \
      -hdr "host: hostname1"

    rxresp
    expect resp.status == 400
} -run

# Wait matching on log message
barrier b1 sync

# CONNECT authoriy without port => error
client c14 -connect ${h1_fe_sock} {
    txreq \
      -req "CONNECT" \
      -url "hostname" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 400
} -run

# Wait matching on log message
barrier b1 sync

# host miss-match with CONNECT => error
client c15 -connect ${h1_fe_sock} {
    txreq \
      -req "CONNECT" \
      -url "hostname1:80" \
      -hdr "host: hostname2:80"

    rxresp
    expect resp.status == 400
} -run

# Wait matching on log message
barrier b1 sync

# port miss-match with CONNECT => error
client c16 -connect ${h1_fe_sock} {
    txreq \
      -req "CONNECT" \
      -url "hostname:80" \
      -hdr "host: hostname:443"

    rxresp
    expect resp.status == 400
} -run

# Wait matching on log message
barrier b1 sync

# no host port with non-default port in CONNECT authority => error
client c17 -connect ${h1_fe_sock} {
    txreq \
      -req "CONNECT" \
      -url "hostname:8080" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 400
} -run

# Wait matching on log message
barrier b1 sync

# no authority => error
client c18 -connect ${h1_fe_sock} {
    txreq \
      -req "CONNECT" \
      -url "/" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 400
} -run

# Wait matching on log message
barrier b1 sync

# no authority => error
client c19 -connect ${h1_fe_sock} {
    txreq \
      -req "CONNECT" \
      -url "hostname:" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 400
} -run

# Wait matching on log message
barrier b1 sync


# default port 80 with http scheme but no port for host value => should be normalized
client c20 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname:80/c20" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync


# default port 443 with https scheme but no port for host value => should be normalized
client c21 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "https://hostname:443/c21" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync


# http scheme, no port for the authority but default port for host value => no normalization
client c22 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname/c22" \
      -hdr "host: hostname:80"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# https scheme, no port for the authority but default port for host value => no normalization
client c23 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "https://hostname/c23" \
      -hdr "host: hostname:443"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync


# http scheme, empty port for the authority and no port for host value => should be normalized
client c24 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname:/c24" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# https scheme, empty port for the authority and no port for host value => should be normalized
client c25 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "https://hostname:/c25" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# http scheme, no port for the authority and empty port for host value => no normalization
client c26 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname/c26" \
      -hdr "host: hostname:"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# https scheme, no port for the authority and empty port for host value => no normalization
client c27 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "https://hostname/c27" \
      -hdr "host: hostname:"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# http scheme, default port for the authority and empty port for host value => should be normalized
client c28 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname:80/c28" \
      -hdr "host: hostname:"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# http scheme, empty port for the authority and default port for host value => should be normalized
client c29 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname:/c29" \
      -hdr "host: hostname:80"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# https scheme, default port for the authority and empty port for host value => should be normalized
client c30 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "https://hostname:443/c30" \
      -hdr "host: hostname:"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# https scheme, empty port for the authority and default port for host value => should be normalized
client c31 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "https://hostname:/c31" \
      -hdr "host: hostname:443"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# Strange cases
client c32 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://:" \
      -hdr "host: :80"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync


client c33 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "https://:" \
      -hdr "host: :443"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

# Strange cases
client c34 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://:" \
      -hdr "host: :"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync


client c35 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "https://:" \
      -hdr "host: :"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

client c36 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

client c37 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname:80" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

client c38 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname:" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

client c39 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "https://hostname" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

client c40 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "https://hostname:443" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

client c41 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "https://hostname:" \
      -hdr "host: hostname"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

client c42 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "http://hostname:81" \
      -hdr "host: hostname:81"

    rxresp
    expect resp.status == 200
} -run

# Wait matching on log message
barrier b1 sync

client c43 -connect ${h1_fe_sock} {
    txreq \
      -req "GET" \
      -url "https://hostname:444" \
      -hdr "host: hostname:444"

    rxresp
    expect resp.status == 200
} -run

syslog S1 -wait
