Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
added '[package.metadata.github-api].set-headers' section in Cargo.to…
…ml with an array of http headers necessary to add in lib.rs/`build_request()` (created in build.rs; imported with include!)
  • Loading branch information
dmgorsky committed Oct 29, 2025
commit a44ad6faa0d410a07be466a80634cfcf2a14942a
6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ categories = ["web-programming::http-client"]
keywords = ["github", "github-api"]
rust-version = "1.73.0"

[package.metadata.github-api]
set-headers = ["X-GitHub-Api-Version: 2022-11-28", ]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[package.metadata.docs.rs]
all-features = true
Expand Down Expand Up @@ -74,6 +77,9 @@ base64 = "0.22.0"
pretty_assertions = "1.4.0"
graphql_client = "0.14.0"

[build-dependencies]
cargo_metadata = "0.23.0"

[features]
default = [
"follow-redirect",
Expand Down
43 changes: 43 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use cargo_metadata::MetadataCommand;
use std::env;
use std::fs;
use std::path::Path;

fn main() {
println!("cargo:rerun-if-changed=Cargo.toml");

let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap(); // Cargo.toml path
let manifest_path = Path::new(&manifest_dir).join("Cargo.toml");

let metadata = MetadataCommand::new()
.manifest_path(&manifest_path)
.exec()
.expect("failed to parse `cargo metadata`");

let root_package = metadata.root_package().unwrap();
let custom_metadata = &root_package.metadata;

let set_headers_array = custom_metadata["github-api"]["set-headers"]
.as_array()
.cloned()
.unwrap_or(Default::default());
let set_headers_array = set_headers_array
.iter()
.map(|x| x.as_str().unwrap_or_default())
.map(|x| {
// split either by ":" or by ": "
x.split_once(": ")
.unwrap_or_else(|| (x.split_once(":")).unwrap_or_default())
})
.collect::<Vec<(&str, &str)>>();
let array_creation_static = format!(
"pub const _SET_HEADERS_MAP: [(&str, &str); {}] = {:?};",
&set_headers_array.len(),
&set_headers_array
);

let out_dir = env::var("OUT_DIR").unwrap(); // build's OUT path
let dest_path = Path::new(&out_dir).join("headers_metadata.rs");
fs::write(&dest_path, array_creation_static)
.expect(format!("failed to write {}", dest_path.display()).as_str());
}
15 changes: 15 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,15 @@ pub type Result<T, E = error::Error> = std::result::Result<T, E>;
const GITHUB_BASE_URI: &str = "https://api.github.com";
const GITHUB_BASE_UPLOAD_URI: &str = "https://uploads.github.com";

/// This `include!` gives us pub const _SET_HEADERS_MAP: [(&str, &str)]
/// generated from Cargo.toml `[package.metadata.github-api].set-headers` array, like
/// ```
/// [package.metadata.github-api]
///
/// set-headers = ["X-GitHub-Api-Version: 2022-11-28", ]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we call this headers instead? TOML is declarative not imperative, so you wouldn't include a verb like "set"

Copy link
Collaborator Author

@dmgorsky dmgorsky Nov 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NP, how can we make the name more descriptive? Like, 'headers to be set', without documentation.
necessary-headers, request-headers.
edit: request-headers 👌

/// ```
include!(concat!(env!("OUT_DIR"), "/headers_metadata.rs"));

#[cfg(feature = "default-client")]
static STATIC_INSTANCE: Lazy<arc_swap::ArcSwap<Octocrab>> =
Lazy::new(|| arc_swap::ArcSwap::from_pointee(Octocrab::default()));
Expand Down Expand Up @@ -1569,6 +1578,12 @@ impl Octocrab {
// In case octocrab needs to support cases where body is strictly streamable, it should use something like reqwest::Body,
// since it differentiates between retryable bodies, and streams(aka, it implements try_clone(), which is needed for middlewares like retry).

/// Add headers specified in Cargo.toml
/// '[package.metadata.github-api].set-headers' section
for kv in _SET_HEADERS_MAP {
builder = builder.header(kv.0, kv.1);
}

if let Some(body) = body {
builder = builder.header(http::header::CONTENT_TYPE, "application/json");
let serialized = serde_json::to_string(body).context(SerdeSnafu)?;
Expand Down