Skip to content

Commit b2f9e7f

Browse files
committed
Add $body_bytes_received to log number of (body) bytes read from client, fixes #892.
1 parent e39051d commit b2f9e7f

File tree

3 files changed

+23
-9
lines changed

3 files changed

+23
-9
lines changed

src/Streams.jl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ mutable struct Stream{M <: Message, S <: IO} <: IO
1313
readchunked::Bool
1414
warn_not_to_read_one_byte_at_a_time::Bool
1515
ntoread::Int
16-
nwritten::Int
16+
nread::Int # number of read body bytes
17+
nwritten::Int # number of written body bytes
1718
end
1819

1920
"""
@@ -36,7 +37,7 @@ Creates a `HTTP.Stream` that wraps an existing `IO` stream.
3637
for reuse. If a complete response has not been received, `closeread` throws
3738
`EOFError`.
3839
"""
39-
Stream(r::M, io::S) where {M, S} = Stream{M, S}(r, io, false, false, true, 0, 0)
40+
Stream(r::M, io::S) where {M, S} = Stream{M, S}(r, io, false, false, true, 0, 0, 0)
4041

4142
Messages.header(http::Stream, a...) = header(http.message, a...)
4243
setstatus(http::Stream, status) = (http.message.response.status = status)
@@ -208,6 +209,9 @@ end
208209

209210
@inline function update_ntoread(http::Stream, n)
210211

212+
# Record number of read bytes for logging
213+
http.nread += n
214+
211215
if http.ntoread != unknown_length
212216
http.ntoread -= n
213217
end

src/access_log.jl

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ The following variables are currently supported:
2020
- `$time_local`: local time in Common Log Format
2121
- `$status`: response status code
2222
- `$body_bytes_sent`: number of bytes in response body
23+
- `$body_bytes_received`: number of bytes read from client
2324
2425
## Examples
2526
```julia
@@ -34,7 +35,6 @@ end
3435

3536
function logfmt_parser(s)
3637
s = String(s)
37-
vars = Symbol[]
3838
ex = Expr(:call, :print, :io)
3939
i = 1
4040
while i <= lastindex(s)
@@ -101,6 +101,8 @@ function symbol_mapping(s::Symbol)
101101
:(http.message.response.status)
102102
elseif s === :body_bytes_sent
103103
return :(http.nwritten)
104+
elseif s === :body_bytes_received
105+
return :(http.nread)
104106
else
105107
error("unknown variable in logfmt: $s")
106108
end

test/server.jl

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,12 @@ end # @testset
208208
close(http.stream)
209209
return
210210
end
211+
if http.message.method == "POST" && http.message.target == "/post"
212+
read(http, String)
213+
HTTP.setstatus(http, 200)
214+
HTTP.startwrite(http)
215+
return
216+
end
211217
HTTP.setstatus(http, 200)
212218
HTTP.setheader(http, "Content-Type" => "text/plain")
213219
msg = "hello, world"
@@ -270,19 +276,21 @@ end # @testset
270276
@test occursin(r"^127.0.0.1 - - \[(\d{2})/.*/(\d{4}):\d{2}:\d{2}:\d{2}.*\] \"HEAD / HTTP/1.1\" 200 0 \"-\" \"HTTP\.jl/.*\"$", logs[4].message)
271277

272278
# Custom log format
273-
fmt = logfmt"$http_accept $sent_http_content_type $request $request_method $request_uri $remote_addr $remote_port $remote_user $server_protocol $time_iso8601 $time_local $status $body_bytes_sent"
279+
fmt = logfmt"$http_accept $sent_http_content_type $request $request_method $request_uri $remote_addr $remote_port $remote_user $server_protocol $time_iso8601 $time_local $status $body_bytes_sent $body_bytes_received"
274280
logs = with_testserver(fmt) do
275281
HTTP.get("http://localhost:32612", ["Accept" => "application/json"])
276282
HTTP.get("http://localhost:32612/index.html")
277283
HTTP.get("http://localhost:32612/index.html?a=b")
278284
HTTP.head("http://localhost:32612")
285+
HTTP.post("http://localhost:32612/post", [], "hello, world")
279286
end
280-
@test length(logs) == 4
287+
@test length(logs) == 5
281288
@test all(x -> x.group === :access, logs)
282-
@test occursin(r"^application/json text/plain GET / HTTP/1\.1 GET / 127\.0\.0\.1 \d+ - HTTP/1\.1 \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.* \d+/.*/\d{4}:\d{2}:\d{2}:\d{2}.* 200 12$", logs[1].message)
283-
@test occursin(r"^\*/\* text/plain GET /index\.html HTTP/1\.1 GET /index\.html 127\.0\.0\.1 \d+ - HTTP/1\.1 \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.* \d+/.*/\d{4}:\d{2}:\d{2}:\d{2}.* 200 12$", logs[2].message)
284-
@test occursin(r"^\*/\* text/plain GET /index\.html\?a=b HTTP/1\.1 GET /index\.html\?a=b 127\.0\.0\.1 \d+ - HTTP/1\.1 \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.* \d+/.*/\d{4}:\d{2}:\d{2}:\d{2}.* 200 12$", logs[3].message)
285-
@test occursin(r"^\*/\* text/plain HEAD / HTTP/1\.1 HEAD / 127\.0\.0\.1 \d+ - HTTP/1\.1 \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.* \d+/.*/\d{4}:\d{2}:\d{2}:\d{2}.* 200 0$", logs[4].message)
289+
@test occursin(r"^application/json text/plain GET / HTTP/1\.1 GET / 127\.0\.0\.1 \d+ - HTTP/1\.1 \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.* \d+/.*/\d{4}:\d{2}:\d{2}:\d{2}.* 200 12 0$", logs[1].message)
290+
@test occursin(r"^\*/\* text/plain GET /index\.html HTTP/1\.1 GET /index\.html 127\.0\.0\.1 \d+ - HTTP/1\.1 \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.* \d+/.*/\d{4}:\d{2}:\d{2}:\d{2}.* 200 12 0$", logs[2].message)
291+
@test occursin(r"^\*/\* text/plain GET /index\.html\?a=b HTTP/1\.1 GET /index\.html\?a=b 127\.0\.0\.1 \d+ - HTTP/1\.1 \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.* \d+/.*/\d{4}:\d{2}:\d{2}:\d{2}.* 200 12 0$", logs[3].message)
292+
@test occursin(r"^\*/\* text/plain HEAD / HTTP/1\.1 HEAD / 127\.0\.0\.1 \d+ - HTTP/1\.1 \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.* \d+/.*/\d{4}:\d{2}:\d{2}:\d{2}.* 200 0 0$", logs[4].message)
293+
@test occursin(r"^\*/\* - POST /post HTTP/1\.1 POST /post 127\.0\.0\.1 \d+ - HTTP/1\.1 \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.* \d+/.*/\d{4}:\d{2}:\d{2}:\d{2}.* 200 0 12$", logs[5].message)
286294
end
287295

288296
end # module

0 commit comments

Comments
 (0)