rexyai / RestRserve

R web API framework for building high-performance microservices and app backends
https://restrserve.org
271 stars 31 forks source link

Preferred way to use RestRserve from client R process #179

Closed kaneplusplus closed 2 years ago

kaneplusplus commented 2 years ago

I'm running into an issue using RestRserve from a client where I'm passing serialized R objects. I'm currently trying to call via httr. Is there another preferred methods? an example is as follows.

From an R session:


library(RestRserve)

edm <- EncodeDecodeMiddleware$new()

edm$ContentHandlers$set_encode(
  "application/rds",
  function(x) {
    serialize(x, NULL)
  }
)

edm$ContentHandlers$set_decode(
  "application/rds",
  function(x) {
    tryCatch(
      res <- unserialize(x),
      error = function(e) {
        raise(HTTPError$bad_request(body = e))
      }
    )
    res
  }
)

s <- Application$new(middleware = list(edm))

s$add_get(
  path = "/echo",
  function(.req, .res) {
    .res$set_body(.req$body)

  }
)

request <- Request$new(path = "/echo", method = "GET",
  body = serialize("hello world", NULL), content_type = "application/rds")

# The following works.
a <- s$process_request(request)$body

backend <- BackendRserve$new()
backend$start(s, port = 8000)

From R session 2:

library(httr)
content(GET(paste("http://localhost:8000", "echo", sep = "/"),
            body = serialize("hello world", NULL),
            encode = "raw", content_type("application/rds"),
            accept("application/rds")))

When I call the code from the second session I get the following error message in R session 1:

WARNING: discarding buffer because too big (awaiting 3544139755222689071 bytes)

And the following message in session 2:

Error in curl::curl_fetch_memory(url, handle = handle) :
  Received HTTP/0.9 when not allowed

I think the server is set up correctly since it services local requests. Is there another preferred way of making request from another process? Any help would be appreciated.

artemklevtsov commented 2 years ago

I could try using a temp file. See example: https://github.com/rexyai/RestRserve/blob/master/inst/examples/plot-ggplot/app.R#L13-L18

artemklevtsov commented 2 years ago

Why are you trying to send the body on a get request?

dselivanov commented 2 years ago

@artemklevtsov but POST also doesn't work. @kaneplusplus Thanks, for reporting. That's look weird. WARNING: discarding buffer because too big (awaiting 3544139755222689071 bytes) - this comes from Rserve backend. I think something is wrong with how httr encodes the body, but not 100% sure. I will investigate.

kaneplusplus commented 2 years ago

@dselivanov Thanks so much for taking a look. If it's better to loop Simon Urbanek in, I can let him know.

@artemklevtsov The structure of the object that I want to pass to the server is a bit more complicated. I was trying to provide a minimal example. It's a good point that it might be better as a POST.

dselivanov commented 2 years ago

@kaneplusplus the answer is easy! you are sending request to 8000 port (why?) which is Rserve binary port, not http server port which is 8080 by default. Try

content(GET(paste("http://localhost:8080", "echo", sep = "/"),
            body = serialize("hello world", NULL),
            encode = "raw", content_type("application/rds"),
            accept("application/rds")))
dselivanov commented 2 years ago

@kaneplusplus when you specify backend$start(s, port = 8000) this is related to Rserve binary port. For http port see http_port argument.

kaneplusplus commented 2 years ago

Ugh. Sorry and thanks very much for pointing this out.

kaneplusplus commented 2 years ago

... Also, thanks very much for the package. I just did a few preliminary tests and it seems to be significantly faster than others.