-
Notifications
You must be signed in to change notification settings - Fork 258
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added support for feather files in POST #77
Changes from all commits
d17249a
44be238
076df64
3bc55ec
98d6f22
d2c04a9
2d7e59e
ebaba94
f115c21
8a1a108
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,21 @@ | ||
postBodyFilter <- function(req){ | ||
body <- req$rook.input$read_lines() | ||
args <- parseBody(body) | ||
|
||
if (!is.null(req$CONTENT_TYPE) && grepl("multipart/form-data; boundary=", | ||
req$CONTENT_TYPE, fixed = TRUE)) { | ||
|
||
boundary <- strsplit(req$CONTENT_TYPE, split = "=")[[1]][2] | ||
body <- req$rook.input$read() | ||
args <- parseMultipart(body, boundary) | ||
} else { | ||
body <- req$rook.input$read_lines() | ||
args <- parseBody(body) | ||
} | ||
req$postBody <- body | ||
req$args <- c(req$args, args) | ||
forward() | ||
} | ||
|
||
|
||
#' @importFrom utils URLdecode | ||
#' @noRd | ||
parseBody <- function(body){ | ||
|
@@ -24,3 +34,33 @@ parseBody <- function(body){ | |
} | ||
ret | ||
} | ||
|
||
|
||
#' @importFrom utils URLdecode | ||
#' @noRd | ||
parseMultipart <- function(body, boundary){ | ||
function(val, req, res, errorHandler){ | ||
tryCatch({ | ||
if (!requireNamespace("webutils", quietly = TRUE)) { | ||
stop("The webutils package is not available but is required in order | ||
to use the functionality to POST binary files", | ||
call. = FALSE) | ||
} | ||
# Is there data in the request? | ||
if (is.null(body) || length(body) == 0 || body == "") { | ||
return(list()) | ||
} | ||
parsed_binary <- webutils::parse_multipart(body, boundary) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are there limits built in to any of these on how big of a file we'd attempt to parse? Anything to prevent a client from sending a 10GB file and running the server out of RAM? |
||
file_name <- parsed_binary$myfile$filename | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm having a hard time finding where |
||
file_data <- parsed_binary$myfile$value | ||
|
||
tmpfile <- tempfile() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hm. It's unfortunate that we're not able to clean up these temp files when we're done. But if we added an |
||
writeBin(file_data, tmpfile) | ||
|
||
ret <- NULL | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this any different than It surprised me that you could assign to a field on a NULL objec.t |
||
ret$name <- file_name | ||
ret$data <- tmpfile | ||
ret | ||
}) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
library(plumber) | ||
library(feather) | ||
|
||
# Illustration of binary uploads and post-processing of the file on receipt. | ||
# As a proof of concept we use a feather file: test.feather | ||
|
||
|
||
# To upload and use the content of the file in a function: | ||
# curl -X POST http://localhost:9080/upload -F 'myfile=@test.feather' | ||
|
||
#* @post /upload | ||
function(name, data) { | ||
# work with binary files after upload | ||
# in this example a feather file | ||
content <- read_feather(data) | ||
return(content) | ||
} | ||
|
||
|
||
# To upload and use the properties of the file in a function: | ||
# curl -X POST http://localhost:9080/inspect -F 'myfile=@test.feather' | ||
|
||
#* @post /inspect | ||
function(name, data) { | ||
file_info <- data.frame( | ||
filename = name, | ||
mtime = file.info(data)$mtime, | ||
ctime = file.info(data)$ctime | ||
) | ||
|
||
return(file_info) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this vulnerable to having an
=
sign in the body of the message?