Skip to content

Commit 05079c3

Browse files
committed
support returning strings for cross-client compatibility
1 parent b39b6d3 commit 05079c3

File tree

4 files changed

+99
-54
lines changed

4 files changed

+99
-54
lines changed

R/ncurl.R

-43
Original file line numberDiff line numberDiff line change
@@ -272,46 +272,3 @@ as.promise.ncurlAio <- function(x) {
272272
#' @exportS3Method promises::is.promising
273273
#'
274274
is.promising.ncurlAio <- function(x) TRUE
275-
276-
#' Start REST Server
277-
#'
278-
#' Creates an instance of an HTTP REST server which evaluates R expressions sent
279-
#' to it [EXPERIMENTAL]. As arbitrary R expressions are evaluated, this
280-
#' should only be deployed on the local machine (using the 127.0.0.1
281-
#' loopback address) in a trusted environment.
282-
#'
283-
#' @param url full http address including hostname, port and path at which to
284-
#' host the server.
285-
#'
286-
#' @details Query the API with an HTTP client using the \sQuote{POST} method,
287-
#' with the request data being the R expression as a text string. The
288-
#' received response body will consist of the serialized evaluation result.
289-
#' Unserialize to return an R object.
290-
#'
291-
#' Use only in a new session. Use \sQuote{ctrl + \\} to forcibly quit
292-
#' when finished as the function blocks with no means of interruption.
293-
#'
294-
#' Currently still experimental as the server lacks error handling. Sending
295-
#' an invalid R expression will cause the server to exit.
296-
#'
297-
#' @return This function never returns.
298-
#'
299-
#' @examples
300-
#' if (interactive()) {
301-
#'
302-
#' # run in a new session:
303-
#' # nanonext::server()
304-
#'
305-
#' res <- ncurl("http://127.0.0.1:5555/api/rest",
306-
#' convert = FALSE,
307-
#' method = "POST",
308-
#' data = "Sys.time()")
309-
#'
310-
#' if (!is_error_value(res$data)) unserialize(res$data)
311-
#'
312-
#' }
313-
#'
314-
#' @export
315-
#'
316-
server <- function(url = "http://127.0.0.1:5555/api/rest")
317-
.Call(rnng_rest_server, url)

R/server.R

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Copyright (C) 2022-2024 Hibiki AI Limited <info@hibiki-ai.com>
2+
#
3+
# This file is part of nanonext.
4+
#
5+
# nanonext is free software: you can redistribute it and/or modify it under the
6+
# terms of the GNU General Public License as published by the Free Software
7+
# Foundation, either version 3 of the License, or (at your option) any later
8+
# version.
9+
#
10+
# nanonext is distributed in the hope that it will be useful, but WITHOUT ANY
11+
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12+
# A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13+
#
14+
# You should have received a copy of the GNU General Public License along with
15+
# nanonext. If not, see <https://www.gnu.org/licenses/>.
16+
17+
# nanonext - server - HTTP REST Server -----------------------------------------
18+
19+
#' Start REST Server
20+
#'
21+
#' Creates an instance of an HTTP REST server which evaluates R expressions sent
22+
#' to it [EXPERIMENTAL]. As arbitrary R expressions are evaluated, this
23+
#' should only be deployed on the local machine (using the 127.0.0.1
24+
#' loopback address) in a trusted environment.
25+
#'
26+
#' @param url full http address including hostname, port and path at which to
27+
#' host the server.
28+
#'
29+
#' @details Query the API with an HTTP client using the \sQuote{POST} method,
30+
#' with the request data being the R expression as a text string. The
31+
#' received response body will consist of the evaluation result as a text
32+
#' string (if of the appropriate type), or otherwise a serialized R object,
33+
#' which should be passed to \code{\link{unserialize}}.
34+
#'
35+
#' Use only in a new session. Use \sQuote{ctrl + \\} to forcibly quit
36+
#' when finished as the function blocks with no means of interruption.
37+
#'
38+
#' Currently still experimental as the server lacks error handling. Sending
39+
#' an invalid R expression will cause the server to quit.
40+
#'
41+
#' @return This function never returns.
42+
#'
43+
#' @examples
44+
#' if (interactive()) {
45+
#'
46+
#' # run server in a new session:
47+
#' # Rscript -e 'nanonext::server()'
48+
#'
49+
#' # query using curl:
50+
#' # curl -X POST http://127.0.0.1:5555/api/rest -d 'format(Sys.time())'
51+
#'
52+
#' ncurl(
53+
#' "http://127.0.0.1:5555/api/rest",
54+
#' method = "POST",
55+
#' data = "format(Sys.time())"
56+
#' )
57+
#'
58+
#' res <- ncurl(
59+
#' "http://127.0.0.1:5555/api/rest",
60+
#' convert = FALSE,
61+
#' method = "POST",
62+
#' data = "data.frame(random = nanonext::random(3))"
63+
#' )
64+
#' if (!is_error_value(res$data)) unserialize(res$data)
65+
#'
66+
#' }
67+
#'
68+
#' @export
69+
#'
70+
server <- function(url = "http://127.0.0.1:5555/api/rest")
71+
.Call(rnng_rest_server, url)

man/server.Rd

+21-10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/server.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -253,7 +253,13 @@ void inproc_server(const char* url) {
253253
const char *body = nng_msg_body(msg);
254254
nano_buf buf;
255255
SEXP res = R_ParseEvalString(body, R_GlobalEnv);
256-
nano_serialize(&buf, res, R_NilValue);
256+
if (TYPEOF(res) == STRSXP) {
257+
const char *string = NANO_STRING(res);
258+
buf.buf = (unsigned char *) string;
259+
buf.cur = strlen(string);
260+
} else {
261+
nano_serialize(&buf, res, R_NilValue);
262+
}
257263
nng_msg_clear(msg);
258264
nng_msg_append(msg, buf.buf, buf.cur);
259265
if ((xc = nng_sendmsg(s, msg, 0)))

0 commit comments

Comments
 (0)