Compare commits
No commits in common. 'master' and 'batman' have entirely different histories.
25 changed files with 0 additions and 1024 deletions
@ -1,26 +0,0 @@ |
|||||
^.vscode$ |
|
||||
^.*\.Rproj$ |
|
||||
^\.Rproj\.user$ |
|
||||
^\.travis\.yml$ |
|
||||
^README\.*Rmd$ |
|
||||
^README\.*html$ |
|
||||
^NOTES\.*Rmd$ |
|
||||
^NOTES\.*html$ |
|
||||
^\.codecov\.yml$ |
|
||||
^README_files$ |
|
||||
^doc$ |
|
||||
^docs$ |
|
||||
^tmp$ |
|
||||
^notes$ |
|
||||
^CONDUCT.*$ |
|
||||
^CODE.*$ |
|
||||
^\.gitlab-ci\.yml$ |
|
||||
^\.vscode$ |
|
||||
^CRAN-RELEASE$ |
|
||||
^appveyor\.yml$ |
|
||||
^tools$ |
|
||||
^LICENSE\.md$ |
|
||||
^bld$ |
|
||||
^node_modules^ |
|
||||
^package-lock\.json$ |
|
||||
^\.github$ |
|
@ -1 +0,0 @@ |
|||||
comment: false |
|
@ -1,26 +0,0 @@ |
|||||
# For help debugging build failures open an issue on the RStudio community with the 'github-actions' tag. |
|
||||
# https://community.rstudio.com/new-topic?category=Package%20development&tags=github-actions |
|
||||
on: |
|
||||
push: |
|
||||
branches: |
|
||||
- batman |
|
||||
pull_request: |
|
||||
branches: |
|
||||
- batmsn |
|
||||
|
|
||||
name: R-CMD-check |
|
||||
|
|
||||
jobs: |
|
||||
R-CMD-check: |
|
||||
runs-on: macOS-latest |
|
||||
steps: |
|
||||
- uses: actions/checkout@v2 |
|
||||
- uses: r-lib/actions/setup-r@master |
|
||||
- name: Install dependencies |
|
||||
run: | |
|
||||
install.packages(c("remotes", "rcmdcheck")) |
|
||||
remotes::install_deps(dependencies = TRUE) |
|
||||
shell: Rscript {0} |
|
||||
- name: Check |
|
||||
run: rcmdcheck::rcmdcheck(args = "--no-manual", error_on = "error") |
|
||||
shell: Rscript {0} |
|
@ -1,9 +0,0 @@ |
|||||
.DS_Store |
|
||||
.Rproj.user |
|
||||
.Rhistory |
|
||||
.RData |
|
||||
.Rproj |
|
||||
README_cache |
|
||||
src/*.o |
|
||||
src/*.so |
|
||||
src/*.dll |
|
@ -1,12 +0,0 @@ |
|||||
language: R |
|
||||
sudo: false |
|
||||
cache: packages |
|
||||
|
|
||||
before_install: |
|
||||
- echo "options(repos = c(CRAN = 'https://packagemanager.rstudio.com/all/__linux__/xenial/latest'))" >> ~/.Rprofile.site |
|
||||
- echo "options(HTTPUserAgent = paste0('R/', getRversion(), ' R (', |
|
||||
paste(getRversion(), R.version['platform'], R.version['arch'], R.version['os']), |
|
||||
')'))" >> ~/.Rprofile.site |
|
||||
|
|
||||
after_success: |
|
||||
- Rscript -e 'covr::codecov()' |
|
@ -1,25 +0,0 @@ |
|||||
# Contributor Code of Conduct |
|
||||
|
|
||||
As contributors and maintainers of this project, we pledge to respect all people who |
|
||||
contribute through reporting issues, posting feature requests, updating documentation, |
|
||||
submitting pull requests or patches, and other activities. |
|
||||
|
|
||||
We are committed to making participation in this project a harassment-free experience for |
|
||||
everyone, regardless of level of experience, gender, gender identity and expression, |
|
||||
sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. |
|
||||
|
|
||||
Examples of unacceptable behavior by participants include the use of sexual language or |
|
||||
imagery, derogatory comments or personal attacks, trolling, public or private harassment, |
|
||||
insults, or other unprofessional conduct. |
|
||||
|
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, |
|
||||
commits, code, wiki edits, issues, and other contributions that are not aligned to this |
|
||||
Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed |
|
||||
from the project team. |
|
||||
|
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by |
|
||||
opening an issue or contacting one or more of the project maintainers. |
|
||||
|
|
||||
This Code of Conduct is adapted from the Contributor Covenant |
|
||||
(http:contributor-covenant.org), version 1.0.0, available at |
|
||||
http://contributor-covenant.org/version/1/0/0/ |
|
@ -1,30 +0,0 @@ |
|||||
Package: httr2curl |
|
||||
Type: Package |
|
||||
Title: Turn 'httr' Web Requests Into 'curl' Command Line Calls |
|
||||
Version: 0.1.0 |
|
||||
Date: 2021-01-27 |
|
||||
Authors@R: c( |
|
||||
person("Bob", "Rudis", email = "bob@rud.is", role = c("aut", "cre"), |
|
||||
comment = c(ORCID = "0000-0001-5670-2640")) |
|
||||
) |
|
||||
Maintainer: Bob Rudis <bob@rud.is> |
|
||||
Description: When provided with an 'httr' "VERB" call, the request will be made |
|
||||
and 'libcurl' headers will be captured and post-processed to provide a working |
|
||||
'curl' command line call. |
|
||||
URL: https://git.rud.is/hrbrmstr/httr2curl |
|
||||
BugReports: https://git.rud.is/hrbrmstr/httr2curl/issues |
|
||||
Encoding: UTF-8 |
|
||||
License: MIT + file LICENSE |
|
||||
SystemRequirements: perl |
|
||||
Suggests: |
|
||||
covr, tinytest |
|
||||
Depends: |
|
||||
R (>= 3.6.0) |
|
||||
Imports: |
|
||||
httr, |
|
||||
processx, |
|
||||
rvest, |
|
||||
xml2, |
|
||||
magrittr |
|
||||
Roxygen: list(markdown = TRUE) |
|
||||
RoxygenNote: 7.1.1 |
|
@ -1,2 +0,0 @@ |
|||||
YEAR: 2021 |
|
||||
COPYRIGHT HOLDER: Bob Rudis |
|
@ -1,21 +0,0 @@ |
|||||
# MIT License |
|
||||
|
|
||||
Copyright (c) 2021 Bob Rudis |
|
||||
|
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|
||||
of this software and associated documentation files (the "Software"), to deal |
|
||||
in the Software without restriction, including without limitation the rights |
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
||||
copies of the Software, and to permit persons to whom the Software is |
|
||||
furnished to do so, subject to the following conditions: |
|
||||
|
|
||||
The above copyright notice and this permission notice shall be included in all |
|
||||
copies or substantial portions of the Software. |
|
||||
|
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
||||
SOFTWARE. |
|
@ -1,9 +0,0 @@ |
|||||
# Generated by roxygen2: do not edit by hand |
|
||||
|
|
||||
export("%>%") |
|
||||
export(h2c) |
|
||||
import(httr) |
|
||||
import(processx) |
|
||||
import(rvest) |
|
||||
import(xml2) |
|
||||
importFrom(magrittr,"%>%") |
|
@ -1,2 +0,0 @@ |
|||||
0.1.0 |
|
||||
* Initial release |
|
@ -1,68 +0,0 @@ |
|||||
#' Convert an 'httr' call to 'curl' command line |
|
||||
#' |
|
||||
#' @param complete_httr_verb_call wrap an `httr` `VERB` call with this function |
|
||||
#' and it will return the text of a working `curl` command line |
|
||||
#' @param use_web_service if `TRUE` (`FALSE` by default) this function will use |
|
||||
#' `https://curl.se/h2c/` to process the headers. |
|
||||
#' @export |
|
||||
#' @examples \dontrun{ |
|
||||
#' h2c( |
|
||||
#' httr::GET( |
|
||||
#' url = "https://rud.is/", |
|
||||
#' httr::user_agent(splashr::ua_apple_tv), |
|
||||
#' query = list( |
|
||||
#' a = "b", |
|
||||
#' c = 1 |
|
||||
#' ) |
|
||||
#' ) |
|
||||
#' ) |
|
||||
#' } |
|
||||
h2c <- function(complete_httr_verb_call, use_web_service = FALSE) { |
|
||||
|
|
||||
ƒ_call <- substitute(complete_httr_verb_call) |
|
||||
|
|
||||
capture.output( |
|
||||
capture.output( |
|
||||
httr::with_verbose( |
|
||||
eval(ƒ_call) |
|
||||
), type = "message") -> res |
|
||||
) -> junk |
|
||||
|
|
||||
out <- tempfile() |
|
||||
|
|
||||
res[grepl("^->", res)] %>% |
|
||||
sub("^-> ", "", .) %>% |
|
||||
paste0(collapse = "\n") -> res |
|
||||
|
|
||||
if (use_web_service) { |
|
||||
|
|
||||
httr::POST( |
|
||||
url = "https://curl.se/h2c/", |
|
||||
httr::user_agent("curl/7.64.1"), |
|
||||
httr::accept("*/*"), |
|
||||
httr::content_type("application/x-www-form-urlencoded"), |
|
||||
body = sprintf("http=%s", curl::curl_escape(res)), |
|
||||
encode = "raw" |
|
||||
) -> res1 |
|
||||
|
|
||||
trimws(rawToChar(res1$content)) |
|
||||
|
|
||||
} else { |
|
||||
|
|
||||
writeLines(res, out) |
|
||||
|
|
||||
perl <- find_perl() |
|
||||
|
|
||||
args <- system.file("bin", "h2c.pl", package = "httr2curl") |
|
||||
|
|
||||
processx::run( |
|
||||
command = perl, |
|
||||
args = args, |
|
||||
stdin = out |
|
||||
) -> res |
|
||||
|
|
||||
trimws(res$stdout) |
|
||||
|
|
||||
} |
|
||||
|
|
||||
} |
|
@ -1,12 +0,0 @@ |
|||||
#' Turn 'httr' Web Requests Into 'curl' Command Line Calls |
|
||||
#' |
|
||||
#' When provided with an 'httr' "VERB" call, the request will be made |
|
||||
#' and 'libcurl' headers will be captured and post-processed to provide a working |
|
||||
#' 'curl' command line call. |
|
||||
#' |
|
||||
#' @md |
|
||||
#' @name httr2curl |
|
||||
#' @keywords internal |
|
||||
#' @author Bob Rudis (bob@@rud.is) |
|
||||
#' @import httr processx rvest xml2 |
|
||||
"_PACKAGE" |
|
@ -1,11 +0,0 @@ |
|||||
#' Pipe operator |
|
||||
#' |
|
||||
#' See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. |
|
||||
#' |
|
||||
#' @name %>% |
|
||||
#' @rdname pipe |
|
||||
#' @keywords internal |
|
||||
#' @export |
|
||||
#' @importFrom magrittr %>% |
|
||||
#' @usage lhs \%>\% rhs |
|
||||
NULL |
|
@ -1,14 +0,0 @@ |
|||||
find_perl <- function() { |
|
||||
|
|
||||
perl <- Sys.which("perl") |
|
||||
|
|
||||
if (perl == "") { |
|
||||
stop( |
|
||||
"Cannot find 'perl'. httr2curl requires perl to be installed and on the PATH.", |
|
||||
call. = FALSE |
|
||||
) |
|
||||
} |
|
||||
|
|
||||
return(perl) |
|
||||
|
|
||||
} |
|
@ -1,83 +0,0 @@ |
|||||
--- |
|
||||
output: rmarkdown::github_document |
|
||||
editor_options: |
|
||||
chunk_output_type: console |
|
||||
--- |
|
||||
|
|
||||
```{r pkg-knitr-opts, include=FALSE} |
|
||||
hrbrpkghelpr::global_opts() |
|
||||
``` |
|
||||
|
|
||||
```{r badges, results='asis', echo=FALSE, cache=FALSE} |
|
||||
hrbrpkghelpr::stinking_badges() |
|
||||
``` |
|
||||
|
|
||||
```{r description, results='asis', echo=FALSE, cache=FALSE} |
|
||||
hrbrpkghelpr::yank_title_and_description() |
|
||||
``` |
|
||||
|
|
||||
## What's Inside The Tin |
|
||||
|
|
||||
The following functions are implemented: |
|
||||
|
|
||||
```{r ingredients, results='asis', echo=FALSE, cache=FALSE} |
|
||||
hrbrpkghelpr::describe_ingredients() |
|
||||
``` |
|
||||
|
|
||||
## Installation |
|
||||
|
|
||||
```{r install-ex, results='asis', echo=FALSE, cache=FALSE} |
|
||||
hrbrpkghelpr::install_block() |
|
||||
``` |
|
||||
|
|
||||
## Usage |
|
||||
|
|
||||
```{r lib-ex} |
|
||||
library(httr2curl) |
|
||||
|
|
||||
# current version |
|
||||
packageVersion("httr2curl") |
|
||||
``` |
|
||||
|
|
||||
### Using local perl |
|
||||
|
|
||||
```{r ex01} |
|
||||
h2c( |
|
||||
httr::GET( |
|
||||
url = "https://rud.is/", |
|
||||
httr::user_agent(splashr::ua_apple_tv), |
|
||||
query = list( |
|
||||
a = "b", |
|
||||
c = 1 |
|
||||
) |
|
||||
) |
|
||||
) |
|
||||
``` |
|
||||
|
|
||||
### Using the web service |
|
||||
|
|
||||
```{r ex02} |
|
||||
h2c( |
|
||||
httr::GET( |
|
||||
url = "https://rud.is/", |
|
||||
httr::user_agent(splashr::ua_apple_tv), |
|
||||
query = list( |
|
||||
a = "b", |
|
||||
c = 1 |
|
||||
) |
|
||||
), |
|
||||
use_web_service = TRUE |
|
||||
) |
|
||||
``` |
|
||||
|
|
||||
## httr2curl Metrics |
|
||||
|
|
||||
```{r cloc, echo=FALSE} |
|
||||
cloc::cloc_pkg_md() |
|
||||
``` |
|
||||
|
|
||||
## Code of Conduct |
|
||||
|
|
||||
Please note that this project is released with a Contributor Code of |
|
||||
Conduct. By participating in this project you agree to abide by its |
|
||||
terms. |
|
@ -1,52 +0,0 @@ |
|||||
# DO NOT CHANGE the "init" and "install" sections below |
|
||||
|
|
||||
# Download script file from GitHub |
|
||||
init: |
|
||||
ps: | |
|
||||
= "Stop" |
|
||||
Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1" |
|
||||
Import-Module '..\appveyor-tool.ps1' |
|
||||
|
|
||||
install: |
|
||||
ps: Bootstrap |
|
||||
|
|
||||
cache: |
|
||||
- C:\RLibrary |
|
||||
|
|
||||
environment: |
|
||||
NOT_CRAN: true |
|
||||
# env vars that may need to be set, at least temporarily, from time to time |
|
||||
# see https://github.com/krlmlr/r-appveyor#readme for details |
|
||||
# USE_RTOOLS: true |
|
||||
# R_REMOTES_STANDALONE: true |
|
||||
|
|
||||
# Adapt as necessary starting from here |
|
||||
|
|
||||
build_script: |
|
||||
- travis-tool.sh install_deps |
|
||||
|
|
||||
test_script: |
|
||||
- travis-tool.sh run_tests |
|
||||
|
|
||||
on_failure: |
|
||||
- 7z a failure.zip *.Rcheck\* |
|
||||
- appveyor PushArtifact failure.zip |
|
||||
|
|
||||
artifacts: |
|
||||
- path: '*.Rcheck\**\*.log' |
|
||||
name: Logs |
|
||||
|
|
||||
- path: '*.Rcheck\**\*.out' |
|
||||
name: Logs |
|
||||
|
|
||||
- path: '*.Rcheck\**\*.fail' |
|
||||
name: Logs |
|
||||
|
|
||||
- path: '*.Rcheck\**\*.Rout' |
|
||||
name: Logs |
|
||||
|
|
||||
- path: '\*_*.tar.gz' |
|
||||
name: Bits |
|
||||
|
|
||||
- path: '\*_*.zip' |
|
||||
name: Bits |
|
@ -1,21 +0,0 @@ |
|||||
Version: 1.0 |
|
||||
|
|
||||
RestoreWorkspace: Default |
|
||||
SaveWorkspace: Default |
|
||||
AlwaysSaveHistory: Default |
|
||||
|
|
||||
EnableCodeIndexing: Yes |
|
||||
UseSpacesForTab: Yes |
|
||||
NumSpacesForTab: 2 |
|
||||
Encoding: UTF-8 |
|
||||
|
|
||||
RnwWeave: Sweave |
|
||||
LaTeX: pdfLaTeX |
|
||||
|
|
||||
StripTrailingWhitespace: Yes |
|
||||
|
|
||||
BuildType: Package |
|
||||
PackageUseDevtools: Yes |
|
||||
PackageInstallArgs: --no-multiarch --with-keep.source |
|
||||
PackageBuildArgs: --resave-data |
|
||||
PackageRoxygenize: rd,collate,namespace |
|
@ -1,426 +0,0 @@ |
|||||
#!/usr/bin/perl |
|
||||
|
|
||||
use MIME::Base64; |
|
||||
|
|
||||
sub usage { |
|
||||
print "h2c.pl [options] < file \n", |
|
||||
" -a Allow curl's default headers\n", |
|
||||
" -d Output man page HTML links after command line\n", |
|
||||
" -h Show short help\n", |
|
||||
" -H Output HTTP generated URLs instead\n", |
|
||||
" -i Ignore HTTP version\n", |
|
||||
" --libcurl Output libcurl code instead\n", |
|
||||
" -n Output notes after command line\n", |
|
||||
" -s Use short command line options\n", |
|
||||
" -v Add a verbose option to the command line\n"; |
|
||||
exit; |
|
||||
} |
|
||||
|
|
||||
sub manpage { |
|
||||
my ($p, $n, $desc) = @_; |
|
||||
if(!$n) { |
|
||||
$n = $p; |
|
||||
} |
|
||||
return sprintf("%s;%s;$desc", $p, $n); |
|
||||
} |
|
||||
|
|
||||
my $usesamehttpversion = 1; |
|
||||
my $disableheadersnotseen = 1; |
|
||||
my $shellcompatible = 1; # may not been windows command prompt compat |
|
||||
my $uselongoptions = 1; # instead of short |
|
||||
my $uselibcurl = 0; # --libcurl |
|
||||
my $usehttp = 0; |
|
||||
|
|
||||
while($ARGV[0]) { |
|
||||
if(($ARGV[0] eq "-h") || ($ARGV[0] eq "--help")) { |
|
||||
usage(); |
|
||||
} |
|
||||
elsif($ARGV[0] eq "-a") { |
|
||||
$disableheadersnotseen = 0; |
|
||||
shift @ARGV; |
|
||||
} |
|
||||
elsif($ARGV[0] eq "-d") { |
|
||||
$usedocs = 1; |
|
||||
shift @ARGV; |
|
||||
} |
|
||||
elsif($ARGV[0] eq "-H") { |
|
||||
$usehttp = 1; |
|
||||
shift @ARGV; |
|
||||
} |
|
||||
elsif($ARGV[0] eq "-i") { |
|
||||
$usesamehttpversion = 0; |
|
||||
shift @ARGV; |
|
||||
} |
|
||||
elsif($ARGV[0] eq "--libcurl") { |
|
||||
$uselibcurl = 1; |
|
||||
shift @ARGV; |
|
||||
} |
|
||||
elsif($ARGV[0] eq "-n") { |
|
||||
$usenotes = 1; |
|
||||
shift @ARGV; |
|
||||
} |
|
||||
elsif($ARGV[0] eq "-s") { |
|
||||
$uselongoptions = 0; |
|
||||
shift @ARGV; |
|
||||
} |
|
||||
elsif($ARGV[0] eq "-v") { |
|
||||
$useverbose = 1; |
|
||||
shift @ARGV; |
|
||||
} |
|
||||
else { |
|
||||
usage(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
|
|
||||
my $state; # 0 is request-line, 1-headers, 2-body |
|
||||
my $line = 1; |
|
||||
while(<STDIN>) { |
|
||||
my $l = $_; |
|
||||
# discard CRs completely |
|
||||
$l =~ s/\r//g; |
|
||||
if(!$state) { |
|
||||
chomp $l; |
|
||||
if($l =~ /([^ ]*) +(.*) +(HTTP\/.*)/) { |
|
||||
$method = $1; |
|
||||
$path = $2; |
|
||||
$http = $3; |
|
||||
} |
|
||||
else { |
|
||||
$error="bad request-line"; |
|
||||
last; |
|
||||
} |
|
||||
$state++; |
|
||||
} |
|
||||
elsif(1 == $state) { |
|
||||
chomp $l; |
|
||||
if($l =~ /([^:]*): *(.*)/) { |
|
||||
$header{lc($1)}=$2; |
|
||||
$exactcase{lc($1)}=$1; # to allow us to use it as read |
|
||||
} |
|
||||
elsif(length($l)<2) { |
|
||||
# body time |
|
||||
$state++; |
|
||||
} |
|
||||
else { |
|
||||
$error="illegal HTTP header on line $line"; |
|
||||
last; |
|
||||
} |
|
||||
} |
|
||||
elsif(2 == $state) { |
|
||||
push @body, $l; |
|
||||
} |
|
||||
$line++; |
|
||||
} |
|
||||
|
|
||||
if(!$header{'host'}) { |
|
||||
$error = "No Host: header makes it impossible to tell URL\n"; |
|
||||
} |
|
||||
|
|
||||
error: |
|
||||
if($error) { |
|
||||
print "Error: $error\n"; |
|
||||
exit; |
|
||||
} |
|
||||
|
|
||||
if($uselongoptions) { |
|
||||
$opt_data = "--data"; |
|
||||
$opt_request = "--request"; |
|
||||
$opt_head = "--head"; |
|
||||
$opt_header = "--header"; |
|
||||
$opt_user_agent = "--user-agent"; |
|
||||
$opt_cookie = "--cookie"; |
|
||||
$opt_verbose = "--verbose"; |
|
||||
$opt_form = "--form"; |
|
||||
$opt_user = "--user"; |
|
||||
} |
|
||||
else { |
|
||||
$opt_data = "-d"; |
|
||||
$opt_request = "-X"; |
|
||||
$opt_head = "-I"; |
|
||||
$opt_header = "-H"; |
|
||||
$opt_user_agent = "-A"; |
|
||||
$opt_cookie = "-b"; |
|
||||
$opt_verbose = "-v"; |
|
||||
$opt_form = "-F"; |
|
||||
$opt_user = "-u"; |
|
||||
} |
|
||||
|
|
||||
my $httpver=""; |
|
||||
my $disabledheaders=""; |
|
||||
my $addedheaders=""; |
|
||||
|
|
||||
if($header{"content-type"} =~ /^multipart\/form-data;/) { |
|
||||
# multipart formpost, this is special |
|
||||
my $type = $header{"content-type"}; |
|
||||
my $boundary = $type; |
|
||||
$boundary =~ s/.*boundary=(.*)/$1/; |
|
||||
my $inbound = $body[0]; |
|
||||
chomp $inbound; |
|
||||
# a body MUST start with dash-dash-boundary |
|
||||
if("--$boundary" ne $inbound) { |
|
||||
$error = "unexpected multipart format"; |
|
||||
goto error; |
|
||||
} |
|
||||
my $bline=1; |
|
||||
|
|
||||
my %fheader; |
|
||||
my $fstate = 0; |
|
||||
my @fbody; |
|
||||
while($body[$bline]) { |
|
||||
my $l = $body[$bline]; |
|
||||
if(0 == $fstate) { |
|
||||
# headers |
|
||||
chomp $l; |
|
||||
if($l =~ /([^:]*): *(.*)/) { |
|
||||
$fheader{lc($1)}=$2; |
|
||||
} |
|
||||
elsif(length($l)<2) { |
|
||||
# body time |
|
||||
$fstate++; |
|
||||
} |
|
||||
} |
|
||||
elsif($fstate) { |
|
||||
if($l =~ /^--$boundary/) { |
|
||||
# end of this part |
|
||||
my $cd = $fheader{'content-disposition'}; |
|
||||
if(!$cd) { |
|
||||
$error = "multi-part without Content-Disposition: header!"; |
|
||||
goto error; |
|
||||
} |
|
||||
# Content-Disposition: form-data; name="name" |
|
||||
# Content-Disposition: form-data; name="file"; filename="README.md" |
|
||||
if($cd =~ /^form-data; name=([^;]*)[;]? *(.*)/i) { |
|
||||
my ($n, $f)=($1, $2); |
|
||||
# name is with or without quotes |
|
||||
$n =~ s/\"//g; |
|
||||
if($f =~ /^filename=(.*)/) { |
|
||||
# filename is with or without quotes |
|
||||
$f = $1; |
|
||||
$f =~ s/\"//g; |
|
||||
} |
|
||||
if(!$multipart) { |
|
||||
push @docs, manpage("-F", $opt_form, "send a multipart formpost"); |
|
||||
} |
|
||||
if(!$f) { |
|
||||
my $fbody = join("", @fbody); |
|
||||
$fbody =~ s/[ \n\r]+\z//g; |
|
||||
$fbody =~ s/([\\\$\"\'\`])/\\$1/g; |
|
||||
$multipart .= "$opt_form $n=\"$fbody\" "; |
|
||||
@fbody=""; |
|
||||
} |
|
||||
else { |
|
||||
# file name was present |
|
||||
$multipart .= "$opt_form $n=\@$f "; |
|
||||
} |
|
||||
} |
|
||||
$fstate = 0; |
|
||||
%fheader = 0; |
|
||||
$bline++; |
|
||||
next; |
|
||||
} |
|
||||
push @fbody, $l; |
|
||||
} |
|
||||
$bline++; |
|
||||
} |
|
||||
if($body[$bline-1] !~ /^--$boundary--/) { |
|
||||
print STDERR "bad last line?"; |
|
||||
} |
|
||||
|
|
||||
$header{"content-type"} = ""; # blank it |
|
||||
$do_multipart = 1; |
|
||||
|
|
||||
} |
|
||||
elsif(length(join("", @body))) { |
|
||||
# TODO: escape the body |
|
||||
my $esc = join("", @body); |
|
||||
chomp $esc; # trim the final newline |
|
||||
if($shellcompatible) { |
|
||||
$esc =~ s/\n/ /g; # turn newlines into space! |
|
||||
$esc =~ s/\"/\\"/g; # escape double quotes |
|
||||
if(!$unixescaped) { |
|
||||
push @notes, "uses quotes suitable for *nix command lines"; |
|
||||
$unixescaped++; |
|
||||
} |
|
||||
} |
|
||||
$usebody= sprintf("--data-binary \"%s\" ", $esc); |
|
||||
push @docs, manpage("--data-binary", "", "send this string as a body with POST"); |
|
||||
} |
|
||||
if(uc($method) eq "HEAD") { |
|
||||
$usemethod = "$opt_head "; |
|
||||
push @docs, manpage("-I", $opt_head, "send a HEAD request"); |
|
||||
} |
|
||||
elsif(uc($method) eq "POST") { |
|
||||
if(!$usebody && !$do_multipart) { |
|
||||
$usebody= sprintf("$opt_data \"\" "); |
|
||||
push @docs, manpage("-d", $opt_data, "send this string as a body with POST"); |
|
||||
} |
|
||||
} |
|
||||
elsif(uc($method) eq "PUT") { |
|
||||
if(!$usebody) { |
|
||||
$usebody= sprintf("$opt_data \"\" "); |
|
||||
push @docs, manpage("-d", $opt_data, "send this string as a body with POST"); |
|
||||
} |
|
||||
$usebody .= "$opt_request PUT "; |
|
||||
push @docs, manpage("-X", $opt_request, "replace the request method with this string"); |
|
||||
} |
|
||||
elsif(uc($method) eq "OPTIONS") { |
|
||||
$usemethod .= "$opt_request OPTIONS "; |
|
||||
if($path !~ /^\//) { |
|
||||
# very special case |
|
||||
$requesttarget="--request-target \"$path\" "; |
|
||||
push @docs, manpage("--request-target", "", |
|
||||
"specify request target to use instead of using the URL's"); |
|
||||
$path = ""; |
|
||||
} |
|
||||
} |
|
||||
elsif(uc($method) ne "GET") { |
|
||||
$error = "unsupported HTTP method $method"; |
|
||||
goto error; |
|
||||
} |
|
||||
|
|
||||
if($usebody) { |
|
||||
# body is set, handle the content-type |
|
||||
if(!$header{"content-type"}) { |
|
||||
$disabledheaders .= "$opt_header Content-Type: "; |
|
||||
} |
|
||||
elsif(lc($header{"content-type"}) ne |
|
||||
"application/x-www-form-urlencoded") { |
|
||||
# custom |
|
||||
$ignore_contenttype = 1; |
|
||||
$addedheaders .= sprintf("$opt_header \"Content-Type: %s\" ", |
|
||||
$header{"content-type"}); |
|
||||
} |
|
||||
elsif((lc($header{"content-type"}) eq |
|
||||
"application/x-www-form-urlencoded") && !$do_multipart && |
|
||||
($method eq "POST")) { |
|
||||
# default for normal POST |
|
||||
$ignore_contenttype = 1; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if($usesamehttpversion) { |
|
||||
if(uc($http) eq "HTTP/1.1") { |
|
||||
$httpver = "--http1.1 "; |
|
||||
push @docs, manpage("--http1.1", "", "use HTTP protocol version 1.1"); |
|
||||
} |
|
||||
elsif(uc($http) eq "HTTP/2") { |
|
||||
$httpver = "--http2 "; |
|
||||
push @docs, manpage("--http2", "", "use HTTP protocol version 2"); |
|
||||
} |
|
||||
else { |
|
||||
$error = "unsupported HTTP version $http"; |
|
||||
goto error; |
|
||||
} |
|
||||
} |
|
||||
if($disableheadersnotseen) { |
|
||||
if(!$header{'accept'}) { |
|
||||
$disabledheaders .= "$opt_header Accept: "; |
|
||||
} |
|
||||
if(!$header{'user-agent'}) { |
|
||||
$disabledheaders .= "$opt_header User-Agent: "; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if($do_multipart) { |
|
||||
if(!$header{lc("expect")}) { |
|
||||
# no expect header, disable it for us too since curl -F defaults to |
|
||||
# Expect: 100-continue |
|
||||
$disabledheaders .= "$opt_header Expect: "; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
# go through the headers alphabetically just to make the order fixed |
|
||||
foreach my $h (sort keys %header) { |
|
||||
if(lc($h) eq "host") { |
|
||||
# We use Host: for the URL creation |
|
||||
} |
|
||||
elsif((lc($h) eq "authorization") && |
|
||||
($header{'authorization'} =~ /^Basic (.*)/)) { |
|
||||
my $decoded = decode_base64($1); |
|
||||
$addedheaders .= sprintf("%s \"%s\" ", $opt_user, $decoded); |
|
||||
push @docs, manpage("-u", $opt_user, "use this user and password for Basic auth"); |
|
||||
} |
|
||||
elsif(lc($h) eq "expect") { |
|
||||
# let curl do expect on its own |
|
||||
} |
|
||||
elsif(lc($h) eq "content-type" && |
|
||||
($do_multipart || $ignore_contenttype)) { |
|
||||
# skip this for multipart |
|
||||
} |
|
||||
elsif(($h eq "accept-encoding") && |
|
||||
($header{$h} =~ /gzip/)) { |
|
||||
push @docs, manpage("--compressed", "", "request a compressed response"); |
|
||||
$addedheaders .= "--compressed "; |
|
||||
} |
|
||||
elsif((lc($h) eq "accept") && |
|
||||
($header{"accept"} eq "*/*")) { |
|
||||
# ignore if set to */* as that's a curl default |
|
||||
} |
|
||||
elsif(lc($h) eq "content-length") { |
|
||||
# we don't set custom size, just usebody |
|
||||
} |
|
||||
else { |
|
||||
$exact = $exactcase{$h}; |
|
||||
my $opt = sprintf("$opt_header \"%s: ", $exact); |
|
||||
if(lc($h) eq "user-agent") { |
|
||||
$opt = "$opt_user_agent \""; |
|
||||
push @docs, manpage("-A", $opt_user_agent, "use this custom User-Agent request header"); |
|
||||
} |
|
||||
elsif(lc($h) eq "cookie") { |
|
||||
$opt = "$opt_cookie \""; |
|
||||
push @docs, manpage("-b", $opt_cookie, "pass on this custom Cookie: request header"); |
|
||||
} |
|
||||
$addedheaders .= sprintf("%s%s\" ", $opt, $header{$h}); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if($path =~ /[ &?]/) { |
|
||||
$url = sprintf "\"%s://%s%s\"", $usehttp ? "http" : "https", $header{'host'}, $path; |
|
||||
} |
|
||||
else { |
|
||||
$url = sprintf "%s://%s%s", $usehttp ? "http" : "https", $header{'host'}, $path; |
|
||||
} |
|
||||
|
|
||||
if($disabledheaders || $addedheaders) { |
|
||||
push @docs, manpage("-H", $opt_header, "add, replace or remove HTTP headers from the request"); |
|
||||
} |
|
||||
|
|
||||
if($useverbose) { |
|
||||
$useverbose = "$opt_verbose "; |
|
||||
push @docs, manpage("-v", $opt_verbose, "show verbose output"); |
|
||||
} |
|
||||
|
|
||||
# This adds the -x option to prevent a curl request to actually go out to any |
|
||||
# remote server |
|
||||
my $lib="--libcurl - -x localhost:0 " if($uselibcurl); |
|
||||
my $curlcmd = sprintf "curl ${useverbose}${usemethod}${httpver}${disabledheaders}${addedheaders}${usebody}${multipart}${requesttarget}${lib}${url}"; |
|
||||
|
|
||||
if($uselibcurl) { |
|
||||
# this actually runs curl which will fail to connect so ignore errors |
|
||||
open(C, "$curlcmd 2>/dev/null|"); |
|
||||
while(<C>) { |
|
||||
# skip CURLOPT_PROXY since that's only used to avoid network |
|
||||
if($_ !~ /CURLOPT_PROXY, /) { |
|
||||
print $_; |
|
||||
} |
|
||||
} |
|
||||
close(C); |
|
||||
} |
|
||||
else { |
|
||||
print "$curlcmd\n"; |
|
||||
} |
|
||||
|
|
||||
if($usenotes) { |
|
||||
print "---\n"; |
|
||||
foreach my $n (@notes) { |
|
||||
print "$n\n"; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if($usedocs) { |
|
||||
print "---\n"; |
|
||||
foreach my $d (@docs) { |
|
||||
print "$d\n"; |
|
||||
} |
|
||||
} |
|
@ -1,4 +0,0 @@ |
|||||
|
|
||||
# Placeholder with simple test |
|
||||
expect_equal(1 + 1, 2) |
|
||||
|
|
@ -1,32 +0,0 @@ |
|||||
% Generated by roxygen2: do not edit by hand |
|
||||
% Please edit documentation in R/h2c.R |
|
||||
\name{h2c} |
|
||||
\alias{h2c} |
|
||||
\title{Convert an 'httr' call to 'curl' command line} |
|
||||
\usage{ |
|
||||
h2c(complete_httr_verb_call, use_web_service = FALSE) |
|
||||
} |
|
||||
\arguments{ |
|
||||
\item{complete_httr_verb_call}{wrap an \code{httr} \code{VERB} call with this function |
|
||||
and it will return the text of a working \code{curl} command line} |
|
||||
|
|
||||
\item{use_web_service}{if \code{TRUE} (\code{FALSE} by default) this function will use |
|
||||
\verb{https://curl.se/h2c/} to process the headers.} |
|
||||
} |
|
||||
\description{ |
|
||||
Convert an 'httr' call to 'curl' command line |
|
||||
} |
|
||||
\examples{ |
|
||||
\dontrun{ |
|
||||
h2c( |
|
||||
httr::GET( |
|
||||
url = "https://rud.is/", |
|
||||
httr::user_agent(splashr::ua_apple_tv), |
|
||||
query = list( |
|
||||
a = "b", |
|
||||
c = 1 |
|
||||
) |
|
||||
) |
|
||||
) |
|
||||
} |
|
||||
} |
|
@ -1,24 +0,0 @@ |
|||||
% Generated by roxygen2: do not edit by hand |
|
||||
% Please edit documentation in R/httr2curl-package.R |
|
||||
\docType{package} |
|
||||
\name{httr2curl} |
|
||||
\alias{httr2curl} |
|
||||
\alias{httr2curl-package} |
|
||||
\title{Turn 'httr' Web Requests Into 'curl' Command Line Calls} |
|
||||
\description{ |
|
||||
When provided with an 'httr' "VERB" call, the request will be made |
|
||||
and 'libcurl' headers will be captured and post-processed to provide a working |
|
||||
'curl' command line call. |
|
||||
} |
|
||||
\seealso{ |
|
||||
Useful links: |
|
||||
\itemize{ |
|
||||
\item \url{https://git.rud.is/hrbrmstr/httr2curl} |
|
||||
\item Report bugs at \url{https://git.rud.is/hrbrmstr/httr2curl/issues} |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
\author{ |
|
||||
Bob Rudis (bob@rud.is) |
|
||||
} |
|
||||
\keyword{internal} |
|
@ -1,12 +0,0 @@ |
|||||
% Generated by roxygen2: do not edit by hand |
|
||||
% Please edit documentation in R/utils-pipe.R |
|
||||
\name{\%>\%} |
|
||||
\alias{\%>\%} |
|
||||
\title{Pipe operator} |
|
||||
\usage{ |
|
||||
lhs \%>\% rhs |
|
||||
} |
|
||||
\description{ |
|
||||
See \code{magrittr::\link[magrittr:pipe]{\%>\%}} for details. |
|
||||
} |
|
||||
\keyword{internal} |
|
@ -1,5 +0,0 @@ |
|||||
|
|
||||
if ( requireNamespace("tinytest", quietly=TRUE) ){ |
|
||||
tinytest::test_package("httr2curl") |
|
||||
} |
|
||||
|
|
Loading…
Reference in new issue