rexyai / RestRserve

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

i can't use post #142

Closed longhua8800w closed 4 years ago

longhua8800w commented 4 years ago

i post a simple json {"x":1} , i find the type of request$body is character and when i use response$body = request$body , it return {"x":1} crectly. but when i use fromJson( request$body) to convert it to list. error always happen: {"timestamp":"2020-04-27 12:48:04.066641","level":"ERROR","name":"Application","pid":16448,"msg":"","context":{"request_id":"47b57b44-8842-11ea-bd01-b38daf995dd7","message":{"error":"Argument 'txt' must be a JSON string, URL or file.","call":"NULL","traceback":["FUN(request, response)","x = fromJSON(rq_body)","stop(\"Argument 'txt' must be a JSON string, URL or file.\")","base::stop(..., call. = FALSE)"]}}} this is my postman: image

this is my session: R version 3.6.3 (2020-02-29) Platform: x86_64-w64-mingw32/x64 (64-bit) Running under: Windows 10 x64 (build 19041)

Matrix products: default

locale: [1] LC_COLLATE=Chinese (Simplified)_China.936 LC_CTYPE=Chinese (Simplified)_China.936 LC_MONETARY=Chinese (Simplified)_China.936 [4] LC_NUMERIC=C LC_TIME=Chinese (Simplified)_China.936

attached base packages: [1] stats graphics grDevices utils datasets methods base

other attached packages: [1] forcats_0.5.0 stringr_1.4.0 dplyr_0.8.5 purrr_0.3.3 readr_1.3.1 tidyr_1.0.2 tibble_3.0.0 ggplot2_3.3.0
[9] tidyverse_1.3.0 jsonlite_1.6.1

loaded via a namespace (and not attached): [1] Rcpp_1.0.4 cellranger_1.1.0 pillar_1.4.3 compiler_3.6.3 dbplyr_1.4.2 tools_3.6.3 lubridate_1.7.8 [8] lifecycle_0.2.0 nlme_3.1-145 gtable_0.3.0 lattice_0.20-41 pkgconfig_2.0.3 rlang_0.4.5 reprex_0.3.0
[15] cli_2.0.2 DBI_1.1.0 rstudioapi_0.11 haven_2.2.0 withr_2.1.2 xml2_1.3.2 httr_1.4.1
[22] fs_1.4.1 generics_0.0.2 vctrs_0.2.4 hms_0.5.3 grid_3.6.3 tidyselect_1.0.0 glue_1.4.0
[29] R6_2.4.1 fansi_0.4.1 readxl_1.3.1 modelr_0.1.6 magrittr_1.5 backports_1.1.6 scales_1.1.0
[36] ellipsis_0.3.0 rvest_0.3.5 assertthat_0.2.1 colorspace_1.4-1 utf8_1.1.4 stringi_1.4.6 munsell_0.5.0
[43] broom_0.5.5 crayon_1.3.4

is there a example that i can run a post request successfully? i want use it to corect my code, thanks!

longhua8800w commented 4 years ago

I find that in 0.2.2 request$body is list there is no need to use fromJson. then example "predict-lm" can be post successfully.

dselivanov commented 4 years ago

Yeah, seems we need to check/update examples

hongooi73 commented 4 years ago

Hm, I still have to manually convert a json request body to an R object. Here is my handler and app:

score <- function(request, response)
{
    df <- jsonlite::fromJSON(rawToChar(request$body))
    sc <- predict(bos_rf, df)

    response$set_body(jsonlite::toJSON(sc, auto_unbox=TRUE))
    response$set_content_type("application/json")
}

app <- Application$new(content_type="application/json", middleware=list())
app$add_post(path="/score", FUN=score)

Does the fact that I'm not including any middleware make a difference?

dselivanov commented 4 years ago

@Hong-Revo yes, see here. EncodeDecodeMiddleware which is passed to the Application by default encodes/decodes json and text automatically.

hongooi73 commented 4 years ago

Ta. Interestingly, for my use case it's actually more convenient to omit the middleware and call jsonlite::fromJSON/toJSON myself. This is because I want to pass a data frame to the predict method; the default middleware turns my json input into a list of rows, which is technically correct but rather cumbersome to deal with. Whereas if I do the conversion manually, I can call fromJSON(*, simplifyDataFrame=TRUE) which will automagically return a df.

Not sure if this is worth changing the package over, but something to keep in mind.

dselivanov commented 4 years ago

Such json decoding is intentional. We don't want to make any implicit assumptions about underlying data and convert inherently nested data into flat data frame.

On Tue, Apr 28, 2020 at 12:07 PM Hong Ooi notifications@github.com wrote:

Ta. Interestingly, for my use case it's actually more convenient to omit the middleware and call jsonlite::fromJSON/toJSON myself. This is because I want to pass a data frame to the predict method; the default middleware turns my json input into a list of rows, which is technically correct but rather cumbersome to deal with. Whereas if I do the conversion manually, I can call fromJSON(*, simplifyDataFrame=TRUE) which will automagically return a df.

Not sure if this is worth changing the package over, but something to keep in mind.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/rexyai/RestRserve/issues/142#issuecomment-620449743, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABHC5XLL5IQNZ7FNPA45A2TRO2FFFANCNFSM4MRSXZ6A .

-- Regards Dmitriy Selivanov

hongooi73 commented 4 years ago

No worries, that is what I would expect as well.

dselivanov commented 4 years ago

closing as off topic. Will update documentations as soon as will have spare time.