Skip to content

Commit 8d645ca

Browse files
committed
chore: move insert_header to client
1 parent c46f9bd commit 8d645ca

File tree

3 files changed

+61
-69
lines changed

3 files changed

+61
-69
lines changed

README.md

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,54 +49,45 @@ let body = resp
4949
.await?;
5050
```
5151

52-
Simplified example using an authenticated API gateway and JWT authorization (like SupaBase).
52+
Simplified example using a custom header (e.g. for API gateway authentication with Supabase).
5353

5454
```rust
5555
use postgrest::Postgrest;
5656

57-
static HEADER_KEY: &str = "apikey";
58-
let header_value: String = "ExampleAPIKeyValue".to_string(); // EXAMPLE ONLY!
57+
let client = Postgrest::new("https://your.supabase.endpoint/rest/v1/")
58+
.insert_header("apikey", "ExampleAPIKeyValue"); // EXAMPLE ONLY!
5959
// Don't actually hard code this value, that's really bad. Use environment
6060
// variables like with the dotenv(https://crates.io/crates/dotenv) crate to inject
61-
62-
let client = Postgrest::new("https://your.supabase.endpoint/rest/v1/");
6361
let resp = client
6462
.from("your_table")
65-
.auth(header_value)
66-
.insert_header(HEADER_KEY, header_value)
6763
.select("*")
6864
.execute()
6965
.await?;
7066
let body = resp
7167
.text()
7268
.await?;
73-
7469
```
7570

76-
**Secure** example with authenticated API gateway and JWT authorization using the dotenv crate to correctly retrieve sensitive values.
71+
**Secure** example with authenticated API gateway using the dotenv crate to correctly retrieve sensitive values.
7772

7873
```rust
7974
use postgrest::Postgrest;
8075
use dotenv;
8176

8277
dotenv().ok();
8378

84-
static HEADER_KEY: &str = "apikey";
85-
8679
let client = Postgrest::new("https://your.supabase.endpoint/rest/v1/");
80+
.insert_header(
81+
"apikey",
82+
env::var("SUPABASE_PUBLIC_API_KEY").unwrap())
8783
let resp = client
8884
.from("your_table")
89-
.auth(env::var("supabase_public_api_key").unwrap().to_string()))
90-
.insert_header(
91-
HEADER_KEY,
92-
env::var("supabase_public_api_key").unwrap().to_string())
9385
.select("*")
9486
.execute()
9587
.await?;
9688
let body = resp
9789
.text()
9890
.await?;
99-
10091
```
10192

10293
### Building Queries

src/builder.rs

Lines changed: 13 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub struct Builder {
1717
// TODO: Test Unicode support
1818
impl Builder {
1919
/// Creates a new `Builder` with the specified `schema`.
20-
pub fn new<T>(url: T, schema: Option<String>) -> Self
20+
pub fn new<T>(url: T, schema: Option<String>, headers: HeaderMap) -> Self
2121
where
2222
T: Into<String>,
2323
{
@@ -26,7 +26,7 @@ impl Builder {
2626
url: url.into(),
2727
schema,
2828
queries: Vec::new(),
29-
headers: HeaderMap::new(),
29+
headers,
3030
body: None,
3131
is_rpc: false,
3232
};
@@ -59,31 +59,6 @@ impl Builder {
5959
self
6060
}
6161

62-
/// Add arbitrary headers to the request. For instance when you may want to connect
63-
/// through an api gateway that needs an API key header in addition to the JWT.
64-
///
65-
/// # Example
66-
///
67-
/// ```
68-
/// use postgrest::Postgrest;
69-
///
70-
/// static header_name: &'static str = "foo";
71-
/// let header_value: String = "bar".to_string();
72-
///
73-
/// let client = Postgrest::new("https://your.postgrest.endpoint/rest/v1/");
74-
/// client
75-
/// .from("table")
76-
/// .insert_header(header_name, header_value);
77-
/// ```
78-
pub fn insert_header(mut self, header_name: &'static str, header_value: String) -> Self {
79-
self.headers.insert(
80-
header_name,
81-
HeaderValue::from_str(&header_value)
82-
.expect("Couldn't convert supplied header value from String to str."),
83-
);
84-
self
85-
}
86-
8762
/// Performs horizontal filtering with SELECT.
8863
///
8964
/// # Note
@@ -478,7 +453,7 @@ mod tests {
478453

479454
#[test]
480455
fn only_accept_json() {
481-
let builder = Builder::new(TABLE_URL, None);
456+
let builder = Builder::new(TABLE_URL, None, HeaderMap::new());
482457
assert_eq!(
483458
builder.headers.get("Accept").unwrap(),
484459
HeaderValue::from_static("application/json")
@@ -487,27 +462,16 @@ mod tests {
487462

488463
#[test]
489464
fn auth_with_token() {
490-
let builder = Builder::new(TABLE_URL, None).auth("$Up3rS3crET");
465+
let builder = Builder::new(TABLE_URL, None, HeaderMap::new()).auth("$Up3rS3crET");
491466
assert_eq!(
492467
builder.headers.get("Authorization").unwrap(),
493468
HeaderValue::from_static("Bearer $Up3rS3crET")
494469
);
495470
}
496471

497-
#[test]
498-
fn with_insert_header() {
499-
static A_HEADER_KEY: &str = "foo";
500-
let a_header_value: String = "bar".to_string();
501-
let builder = Builder::new(TABLE_URL, None).insert_header(A_HEADER_KEY, a_header_value);
502-
assert_eq!(
503-
builder.headers.get("foo").unwrap(),
504-
HeaderValue::from_static("bar")
505-
);
506-
}
507-
508472
#[test]
509473
fn select_assert_query() {
510-
let builder = Builder::new(TABLE_URL, None).select("some_table");
474+
let builder = Builder::new(TABLE_URL, None, HeaderMap::new()).select("some_table");
511475
assert_eq!(builder.method, Method::GET);
512476
assert_eq!(
513477
builder
@@ -519,7 +483,7 @@ mod tests {
519483

520484
#[test]
521485
fn order_assert_query() {
522-
let builder = Builder::new(TABLE_URL, None).order("id");
486+
let builder = Builder::new(TABLE_URL, None, HeaderMap::new()).order("id");
523487
assert_eq!(
524488
builder
525489
.queries
@@ -530,7 +494,7 @@ mod tests {
530494

531495
#[test]
532496
fn limit_assert_range_header() {
533-
let builder = Builder::new(TABLE_URL, None).limit(20);
497+
let builder = Builder::new(TABLE_URL, None, HeaderMap::new()).limit(20);
534498
assert_eq!(
535499
builder.headers.get("Range").unwrap(),
536500
HeaderValue::from_static("0-19")
@@ -539,7 +503,7 @@ mod tests {
539503

540504
#[test]
541505
fn range_assert_range_header() {
542-
let builder = Builder::new(TABLE_URL, None).range(10, 20);
506+
let builder = Builder::new(TABLE_URL, None, HeaderMap::new()).range(10, 20);
543507
assert_eq!(
544508
builder.headers.get("Range").unwrap(),
545509
HeaderValue::from_static("10-20")
@@ -548,7 +512,7 @@ mod tests {
548512

549513
#[test]
550514
fn single_assert_accept_header() {
551-
let builder = Builder::new(TABLE_URL, None).single();
515+
let builder = Builder::new(TABLE_URL, None, HeaderMap::new()).single();
552516
assert_eq!(
553517
builder.headers.get("Accept").unwrap(),
554518
HeaderValue::from_static("application/vnd.pgrst.object+json")
@@ -557,7 +521,7 @@ mod tests {
557521

558522
#[test]
559523
fn upsert_assert_prefer_header() {
560-
let builder = Builder::new(TABLE_URL, None).upsert("ignored");
524+
let builder = Builder::new(TABLE_URL, None, HeaderMap::new()).upsert("ignored");
561525
assert_eq!(
562526
builder.headers.get("Prefer").unwrap(),
563527
HeaderValue::from_static("return=representation,resolution=merge-duplicates")
@@ -566,20 +530,20 @@ mod tests {
566530

567531
#[test]
568532
fn not_rpc_should_not_have_flag() {
569-
let builder = Builder::new(TABLE_URL, None).select("ignored");
533+
let builder = Builder::new(TABLE_URL, None, HeaderMap::new()).select("ignored");
570534
assert_eq!(builder.is_rpc, false);
571535
}
572536

573537
#[test]
574538
fn rpc_should_have_body_and_flag() {
575-
let builder = Builder::new(RPC_URL, None).rpc("{\"a\": 1, \"b\": 2}");
539+
let builder = Builder::new(RPC_URL, None, HeaderMap::new()).rpc("{\"a\": 1, \"b\": 2}");
576540
assert_eq!(builder.body.unwrap(), "{\"a\": 1, \"b\": 2}");
577541
assert_eq!(builder.is_rpc, true);
578542
}
579543

580544
#[test]
581545
fn chain_filters() -> Result<(), Box<dyn std::error::Error>> {
582-
let builder = Builder::new(TABLE_URL, None)
546+
let builder = Builder::new(TABLE_URL, None, HeaderMap::new())
583547
.eq("username", "supabot")
584548
.neq("message", "hello world")
585549
.gte("channel_id", "1")

src/lib.rs

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,16 +74,16 @@
7474
//! [postgrest]: https://postgrest.org
7575
//! [readme]: https://github.com/supabase/postgrest-rs
7676
77-
extern crate reqwest;
78-
7977
mod builder;
8078
mod filter;
8179

8280
pub use builder::Builder;
81+
use reqwest::header::{HeaderMap, HeaderValue, IntoHeaderName};
8382

8483
pub struct Postgrest {
8584
url: String,
8685
schema: Option<String>,
86+
headers: HeaderMap,
8787
}
8888

8989
impl Postgrest {
@@ -103,6 +103,7 @@ impl Postgrest {
103103
Postgrest {
104104
url: url.into(),
105105
schema: None,
106+
headers: HeaderMap::new(),
106107
}
107108
}
108109

@@ -128,6 +129,30 @@ impl Postgrest {
128129
self
129130
}
130131

132+
/// Add arbitrary headers to the request. For instance when you may want to connect
133+
/// through an API gateway that needs an API key header.
134+
///
135+
/// # Example
136+
///
137+
/// ```
138+
/// use postgrest::Postgrest;
139+
///
140+
/// let client = Postgrest::new("https://your.postgrest.endpoint")
141+
/// .insert_header("apikey", "super.secret.key")
142+
/// .from("table");
143+
/// ```
144+
pub fn insert_header(
145+
mut self,
146+
header_name: impl IntoHeaderName,
147+
header_value: impl AsRef<str>,
148+
) -> Self {
149+
self.headers.insert(
150+
header_name,
151+
HeaderValue::from_str(header_value.as_ref()).expect("Invalid header value."),
152+
);
153+
self
154+
}
155+
131156
/// Perform a table operation.
132157
///
133158
/// # Example
@@ -143,7 +168,7 @@ impl Postgrest {
143168
T: AsRef<str>,
144169
{
145170
let url = format!("{}/{}", self.url, table.as_ref());
146-
Builder::new(url, self.schema.clone())
171+
Builder::new(url, self.schema.clone(), self.headers.clone())
147172
}
148173

149174
/// Perform a stored procedure call.
@@ -162,7 +187,7 @@ impl Postgrest {
162187
U: Into<String>,
163188
{
164189
let url = format!("{}/rpc/{}", self.url, function.as_ref());
165-
Builder::new(url, self.schema.clone()).rpc(params)
190+
Builder::new(url, self.schema.clone(), self.headers.clone()).rpc(params)
166191
}
167192
}
168193

@@ -184,4 +209,16 @@ mod tests {
184209
Some("private".to_string())
185210
);
186211
}
212+
213+
#[test]
214+
fn with_insert_header() {
215+
assert_eq!(
216+
Postgrest::new(REST_URL)
217+
.insert_header("apikey", "super.secret.key")
218+
.headers
219+
.get("apikey")
220+
.unwrap(),
221+
"super.secret.key"
222+
);
223+
}
187224
}

0 commit comments

Comments
 (0)