Skip to content

Commit 7eb5342

Browse files
committed
add code and time metadata for ncurl requests
1 parent 485561a commit 7eb5342

File tree

7 files changed

+61
-32
lines changed

7 files changed

+61
-32
lines changed

NEWS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
* Implements `sha224()`, `sha256()`, `sha384()` and `sha512()` series of fast, optimised cryptographic hash and HMAC generation functions using the 'Mbed TLS' library.
66
* `ncurl()` and `stream()` gain the argmument 'pem' for optionally specifying a certificate authority certificate chain PEM file for authenticating secure sites.
7-
* `ncurl()` now returns an additional `$status` field.
7+
* `ncurl()` now returns additional `$code` (response status code) and `$time` (server date header) fields.
88
* `messenger()` gains the argument 'auth' for authenticating communications based on a pre-shared key.
99
* `random()` gains the argument 'n' for generating a vector of random numbers.
1010

R/nano.R

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ print.sendAio <- function(x, ...) {
273273
#'
274274
print.ncurlAio <- function(x, ...) {
275275

276-
cat("< ncurlAio >\n - $status for status code\n - $raw for raw message\n - $data for message data\n", file = stdout())
276+
cat("< ncurlAio >\n - $code for response status code\n - $time for server date header\n - $raw for raw message\n - $data for message data\n", file = stdout())
277277
invisible(x)
278278

279279
}
@@ -341,5 +341,5 @@ print.errorValue <- function(x, ...) {
341341

342342
#' @export
343343
#'
344-
.DollarNames.ncurlAio <- function(x, pattern = "") grep(pattern, c("status", "raw", "data"),
344+
.DollarNames.ncurlAio <- function(x, pattern = "") grep(pattern, c("code", "time", "raw", "data"),
345345
value = TRUE, fixed = TRUE)

R/ncurl.R

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,10 @@
3434
#' certificate authority certificate chain (and revocation list if present).
3535
#' If missing or NULL, certificates are not validated.
3636
#'
37-
#' @return Named list of 3 elements:
37+
#' @return Named list of 4 elements:
3838
#' \itemize{
39-
#' \item{\code{$status}} {- integer HTTP repsonse status code (200 - OK)}
39+
#' \item{\code{$code}} {- integer HTTP repsonse status code (200 - OK).}
40+
#' \item{\code{$time}} {- character server response header 'Date'.}
4041
#' \item{\code{$raw}} {- raw vector of the received resource (use
4142
#' \code{\link{writeBin}} to save to a file).}
4243
#' \item{\code{$data}} {- converted character string (if \code{'convert' = TRUE}
@@ -80,24 +81,42 @@ ncurl <- function(url,
8081
is.integer(aio) && return(aio)
8182

8283
convert <- missing(convert) || isTRUE(convert)
83-
status <- raw <- data <- NULL
84+
code <- time <- raw <- data <- NULL
8485
unresolv <- TRUE
8586
env <- new.env(hash = FALSE)
86-
makeActiveBinding(sym = "status", fun = function(x) {
87+
makeActiveBinding(sym = "code", fun = function(x) {
8788
if (unresolv) {
8889
res <- .Call(rnng_aio_http, aio)
8990
missing(res) && return(.Call(rnng_aio_unresolv))
9091
if (is.integer(res)) {
9192
data <<- raw <<- res
9293
} else {
93-
status <<- res[[1L]]
94-
raw <<- res[[2L]]
94+
code <<- res[[1L]]
95+
time <<- res[[2L]]
96+
raw <<- res[[3L]]
9597
data <<- if (convert) tryCatch(rawToChar(raw), error = function(e) NULL)
9698
}
9799
aio <<- env[["aio"]] <<- NULL
98100
unresolv <<- FALSE
99101
}
100-
status
102+
code
103+
}, env = env)
104+
makeActiveBinding(sym = "time", fun = function(x) {
105+
if (unresolv) {
106+
res <- .Call(rnng_aio_http, aio)
107+
missing(res) && return(.Call(rnng_aio_unresolv))
108+
if (is.integer(res)) {
109+
data <<- raw <<- res
110+
} else {
111+
code <<- res[[1L]]
112+
time <<- res[[2L]]
113+
raw <<- res[[3L]]
114+
data <<- if (convert) tryCatch(rawToChar(raw), error = function(e) NULL)
115+
}
116+
aio <<- env[["aio"]] <<- NULL
117+
unresolv <<- FALSE
118+
}
119+
time
101120
}, env = env)
102121
makeActiveBinding(sym = "raw", fun = function(x) {
103122
if (unresolv) {
@@ -106,8 +125,9 @@ ncurl <- function(url,
106125
if (is.integer(res)) {
107126
data <<- raw <<- res
108127
} else {
109-
status <<- res[[1L]]
110-
raw <<- res[[2L]]
128+
code <<- res[[1L]]
129+
time <<- res[[2L]]
130+
raw <<- res[[3L]]
111131
data <<- if (convert) tryCatch(rawToChar(raw), error = function(e) NULL)
112132
}
113133
aio <<- env[["aio"]] <<- NULL
@@ -122,8 +142,9 @@ ncurl <- function(url,
122142
if (is.integer(res)) {
123143
data <<- raw <<- res
124144
} else {
125-
status <<- res[[1L]]
126-
raw <<- res[[2L]]
145+
code <<- res[[1L]]
146+
time <<- res[[2L]]
147+
raw <<- res[[3L]]
127148
data <<- if (convert) tryCatch(rawToChar(raw), error = function(e) NULL)
128149
}
129150
aio <<- env[["aio"]] <<- NULL

README.md

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ aio
384384
#> < recvAio >
385385
#> - $data for message data
386386
aio$data |> str()
387-
#> num [1:100000000] -1.07171 -1.2844 0.69956 -0.00593 0.55111 ...
387+
#> num [1:100000000] -0.428 0.206 0.609 0.309 -1.545 ...
388388
```
389389

390390
As `call_aio()` is blocking and will wait for completion, an alternative
@@ -533,18 +533,21 @@ For normal use, it takes just the URL. It can follow redirects.
533533

534534
``` r
535535
ncurl("https://httpbin.org/headers")
536-
#> $status
536+
#> $code
537537
#> [1] 200
538538
#>
539+
#> $time
540+
#> [1] "Thu, 01 Sep 2022 16:11:56 GMT"
541+
#>
539542
#> $raw
540543
#> [1] 7b 0a 20 20 22 68 65 61 64 65 72 73 22 3a 20 7b 0a 20 20 20 20 22 48 6f 73
541544
#> [26] 74 22 3a 20 22 68 74 74 70 62 69 6e 2e 6f 72 67 22 2c 20 0a 20 20 20 20 22
542545
#> [51] 58 2d 41 6d 7a 6e 2d 54 72 61 63 65 2d 49 64 22 3a 20 22 52 6f 6f 74 3d 31
543-
#> [76] 2d 36 33 31 30 64 30 34 38 2d 37 30 63 39 65 34 30 38 30 62 61 63 38 62 35
544-
#> [101] 31 36 64 32 30 62 34 30 31 22 0a 20 20 7d 0a 7d 0a
546+
#> [76] 2d 36 33 31 30 64 39 63 63 2d 31 63 35 32 65 61 66 33 37 31 38 38 61 64 34
547+
#> [101] 37 35 64 37 36 62 30 64 37 22 0a 20 20 7d 0a 7d 0a
545548
#>
546549
#> $data
547-
#> [1] "{\n \"headers\": {\n \"Host\": \"httpbin.org\", \n \"X-Amzn-Trace-Id\": \"Root=1-6310d048-70c9e4080bac8b516d20b401\"\n }\n}\n"
550+
#> [1] "{\n \"headers\": {\n \"Host\": \"httpbin.org\", \n \"X-Amzn-Trace-Id\": \"Root=1-6310d9cc-1c52eaf37188ad475d76b0d7\"\n }\n}\n"
548551
```
549552

550553
For advanced use, supports additional HTTP methods such as POST or PUT.
@@ -555,12 +558,13 @@ res <- ncurl("http://httpbin.org/post", async = TRUE, method = "POST",
555558
data = '{"key": "value"}')
556559
res
557560
#> < ncurlAio >
558-
#> - $status for status code
561+
#> - $code for response status code
562+
#> - $time for server date header
559563
#> - $raw for raw message
560564
#> - $data for message data
561565

562566
call_aio(res)$data
563-
#> [1] "{\n \"args\": {}, \n \"data\": \"{\\\"key\\\": \\\"value\\\"}\", \n \"files\": {}, \n \"form\": {}, \n \"headers\": {\n \"Authorization\": \"Bearer APIKEY\", \n \"Content-Length\": \"16\", \n \"Content-Type\": \"application/json\", \n \"Host\": \"httpbin.org\", \n \"X-Amzn-Trace-Id\": \"Root=1-6310d048-43a6602f3a64cf211e9e8636\"\n }, \n \"json\": {\n \"key\": \"value\"\n }, \n \"origin\": \"79.173.189.133\", \n \"url\": \"http://httpbin.org/post\"\n}\n"
567+
#> [1] "{\n \"args\": {}, \n \"data\": \"{\\\"key\\\": \\\"value\\\"}\", \n \"files\": {}, \n \"form\": {}, \n \"headers\": {\n \"Authorization\": \"Bearer APIKEY\", \n \"Content-Length\": \"16\", \n \"Content-Type\": \"application/json\", \n \"Host\": \"httpbin.org\", \n \"X-Amzn-Trace-Id\": \"Root=1-6310d9cc-620688304f76281859c78bf2\"\n }, \n \"json\": {\n \"key\": \"value\"\n }, \n \"origin\": \"79.173.189.133\", \n \"url\": \"http://httpbin.org/post\"\n}\n"
564568
```
565569

566570
In this respect, it may be used as a performant and lightweight method
@@ -603,10 +607,10 @@ s |> send('{"action": "subscribe", "symbols": "EURUSD"}')
603607
#> [26] 73 79 6d 62 6f 6c 73 22 3a 20 22 45 55 52 55 53 44 22 7d 00
604608

605609
s |> recv(keep.raw = FALSE)
606-
#> [1] "{\"s\":\"EURUSD\",\"a\":0.9944,\"b\":0.9941,\"dc\":\"-0.9443\",\"dd\":\"-0.0094\",\"ppms\":false,\"t\":1662046284000}"
610+
#> [1] "{\"s\":\"EURUSD\",\"a\":0.99541,\"b\":0.99534,\"dc\":\"-0.8419\",\"dd\":\"-0.0084\",\"ppms\":false,\"t\":1662048718000}"
607611

608612
s |> recv(keep.raw = FALSE)
609-
#> [1] "{\"s\":\"EURUSD\",\"a\":0.99413,\"b\":0.99411,\"dc\":\"-0.9717\",\"dd\":\"-0.0097\",\"ppms\":false,\"t\":1662046284000}"
613+
#> [1] "{\"s\":\"EURUSD\",\"a\":0.99537,\"b\":0.99535,\"dc\":\"-0.8459\",\"dd\":\"-0.0084\",\"ppms\":false,\"t\":1662048718000}"
610614

611615
close(s)
612616
```

man/ncurl.Rd

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

src/aio.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -671,9 +671,10 @@ SEXP rnng_aio_http(SEXP aio) {
671671
REprintf("HTTP Server Response: %d %s\n", code, nng_http_res_get_reason(handle->res));
672672
if (code >= 300 && code < 400) {
673673
SEXP out;
674-
PROTECT(out = Rf_allocVector(VECSXP, 2));
674+
PROTECT(out = Rf_allocVector(VECSXP, 3));
675675
SET_VECTOR_ELT(out, 0, Rf_ScalarInteger(code));
676-
SET_VECTOR_ELT(out, 1, Rf_mkString(nng_http_res_get_header(handle->res, "Location")));
676+
SET_VECTOR_ELT(out, 1, Rf_mkString(nng_http_res_get_header(handle->res, "Date")));
677+
SET_VECTOR_ELT(out, 2, Rf_mkString(nng_http_res_get_header(handle->res, "Location")));
677678
UNPROTECT(1);
678679
return out;
679680
}
@@ -683,12 +684,13 @@ SEXP rnng_aio_http(SEXP aio) {
683684
size_t sz;
684685
SEXP out, vec;
685686

686-
PROTECT(out = Rf_allocVector(VECSXP, 2));
687+
PROTECT(out = Rf_allocVector(VECSXP, 3));
687688
SET_VECTOR_ELT(out, 0, Rf_ScalarInteger(code));
689+
SET_VECTOR_ELT(out, 1, Rf_mkString(nng_http_res_get_header(handle->res, "Date")));
688690
nng_http_res_get_data(handle->res, &dat, &sz);
689691
vec = Rf_allocVector(RAWSXP, sz);
690692
memcpy(RAW(vec), dat, sz);
691-
SET_VECTOR_ELT(out, 1, vec);
693+
SET_VECTOR_ELT(out, 2, vec);
692694

693695
UNPROTECT(1);
694696
return out;

src/utils.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,22 +220,23 @@ SEXP rnng_ncurl(SEXP http, SEXP convert, SEXP method, SEXP headers, SEXP data, S
220220

221221
nng_http_res_get_data(res, &dat, &sz);
222222

223-
const char *names[] = {"status", "raw", "data", ""};
223+
const char *names[] = {"code", "time", "raw", "data", ""};
224224
PROTECT(out = Rf_mkNamed(VECSXP, names));
225225

226226
SET_VECTOR_ELT(out, 0, Rf_ScalarInteger(code));
227+
SET_VECTOR_ELT(out, 1, Rf_mkString(nng_http_res_get_header(res, "Date")));
227228

228229
vec = Rf_allocVector(RAWSXP, sz);
229230
memcpy(RAW(vec), dat, sz);
230-
SET_VECTOR_ELT(out, 1, vec);
231+
SET_VECTOR_ELT(out, 2, vec);
231232

232233
if (Rf_asLogical(convert)) {
233234
SEXP expr;
234235
PROTECT(expr = Rf_lang2(nano_RtcSymbol, vec));
235236
cvec = R_tryEvalSilent(expr, R_BaseEnv, &xc);
236237
UNPROTECT(1);
237238
}
238-
SET_VECTOR_ELT(out, 2, cvec);
239+
SET_VECTOR_ELT(out, 3, cvec);
239240

240241
nng_http_res_free(res);
241242
nng_http_req_free(req);

0 commit comments

Comments
 (0)