Skip to content

Commit cbbd151

Browse files
authored
Expose request timing (#735)
1 parent df68c2b commit cbbd151

File tree

8 files changed

+78
-3
lines changed

8 files changed

+78
-3
lines changed

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ export(resp_stream_is_complete)
131131
export(resp_stream_lines)
132132
export(resp_stream_raw)
133133
export(resp_stream_sse)
134+
export(resp_timing)
134135
export(resp_url)
135136
export(resp_url_path)
136137
export(resp_url_queries)

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# httr2 (development version)
22

3+
* `resp_timing()` exposes timing information about the request measured by libcurl (@arcresu, #725).
34
* `req_url_query()` now re-calculates n lengths when using `.multi = "explode"` to avoid select/recycling issues (@Kevanness, #719).
45

56
# httr2 1.1.2

R/resp-timing.R

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#' Extract timing data
2+
#'
3+
#' The underlying curl library measures how long different components of the
4+
#' request take to complete. This function retrieves that information.
5+
#'
6+
#' @inheritParams resp_header
7+
#' @returns Named numeric vector of timing information.
8+
#' The names of the elements in this vector correspond to the names used
9+
#' in [libcurl's `curl_easy_getinfo()` API][curl docs].
10+
#' The most useful component is likely `"total"` (corresponding to
11+
#' `CURLINFO_TOTAL_TIME`), the overall time in seconds to complete the
12+
#' request including any redirects followed.
13+
#'
14+
#' [curl docs]: https://curl.se/libcurl/c/curl_easy_getinfo.html
15+
#' @export
16+
#' @examples
17+
#' req <- request(example_url())
18+
#' resp <- req_perform(req)
19+
#' resp_timing(resp)
20+
resp_timing <- function(resp) {
21+
check_response(resp)
22+
23+
resp$timing
24+
}

R/resp.R

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
#' which will be parsed using the standard rules, or a named list.
2020
#' @param body Response, if any, contained in the response body.
2121
#' For `response_json()`, a R data structure to serialize to JSON.
22+
#' @param timing A named numeric vector giving the time taken by various
23+
#' components.
2224
#' @returns An HTTP response: an S3 list with class `httr2_response`.
2325
#' @export
2426
#' @examples
@@ -30,7 +32,8 @@ response <- function(
3032
url = "https://example.com",
3133
method = "GET",
3234
headers = list(),
33-
body = raw()
35+
body = raw(),
36+
timing = NULL
3437
) {
3538
check_number_whole(status_code, min = 100, max = 700)
3639
check_string(url)
@@ -43,7 +46,8 @@ response <- function(
4346
url = url,
4447
status_code = as.integer(status_code),
4548
headers = headers,
46-
body = body
49+
body = body,
50+
timing = timing
4751
)
4852
}
4953

@@ -76,13 +80,17 @@ new_response <- function(
7680
status_code,
7781
headers,
7882
body,
83+
timing = NULL,
7984
request = NULL,
8085
error_call = caller_env()
8186
) {
8287
check_string(method, call = error_call)
8388
check_string(url, call = error_call)
8489
check_number_whole(status_code, call = error_call)
8590
check_request(request, allow_null = TRUE)
91+
if (!is.null(timing) && !is_bare_numeric(timing)) {
92+
stop_input_type(timing, "a numeric vector", allow_null = TRUE)
93+
}
8694

8795
headers <- as_headers(headers, error_call = error_call)
8896
# ensure we always have a date field
@@ -97,6 +105,7 @@ new_response <- function(
97105
status_code = status_code,
98106
headers = headers,
99107
body = body,
108+
timing = timing,
100109
request = request,
101110
cache = new_environment()
102111
),
@@ -111,6 +120,7 @@ create_response <- function(req, curl_data, body) {
111120
status_code = curl_data$status_code,
112121
headers = as_headers(curl_data$headers),
113122
body = body,
123+
timing = curl_data$times,
114124
request = req
115125
)
116126

man/resp_timing.Rd

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/response.Rd

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-req-perform.R

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ test_that("successful request returns expected response", {
99
expect_s3_class(resp$headers, "httr2_headers")
1010
expect_type(resp$body, "raw")
1111
expect_equal(resp$request, req)
12+
13+
expect_type(resp$timing, "double")
14+
expect_true(all(resp$timing >= 0))
1215
})
1316

1417
test_that("request updates last_response()", {

tests/testthat/test-resp-timing.R

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
test_that("can extract request timing", {
2+
req <- response(timing = c(total = 1))
3+
expect_equal(resp_timing(req), c(total = 1))
4+
})

0 commit comments

Comments
 (0)