Skip to content

Commit 0a2cb1c

Browse files
committed
ncurl and stream code cleanup
1 parent deca66a commit 0a2cb1c

File tree

4 files changed

+185
-340
lines changed

4 files changed

+185
-340
lines changed

R/ncurl.R

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,10 @@ ncurl <- function(url,
138138

139139
res <- .Call(rnng_ncurl, url, convert, method, headers, data, pem)
140140

141-
is.integer(res) && return(res)
142141
is.character(res) && {
143142
continue <- if (interactive()) readline(sprintf("Follow redirect to <%s>? [Y/n] ", res)) else "n"
144143
continue %in% c("n", "N", "no", "NO") && return(res)
145-
return(ncurl(res))
144+
return(eval(`[[<-`(match.call(), 2L, res)))
146145
}
147146

148147
res

README.md

Lines changed: 7 additions & 7 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.431 -1.057 0.272 -0.784 0.329 ...
387+
#> num [1:100000000] -0.4007 -0.5114 1.4174 0.0758 0.2671 ...
388388
```
389389

390390
As `call_aio()` is blocking and will wait for completion, an alternative
@@ -540,11 +540,11 @@ ncurl("https://httpbin.org/headers")
540540
#> [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
541541
#> [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
542542
#> [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 30 66 64 66 37 33 2d 30 65 34 33 63 35 34 62 31 37 38 39 36 37 34
544-
#> [101] 31 33 64 66 32 64 30 62 39 22 0a 20 20 7d 0a 7d 0a
543+
#> [76] 2d 36 33 31 30 63 62 64 31 2d 36 37 66 66 32 64 31 30 30 66 39 64 33 66 66
544+
#> [101] 61 37 32 62 33 61 63 35 37 22 0a 20 20 7d 0a 7d 0a
545545
#>
546546
#> $data
547-
#> [1] "{\n \"headers\": {\n \"Host\": \"httpbin.org\", \n \"X-Amzn-Trace-Id\": \"Root=1-630fdf73-0e43c54b178967413df2d0b9\"\n }\n}\n"
547+
#> [1] "{\n \"headers\": {\n \"Host\": \"httpbin.org\", \n \"X-Amzn-Trace-Id\": \"Root=1-6310cbd1-67ff2d100f9d3ffa72b3ac57\"\n }\n}\n"
548548
```
549549

550550
For advanced use, supports additional HTTP methods such as POST or PUT.
@@ -560,7 +560,7 @@ res
560560
#> - $data for message data
561561

562562
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-630fdf73-5800665b2a82f9933933d8b3\"\n }, \n \"json\": {\n \"key\": \"value\"\n }, \n \"origin\": \"185.225.45.49\", \n \"url\": \"http://httpbin.org/post\"\n}\n"
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-6310cbd2-332f7efa1a782b527ba19a00\"\n }, \n \"json\": {\n \"key\": \"value\"\n }, \n \"origin\": \"79.173.189.133\", \n \"url\": \"http://httpbin.org/post\"\n}\n"
564564
```
565565

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

605605
s |> recv(keep.raw = FALSE)
606-
#> [1] "{\"s\":\"EURUSD\",\"a\":1.00522,\"b\":1.0052,\"dc\":\"0.2865\",\"dd\":\"0.0029\",\"ppms\":false,\"t\":1661984634000}"
606+
#> [1] "{\"s\":\"EURUSD\",\"a\":0.99382,\"b\":0.99375,\"dc\":\"-1.0032\",\"dd\":\"-0.0100\",\"ppms\":false,\"t\":1662045139000}"
607607

608608
s |> recv(keep.raw = FALSE)
609-
#> [1] "{\"s\":\"EURUSD\",\"a\":1.00519,\"b\":1.00517,\"dc\":\"0.2835\",\"dd\":\"0.0029\",\"ppms\":false,\"t\":1661984637000}"
609+
#> [1] "{\"s\":\"EURUSD\",\"a\":0.99377,\"b\":0.99375,\"dc\":\"-1.0083\",\"dd\":\"-0.0100\",\"ppms\":false,\"t\":1662045139000}"
610610

611611
close(s)
612612
```

src/aio.c

Lines changed: 50 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -554,39 +554,17 @@ SEXP rnng_ncurl_aio(SEXP http, SEXP method, SEXP headers, SEXP data, SEXP pem) {
554554
haio->data = handle;
555555
handle->cfg = NULL;
556556

557-
xc = nng_url_parse(&handle->url, httr);
558-
if (xc) {
559-
R_Free(handle);
560-
R_Free(haio);
561-
return mk_error(xc);
562-
}
563-
xc = nng_http_client_alloc(&handle->cli, handle->url);
564-
if (xc) {
565-
nng_url_free(handle->url);
566-
R_Free(handle);
567-
R_Free(haio);
568-
return mk_error(xc);
569-
}
570-
xc = nng_http_req_alloc(&handle->req, handle->url);
571-
if (xc) {
572-
nng_http_client_free(handle->cli);
573-
nng_url_free(handle->url);
574-
R_Free(handle);
575-
R_Free(haio);
576-
return mk_error(xc);
577-
}
557+
if ((xc = nng_url_parse(&handle->url, httr)))
558+
goto exitlevel1;
559+
if ((xc = nng_http_client_alloc(&handle->cli, handle->url)))
560+
goto exitlevel2;
561+
if ((xc = nng_http_req_alloc(&handle->req, handle->url)))
562+
goto exitlevel3;
578563

579564
if (method != R_NilValue) {
580565
const char *met = CHAR(STRING_ELT(method, 0));
581-
xc = nng_http_req_set_method(handle->req, met);
582-
if (xc) {
583-
nng_http_req_free(handle->req);
584-
nng_http_client_free(handle->cli);
585-
nng_url_free(handle->url);
586-
R_Free(handle);
587-
R_Free(haio);
588-
return mk_error(xc);
589-
}
566+
if ((xc = nng_http_req_set_method(handle->req, met)))
567+
goto exitlevel4;
590568
}
591569

592570
if (headers != R_NilValue) {
@@ -597,30 +575,16 @@ SEXP rnng_ncurl_aio(SEXP http, SEXP method, SEXP headers, SEXP data, SEXP pem) {
597575
for (R_xlen_t i = 0; i < hlen; i++) {
598576
const char *head = CHAR(STRING_ELT(headers, i));
599577
const char *name = CHAR(STRING_ELT(names, i));
600-
xc = nng_http_req_set_header(handle->req, name, head);
601-
if (xc) {
602-
nng_http_req_free(handle->req);
603-
nng_http_client_free(handle->cli);
604-
nng_url_free(handle->url);
605-
R_Free(handle);
606-
R_Free(haio);
607-
return mk_error(xc);
608-
}
578+
if ((xc = nng_http_req_set_header(handle->req, name, head)))
579+
goto exitlevel4;
609580
}
610581
break;
611582
case VECSXP:
612583
for (R_xlen_t i = 0; i < hlen; i++) {
613584
const char *head = CHAR(STRING_ELT(VECTOR_ELT(headers, i), 0));
614585
const char *name = CHAR(STRING_ELT(names, i));
615-
xc = nng_http_req_set_header(handle->req, name, head);
616-
if (xc) {
617-
nng_http_req_free(handle->req);
618-
nng_http_client_free(handle->cli);
619-
nng_url_free(handle->url);
620-
R_Free(handle);
621-
R_Free(haio);
622-
return mk_error(xc);
623-
}
586+
if ((xc = nng_http_req_set_header(handle->req, name, head)))
587+
goto exitlevel4;
624588
}
625589
break;
626590
}
@@ -629,80 +593,32 @@ SEXP rnng_ncurl_aio(SEXP http, SEXP method, SEXP headers, SEXP data, SEXP pem) {
629593
if (data != R_NilValue) {
630594
unsigned char *dp = RAW(data);
631595
const size_t dlen = Rf_xlength(data) - 1;
632-
xc = nng_http_req_set_data(handle->req, dp, dlen);
633-
if (xc) {
634-
nng_http_req_free(handle->req);
635-
nng_http_client_free(handle->cli);
636-
nng_url_free(handle->url);
637-
R_Free(handle);
638-
R_Free(haio);
639-
return mk_error(xc);
640-
}
596+
if ((xc = nng_http_req_set_data(handle->req, dp, dlen)))
597+
goto exitlevel4;
641598
}
642599

643-
xc = nng_http_res_alloc(&handle->res);
644-
if (xc) {
645-
nng_http_req_free(handle->req);
646-
nng_http_client_free(handle->cli);
647-
nng_url_free(handle->url);
648-
R_Free(handle);
649-
R_Free(haio);
650-
return mk_error(xc);
651-
}
600+
if ((xc = nng_http_res_alloc(&handle->res)))
601+
goto exitlevel4;
652602

653-
xc = nng_aio_alloc(&haio->aio, iaio_complete, haio);
654-
if (xc) {
655-
nng_http_res_free(handle->res);
656-
nng_http_req_free(handle->req);
657-
nng_http_client_free(handle->cli);
658-
nng_url_free(handle->url);
659-
R_Free(handle);
660-
R_Free(haio);
661-
return mk_error(xc);
662-
}
603+
if ((xc = nng_aio_alloc(&haio->aio, iaio_complete, haio)))
604+
goto exitlevel5;
663605

664606
if (!strcmp(handle->url->u_scheme, "https")) {
665607

666-
xc = nng_tls_config_alloc(&handle->cfg, NNG_TLS_MODE_CLIENT);
667-
if (xc) {
668-
nng_aio_free(haio->aio);
669-
nng_http_res_free(handle->res);
670-
nng_http_req_free(handle->req);
671-
nng_http_client_free(handle->cli);
672-
nng_url_free(handle->url);
673-
R_Free(handle);
674-
R_Free(haio);
675-
return mk_error(xc);
676-
}
608+
if ((xc = nng_tls_config_alloc(&handle->cfg, NNG_TLS_MODE_CLIENT)))
609+
goto exitlevel6;
610+
677611
if (pem == R_NilValue) {
678612
if ((xc = nng_tls_config_server_name(handle->cfg, handle->url->u_hostname)) ||
679613
(xc = nng_tls_config_auth_mode(handle->cfg, NNG_TLS_AUTH_MODE_NONE)) ||
680-
(xc = nng_http_client_set_tls(handle->cli, handle->cfg))) {
681-
nng_tls_config_free(handle->cfg);
682-
nng_aio_free(haio->aio);
683-
nng_http_res_free(handle->res);
684-
nng_http_req_free(handle->req);
685-
nng_http_client_free(handle->cli);
686-
nng_url_free(handle->url);
687-
R_Free(handle);
688-
R_Free(haio);
689-
return mk_error(xc);
690-
}
614+
(xc = nng_http_client_set_tls(handle->cli, handle->cfg)))
615+
goto exitlevel7;
691616
} else {
692617
if ((xc = nng_tls_config_server_name(handle->cfg, handle->url->u_hostname)) ||
693618
(xc = nng_tls_config_ca_file(handle->cfg, CHAR(STRING_ELT(pem, 0)))) ||
694619
(xc = nng_tls_config_auth_mode(handle->cfg, NNG_TLS_AUTH_MODE_REQUIRED)) ||
695-
(xc = nng_http_client_set_tls(handle->cli, handle->cfg))) {
696-
nng_tls_config_free(handle->cfg);
697-
nng_aio_free(haio->aio);
698-
nng_http_res_free(handle->res);
699-
nng_http_req_free(handle->req);
700-
nng_http_client_free(handle->cli);
701-
nng_url_free(handle->url);
702-
R_Free(handle);
703-
R_Free(haio);
704-
return mk_error(xc);
705-
}
620+
(xc = nng_http_client_set_tls(handle->cli, handle->cfg)))
621+
goto exitlevel7;
706622
}
707623

708624
}
@@ -715,6 +631,23 @@ SEXP rnng_ncurl_aio(SEXP http, SEXP method, SEXP headers, SEXP data, SEXP pem) {
715631
UNPROTECT(1);
716632
return aio;
717633

634+
exitlevel7:
635+
nng_tls_config_free(handle->cfg);
636+
exitlevel6:
637+
nng_aio_free(haio->aio);
638+
exitlevel5:
639+
nng_http_res_free(handle->res);
640+
exitlevel4:
641+
nng_http_req_free(handle->req);
642+
exitlevel3:
643+
nng_http_client_free(handle->cli);
644+
exitlevel2:
645+
nng_url_free(handle->url);
646+
exitlevel1:
647+
R_Free(handle);
648+
R_Free(haio);
649+
return mk_error(xc);
650+
718651
}
719652

720653
SEXP rnng_aio_http(SEXP aio) {
@@ -736,8 +669,14 @@ SEXP rnng_aio_http(SEXP aio) {
736669
uint16_t code = nng_http_res_get_status(handle->res);
737670
if (code != 200) {
738671
REprintf("HTTP Server Response: %d %s\n", code, nng_http_res_get_reason(handle->res));
739-
if (code >= 300 && code < 400)
740-
return Rf_mkString(nng_http_res_get_header(handle->res, "Location"));
672+
if (code >= 300 && code < 400) {
673+
SEXP out;
674+
PROTECT(out = Rf_allocVector(VECSXP, 2));
675+
SET_VECTOR_ELT(out, 0, Rf_ScalarInteger(code));
676+
SET_VECTOR_ELT(out, 1, Rf_mkString(nng_http_res_get_header(handle->res, "Location")));
677+
UNPROTECT(1);
678+
return out;
679+
}
741680
}
742681

743682
void *dat;

0 commit comments

Comments
 (0)