Compare commits

...

No commits in common. 'master' and 'batman' have entirely different histories.

  1. 26
      .Rbuildignore
  2. 1
      .codecov.yml
  3. 26
      .github/workflows/R-CMD-check.yaml
  4. 9
      .gitignore
  5. 12
      .travis.yml
  6. 25
      CONDUCT.md
  7. 30
      DESCRIPTION
  8. 2
      LICENSE
  9. 21
      LICENSE.md
  10. 9
      NAMESPACE
  11. 2
      NEWS.md
  12. 68
      R/h2c.R
  13. 12
      R/httr2curl-package.R
  14. 11
      R/utils-pipe.R
  15. 14
      R/utils.R
  16. 83
      README.Rmd
  17. 97
      README.md
  18. 52
      appveyor.yml
  19. 21
      httr2curl.Rproj
  20. 426
      inst/bin/h2c.pl
  21. 4
      inst/tinytest/test_httr2curl.R
  22. 32
      man/h2c.Rd
  23. 24
      man/httr2curl.Rd
  24. 12
      man/pipe.Rd
  25. 5
      tests/tinytest.R

26
.Rbuildignore

@ -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
.codecov.yml

@ -1 +0,0 @@
comment: false

26
.github/workflows/R-CMD-check.yaml

@ -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}

9
.gitignore

@ -1,9 +0,0 @@
.DS_Store
.Rproj.user
.Rhistory
.RData
.Rproj
README_cache
src/*.o
src/*.so
src/*.dll

12
.travis.yml

@ -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()'

25
CONDUCT.md

@ -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/

30
DESCRIPTION

@ -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

2
LICENSE

@ -1,2 +0,0 @@
YEAR: 2021
COPYRIGHT HOLDER: Bob Rudis

21
LICENSE.md

@ -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.

9
NAMESPACE

@ -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,"%>%")

2
NEWS.md

@ -1,2 +0,0 @@
0.1.0
* Initial release

68
R/h2c.R

@ -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)
}
}

12
R/httr2curl-package.R

@ -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"

11
R/utils-pipe.R

@ -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

14
R/utils.R

@ -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)
}

83
README.Rmd

@ -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.

97
README.md

@ -1,99 +1,2 @@
[![Project Status: Active – The project has reached a stable, usable
state and is being actively
developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
[![Signed
by](https://img.shields.io/badge/Keybase-Verified-brightgreen.svg)](https://keybase.io/hrbrmstr)
![Signed commit
%](https://img.shields.io/badge/Signed_Commits-100%25-lightgrey.svg)
[![R-CMD-check](https://github.com/hrbrmstr/httr2curl/workflows/R-CMD-check/badge.svg)](https://github.com/hrbrmstr/httr2curl/actions?query=workflow%3AR-CMD-check)
[![Linux build
Status](https://travis-ci.org/hrbrmstr/httr2curl.svg?branch=master)](https://travis-ci.org/hrbrmstr/httr2curl)
![Minimal R
Version](https://img.shields.io/badge/R%3E%3D-3.6.0-blue.svg)
![License](https://img.shields.io/badge/License-MIT-blue.svg)
# httr2curl
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.
## What’s Inside The Tin
The following functions are implemented:
- `h2c`: Convert an ‘httr’ call to ‘curl’ command line
## Installation
``` r
remotes::install_git("https://git.rud.is/hrbrmstr/httr2curl.git")
```
NOTE: To use the ‘remotes’ install options you will need to have the
[{remotes} package](https://github.com/r-lib/remotes) installed.
## Usage
``` r
library(httr2curl)
# current version
packageVersion("httr2curl")
## [1] '0.1.0'
```
### Using local perl
``` r
h2c(
httr::GET(
url = "https://rud.is/",
httr::user_agent(splashr::ua_apple_tv),
query = list(
a = "b",
c = 1
)
)
)
## [1] "curl --http2 --header \"Accept: application/json, text/xml, application/xml, */*\" --compressed --user-agent \"AppleTV6,2/11.1\" \"https://rud.is/?a=b&c=1\""
```
### Using the web service
``` r
h2c(
httr::GET(
url = "https://rud.is/",
httr::user_agent(splashr::ua_apple_tv),
query = list(
a = "b",
c = 1
)
),
use_web_service = TRUE
)
## [1] "curl --header \"Accept: application/json, text/xml, application/xml, */*\" --compressed --user-agent \"AppleTV6,2/11.1\" \"https://rud.is/?a=b&c=1\""
```
## httr2curl Metrics
| Lang | \# Files | (%) | LoC | (%) | Blank lines | (%) | \# Lines | (%) |
|:-----|---------:|-----:|----:|-----:|------------:|-----:|---------:|-----:|
| R | 5 | 0.36 | 49 | 0.24 | 21 | 0.25 | 40 | 0.26 |
| Rmd | 1 | 0.07 | 29 | 0.14 | 19 | 0.23 | 35 | 0.23 |
| YAML | 1 | 0.07 | 22 | 0.11 | 2 | 0.02 | 2 | 0.01 |
| SUM | 7 | 0.50 | 100 | 0.50 | 42 | 0.50 | 77 | 0.50 |
clock Package Metrics for httr2curl
## 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.

52
appveyor.yml

@ -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

21
httr2curl.Rproj

@ -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

426
inst/bin/h2c.pl

@ -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";
}
}

4
inst/tinytest/test_httr2curl.R

@ -1,4 +0,0 @@
# Placeholder with simple test
expect_equal(1 + 1, 2)

32
man/h2c.Rd

@ -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
)
)
)
}
}

24
man/httr2curl.Rd

@ -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}

12
man/pipe.Rd

@ -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}

5
tests/tinytest.R

@ -1,5 +0,0 @@
if ( requireNamespace("tinytest", quietly=TRUE) ){
tinytest::test_package("httr2curl")
}
Loading…
Cancel
Save