Skip to content

Commit

Permalink
Add support for custom -H|--header passing. (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
jsirois authored Dec 12, 2022
1 parent ae5fabc commit 6d6b052
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 21 deletions.
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Release Notes

## 0.6.0

This release add support for passing custom headers to the server via
one or more `-H|--header` arguments.

## 0.5.0

This release begins sending a User-Agent header of `ptex/<version>` and
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ members = [

[package]
name = "ptex"
version = "0.5.0"
version = "0.6.0"
edition = "2021"
authors = [
"John Sirois <[email protected]>",
Expand Down
67 changes: 48 additions & 19 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use std::io::{Read, Write};
use std::path::{Path, PathBuf};

use anyhow::{anyhow, Context, Result};
use curl::easy::{Easy2, Handler, NetRc, WriteError};
use curl::easy::{Easy2, Handler, List, NetRc, WriteError};
use indicatif::{ProgressBar, ProgressState, ProgressStyle};
use serde::Deserialize;
use url::Url;
Expand Down Expand Up @@ -91,6 +91,7 @@ fn fetch_manifest<R: Read, W: Write>(
lift_manifest: R,
file_path: &Path,
output: W,
headers: Vec<String>,
show_headers: bool,
) -> Result<()> {
let config = Config::parse(lift_manifest)?;
Expand All @@ -100,11 +101,11 @@ fn fetch_manifest<R: Read, W: Write>(
path = file_path.display()
)
})?;
fetch(url, output, show_headers)
fetch(url, output, headers, show_headers)
.with_context(|| format!("Failed to source file {file}", file = file_path.display()))
}

fn fetch<W: Write>(url: &str, output: W, show_headers: bool) -> Result<()> {
fn fetch<W: Write>(url: &str, output: W, headers: Vec<String>, show_headers: bool) -> Result<()> {
let mut easy = Easy2::new(FetchHandler::new(url, output, show_headers));
easy.follow_location(true)
.context("Failed to configure re-direct following")?;
Expand All @@ -113,11 +114,21 @@ fn fetch<W: Write>(url: &str, output: W, show_headers: bool) -> Result<()> {
easy.netrc(NetRc::Optional)
.context("Failed to enable ~/.netrc parsing")?;
easy.url(url)
.context("Failed to configure URL to fetch from as {url}")?;
.with_context(|| format!("Failed to configure URL to fetch from as {url}"))?;
easy.progress(true)
.context("Failed to enable progress meter")?;
easy.useragent(format!("ptex/{version}", version = env!("CARGO_PKG_VERSION")).as_str())
.context("Failed to set User-Agent")?;
if !headers.is_empty() {
let mut curl_headers = List::new();
for header in headers {
curl_headers
.append(header.as_str())
.with_context(|| format!("Failed to set custom header {header}"))?;
}
easy.http_headers(curl_headers)
.context("Failed to configure custom headers")?;
}
easy.perform()
.with_context(|| format!("Failed to fetch {url}"))
}
Expand All @@ -127,8 +138,10 @@ fn usage(exit_code: i32, program_name: Option<String>) -> ! {
r#"Usage:
{bin_name} -V|--version
{bin_name} -h|--help
{bin_name} (-D|--dump-header) [lift manifest path] [file name]
{bin_name} (-O|--remote-name) (-D|--dump-header) [URL]
{bin_name}:
[-H|--header]* (-D|--dump-header) [lift manifest path] [file name]
{bin_name}:
(-O|--remote-name) [-H|--header]* (-D|--dump-header) [URL]
The `ptex` binary is a statically compiled URL fetcher based on
libcurl. It supports the HTTP protocol up through HTTP/2, the FTP
Expand All @@ -145,7 +158,11 @@ fn usage(exit_code: i32, program_name: Option<String>) -> ! {
Display this help.
{bin_name} (-D|--dump-header) [lift manifest path] [file name]
{bin_name}:
[-H|--header]* Pass custom header(s) to server.
(-D|--dump-header) Dump the headers received to stderr. Can also be
set via non-empty PTEX_DUMP_HEADERS env var.
[lift manifest path] [file name]
For use in a scie file source binding. The first argument is the
path to the scie lift manifest and the second argument is the file
Expand Down Expand Up @@ -200,15 +217,16 @@ fn usage(exit_code: i32, program_name: Option<String>) -> ! {
See more documentation on scie packaging configuration here:
https://github.com/a-scie/jump/blob/main/docs/packaging.md
{bin_name} (-O|--remote-name) (-D|--dump-header) [URL]
{bin_name}:
(-O|--remote-name) Write output to a file named as the remote file.
[-H|--header]* Pass custom header(s) to server.
(-D|--dump-header) Dump the headers received to stderr. Can also be
set via non-empty PTEX_DUMP_HEADERS env var.
[URL]
For use as a fully self-contained curl-like binary. The given URL is
fetched and the response is streamed to a file if -O or
--remote-name was specified and otherwise to stdout.
-O|--remote-name Write output to a file named as the remote file.
-D|--dump-header Dump the headers received to stderr. Can also be
set via non-empty PTEX_DUMP_HEADERS env var.
"#,
bin_name = program_name.unwrap_or_else(|| env!("CARGO_BIN_NAME").to_string())
);
Expand Down Expand Up @@ -250,8 +268,10 @@ fn main() {
let mut program_name = None;
let mut save_as_remote_name = false;
let mut show_headers = false;
let mut args = vec![];
for (index, arg) in env::args().enumerate() {
let mut headers = vec![];
let mut positional_args = vec![];
let mut args = env::args().enumerate();
while let Some((index, arg)) = args.next() {
if index == 0 {
program_name = Some(arg)
} else {
Expand All @@ -265,7 +285,14 @@ fn main() {
}
"-O" | "--remote-name" => save_as_remote_name = true,
"-D" | "--dump-header" => show_headers = true,
_ => args.push(arg),
"-H" | "--header" => {
if let Some((_, header)) = args.next() {
headers.push(header);
} else {
usage(1, program_name)
}
}
_ => positional_args.push(arg),
}
}
}
Expand All @@ -277,7 +304,7 @@ fn main() {
}
}

match &args[..] {
match &positional_args[..] {
[lift_manifest_path, file_path] if !save_as_remote_name => {
let lift_manifest = std::fs::File::open(lift_manifest_path)
.with_context(|| format!("Failed to open lift manifest at {lift_manifest_path}"))
Expand All @@ -286,16 +313,17 @@ fn main() {
&lift_manifest,
&PathBuf::from(file_path),
std::io::stdout(),
headers,
show_headers,
)
.or_exit()
}
[url] => {
if save_as_remote_name {
let file = open_remote_filename(url).or_exit();
fetch(url, file, show_headers).or_exit();
fetch(url, file, headers, show_headers).or_exit();
} else {
fetch(url, std::io::stdout(), show_headers).or_exit();
fetch(url, std::io::stdout(), headers, show_headers).or_exit();
}
}
_ => {
Expand Down Expand Up @@ -338,6 +366,7 @@ mod tests {
Cursor::new(manifest),
Path::new("scie-jump"),
&mut buffer,
vec![],
true,
)
.unwrap();
Expand All @@ -347,7 +376,7 @@ mod tests {
#[test]
fn fetch() {
let mut buffer: Vec<u8> = Vec::new();
super::fetch(URL, &mut buffer, false).unwrap();
super::fetch(URL, &mut buffer, vec![], false).unwrap();
assert_fetched_buffer(buffer.as_slice());
}
}

0 comments on commit 6d6b052

Please sign in to comment.