Skip to content

Commit

Permalink
Return status 413 for too-large headers.
Browse files Browse the repository at this point in the history
  • Loading branch information
samoconnor committed Jan 14, 2018
1 parent 1df2227 commit b2b5a14
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 2 deletions.
18 changes: 16 additions & 2 deletions src/Messages.jl
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Streaming of request and response bodies is handled by the

module Messages

export Message, Request, Response,
export Message, Request, Response, HeaderSizeError,
reset!,
iserror, isredirect, ischunked, issafe, isidempotent,
header, hasheader, setheader, defaultheader, appendheader,
Expand Down Expand Up @@ -385,6 +385,13 @@ function readstartline!(m::Parsers.Message, r::Request)
end


"""
Arbitrary limit to protect against denial of service attacks.
"""
const header_size_limit = 0x10000

struct HeaderSizeError <: Exception end

"""
readheaders(::IO, ::Parser, ::Message)
Expand All @@ -394,11 +401,18 @@ Throw `EOFError` if input is incomplete.

function readheaders(io::IO, parser::Parser, message::Message)

n = 0
while !headerscomplete(parser) && !eof(io)
excess = parseheaders(parser, readavailable(io)) do h
bytes = readavailable(io)
n += length(bytes)
excess = parseheaders(parser, bytes) do h
appendheader(message, h)
end
unread!(io, excess)
n -= length(excess)
if n > header_size_limit
throw(HeaderSizeError())
end
end
if !headerscomplete(parser)
throw(EOFError())
Expand Down
4 changes: 4 additions & 0 deletions src/Servers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,10 @@ function handle_transaction(f::Function, t::Transaction;
write(t, Response(status, body = HTTP.Parsers.ERROR_MESSAGES[e.code]))
close(t)
return
elseif e isa HeaderSizeError
write(t, Response(413))
close(t)
return
else
rethrow(e)
end
Expand Down
7 changes: 7 additions & 0 deletions test/server.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ sleep(2)

# test http vs. https


# echo response
serverlog = HTTP.FIFOBuffer()
server = HTTP.Servers.Server((req, rep) -> begin
Expand Down Expand Up @@ -61,6 +62,12 @@ r = HTTP.get("http://127.0.0.1:8081/"; readtimeout=30)
@test String(r.body) == ""


# large headers
sleep(2.0)
tcp = connect(ip"127.0.0.1", 8081)
write(tcp, "GET / HTTP/1.1\r\n$(repeat("Foo: Bar\r\n", 10000))\r\n")
@test ismatch(r"HTTP/1.1 413 Request Entity Too Large", String(read(tcp)))

# invalid HTTP
sleep(2.0)
tcp = connect(ip"127.0.0.1", 8081)
Expand Down

0 comments on commit b2b5a14

Please sign in to comment.