class Rack::Lint

def check_headers(header)

# === The Headers
def check_headers(header)
  ## The header must respond to +each+, and yield values of key and value.
  assert("headers object should respond to #each, but doesn't (got #{header.class} as headers)") {
     header.respond_to? :each
  }
  header.each { |key, value|
    ## The header keys must be Strings.
    assert("header key must be a string, was #{key.class}") {
      key.kind_of? String
    }
    ## Special headers starting "rack." are for communicating with the
    ## server, and must not be sent back to the client.
    next if key =~ /^rack\..+$/
    ## The header must not contain a +Status+ key.
    assert("header must not contain Status") { key.downcase != "status" }
    ## The header must conform to RFC7230 token specification, i.e. cannot
    ## contain non-printable ASCII, DQUOTE or "(),/:;<=>?@[\]{}".
    assert("invalid header name: #{key}") { key !~ /[\(\),\/:;<=>\?@\[\\\]{}[:cntrl:]]/ }
    ## The values of the header must be Strings,
    assert("a header value must be a String, but the value of " +
      "'#{key}' is a #{value.class}") { value.kind_of? String }
    ## consisting of lines (for multiple header values, e.g. multiple
    ## <tt>Set-Cookie</tt> values) separated by "\\n".
    value.split("\n").each { |item|
      ## The lines must not contain characters below 037.
      assert("invalid header value #{key}: #{item.inspect}") {
        item !~ /[\000-\037]/
      }
    }
  }
end