-
Notifications
You must be signed in to change notification settings - Fork 85
Description
When using httr2::req_body_file, httr2 opens a connection to the file being uploaded but never closes it. Eventually the handle gets closed by the garbage collector, but a warning gets printed onto the console.
Looking at the source, I see some code that is supposed to close the handle on a short read:
Lines 241 to 246 in 06e9133
| out <- readBin(con, "raw", nbytes) | |
| if (length(out) < nbytes) { | |
| close(con) | |
| done <<- TRUE | |
| con <<- NULL | |
| } |
However from what I can tell by adding print statements, libcurl never tries to read more than necessary, so short reads never happen, even on a successful file transfer. For small enough files, nbytes is always just equal to size, and to length(out)
One possible solution would be to accumulate the number of bytes read so far (the sum of all the length(out)), and when that equals size then close the file. This would work in the happy case where the connection is not closed early.
I think a more foolproof solution would be to record the connection handle in the request object, and have req_perform close it when the request is complete.
Example reproduction:
> writeLines("Hello", "hello.txt")
> httr2::request("https://example.com") |> httr2::req_body_file("hello.txt") |> httr2::req_perform()
<httr2_response>
POST https://example.com/
Status: 200 OK
Content-Type: text/html
Body: In memory (1256 bytes)
> gc()
used (Mb) gc trigger (Mb) max used (Mb)
Ncells 6221410 332.3 9245604 493.8 9245604 493.8
Vcells 37136790 283.4 64900073 495.2 42431065 323.8
Warning message:
In .Internal(gc(verbose, reset, full)) :
closing unused connection 3 (hello.txt)
The call to gc() is used to force the GC to run, but even without it the warning message gets printed eventually.