Closed jonovik closed 5 years ago
I think I have a solution.
Calling httr::POST(api_url, ..., query = args)
does indeed put query
into the resulting full url. This is mentioned in ?httr::POST:
... Further named parameters, such as query, path, etc, passed on to modify_url(). Unnamed parameters will be combined with config().
The call signature of httr::POST()
is
function(url = NULL, config = list(), ..., body = NULL, encode = c("multipart", "form", "json", "raw"), handle = NULL)
Because query
is not among the named arguments here, it ends up in ...
and thus gets passed to modify_url
when the current create_wpage code calls canvas_query
.
Somewhat counterintuitively, we can pass all the wiki_data[...]
information in the body
argument to httr::POST
.
The following works:
library(tidyverse)
library(rcanvas)
# Based on rcanvas::create_wpage
my_create_wpage <- function(course_id, title, body, editing_roles = "teachers", published = FALSE){
# POST /api/v1/courses/:course_id/pages
# wiki_page[notify_of_update] boolean Whether participants should be notified when this page changes.
# wiki_page[front_page] boolean Set an unhidden page as the front page (if true)
url <- paste0(rcanvas:::canvas_url(), file.path("courses", course_id, "pages"))
args <- rcanvas:::sc(list(`wiki_page[title]` = title,
`wiki_page[body]` = body,
`wiki_page[editing_roles]` = editing_roles,
`wiki_page[notify_of_update]` = FALSE,
`wiki_page[published]` = published,
`wiki_page[front_page]` = FALSE
))
# resp <- httr::POST(url = url,
# httr::user_agent("rcanvas - https://github.com/daranzolin/rcanvas"),
# httr::add_headers(Authorization = paste("Bearer", rcanvas:::check_token())),
# body = args)
resp <- httr::POST(url,
httr::user_agent("rcanvas - https://github.com/daranzolin/rcanvas"),
httr::add_headers(Authorization = paste("Bearer", rcanvas:::check_token())),
body = args)
httr::stop_for_status(resp)
message(sprintf("Page '%s' created", title))
return(resp)
}
body_size <- 9000
course_id <- get_course_list() %>% filter(name %>% str_detect("COURSE_NAME")) %>% pull(id)
title <- "Test Request-URI Too Long"
body <- paste(rep("x", body_size), collapse = "")
my_create_wpage(course_id, title, body)
A reasonably clean fix might be to modify canvas_query
to pass args
as body
if the method is POST.
create_wpage()
with more than about 8000 characters inwiki_page[body]
fails withRequest-URI Too Long (HTTP 414)
.Usually, this error code means we used GET when we meant POST, but
rcanvas::create_wpage
usesrcanvas:::canvas_query(type = "POST")
which in turn useshttr::POST
, which I would expect to do the right thing.As specified by the Canvas Live API
(scroll down to Pages and look for
POST /v1/courses/{course_id}/pages
),canvas_query
does not use thebody=
argument tohttr::POST
; instead, the page body is passed aswiki_page[body]
.Here's a small reproducible example illustrating the issue; it would be interesting to test on other people's Canvases. With a
wiki_page[body]
of 4 characters it works fine, and with 9000 characters (over the usual limit of 8192 bytes) it causes a HTTP 414 error. Curiously, it runs without error in the Live API for my university's Canvas site, creating the page as expected.This succeeds if
body_size = 4
. We can see that the response object has a long url that contains thewiki_page[body]
. (This is also the case when I test using the Live API.)But it fails if
body_size = 9000
: