Skip to content
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

Pass URL encoded string as parameter in path #106

Closed
alexverse opened this issue Jan 9, 2025 · 4 comments · Fixed by #107
Closed

Pass URL encoded string as parameter in path #106

alexverse opened this issue Jan 9, 2025 · 4 comments · Fixed by #107

Comments

@alexverse
Copy link

I want to test an endpoint that accepts URL-encoded file paths ("/hello/:file_path"). However, the app$get() method throws a 404-error.

I'm also sharing a real-world example from the GitLab API, where the file_path parameter is URL encoded.

library(testthat)
library(webfakes)
library(urltools)
library(httr2, warn.conflicts = FALSE)
library(glue)

app <- webfakes::new_app()
app$get("/hello/:file_path", function(req, res) {
  res$send(paste0("Return content of ", req$params$file_path, "!"))
})
web <- webfakes::local_app_process(app)

test_that("can use hello API", {
  url <- web$url("/hello")
  file_path <- urltools::url_encode("path/to/file.json")

  #This works OK
  # file_path <- "foo"
 
  response <- httr2::request(url) %>%
    httr2::req_url_path_append(file_path) %>%
    httr2::req_perform() %>%
    httr2::resp_body_string()
  
  expected_resp <- glue::glue("Return content of {file_path}!")
  expect_equal(response, expected_resp)
})
#> ── Error: can use hello API ────────────────────────────────────────────────────
#> <httr2_http_404/httr2_http/httr2_error/rlang_error/error/condition>
#> Error in `httr2::req_perform(.)`: HTTP 404 Not Found.
#> Backtrace:
#>     ▆
#>  1. ├─... %>% httr2::resp_body_string()
#>  2. ├─httr2::resp_body_string(.)
#>  3. │ └─httr2:::check_response(resp)
#>  4. │   └─httr2:::is_response(resp)
#>  5. └─httr2::req_perform(.)
#>  6.   └─httr2:::handle_resp(req, resp, error_call = error_call)
#>  7.     └─httr2:::resp_abort(resp, req, body, call = error_call)
#>  8.       └─rlang::abort(...)
#> Error:
#> ! Test failed

Created on 2025-01-09 with reprex v2.1.0

@alexverse alexverse changed the title Pass url-encoded encoded string as parameter in URL path Pass URL encoded string as parameter in path Jan 10, 2025
@gaborcsardi
Copy link
Member

It seems like the web server decodes the path in the URL automatically. IDK if this is what web servers are supposed to do, the GitLab web server is not doing it apparently.

This might be ok for the fake api, or might not. E.g. for

/projects/:id/repository/files/:file_path

it is OK, because you can take the rest or the path as file_path. For

GET /projects/:id/repository/files/:file_path/blame

it it not OK, because you won't know if /blame is part of the path or not.

Unfortunately the web server we are using in internally does not give us access to the raw URL, AFAICT. For a fake app you can work around this by checking if the suffix of the path is something that would indicate another API endpoint. (And not using a path that ends with /blame etc. in your tests.)

This is how to match the rest of the path with a regex, btw:

app$get(
  webfakes::new_regexp("^/hello/(?<path>.*)$"),
  function(req, res) {
    res$send(paste0("Return content of ", req$params$path, "!"))
  }
)

@gaborcsardi
Copy link
Member

Actually, it seems like the web server has an option for this, which we could expose. I'll submit a PR in a minute.

@gaborcsardi
Copy link
Member

PR here: #107

@alexverse
Copy link
Author

alexverse commented Jan 10, 2025

Looks great! 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants