mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 05:25:40 +09:00
feat(push): allow listed hosts to resolve to private addresses (#3228)
This commit is contained in:
1 parent
d456048e69
commit
2006fc0d8d
8 files changed
+103
-22
No files matched your search
@@ -2,7 +2,7 @@
|
||||
|
||||
use crate::config::{ApnsConfig, FcmConfig, ProviderEnvironment};
|
||||
use crate::metrics::Metrics;
|
||||
use crate::resolver::PublicOnlyResolver;
|
||||
use crate::resolver::{BLOCKED_ADDRESS_ERROR, PublicOnlyResolver};
|
||||
use crate::tokens::{TokenCache, TokenError};
|
||||
use reqwest::header::{AUTHORIZATION, CONTENT_TYPE};
|
||||
use reqwest::redirect::Policy;
|
||||
@@ -30,10 +30,10 @@ pub fn http_client() -> reqwest::Result<reqwest::Client> {
|
||||
.build()
|
||||
}
|
||||
|
||||
pub fn web_push_http_client() -> reqwest::Result<reqwest::Client> {
|
||||
pub fn web_push_http_client(private_hosts: &[String]) -> reqwest::Result<reqwest::Client> {
|
||||
reqwest::Client::builder()
|
||||
.redirect(Policy::none())
|
||||
.dns_resolver(PublicOnlyResolver)
|
||||
.dns_resolver(PublicOnlyResolver::new(private_hosts))
|
||||
.connect_timeout(CONNECT_TIMEOUT)
|
||||
.timeout(HTTP_TIMEOUT)
|
||||
.build()
|
||||
@@ -65,6 +65,7 @@ pub enum VendorOutcome {
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum Unreachable {
|
||||
BlockedAddress,
|
||||
Dns,
|
||||
Transport,
|
||||
}
|
||||
@@ -72,17 +73,20 @@ pub enum Unreachable {
|
||||
impl Unreachable {
|
||||
pub fn label(self) -> &'static str {
|
||||
match self {
|
||||
Self::BlockedAddress => "blocked_address",
|
||||
Self::Dns => "dns",
|
||||
Self::Transport => "transport",
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_permanent(self) -> bool {
|
||||
matches!(self, Self::Dns)
|
||||
matches!(self, Self::BlockedAddress | Self::Dns)
|
||||
}
|
||||
|
||||
pub fn of(error: &reqwest::Error) -> Self {
|
||||
if names_no_host(error) {
|
||||
if source_mentions(error, BLOCKED_ADDRESS_ERROR) {
|
||||
Self::BlockedAddress
|
||||
} else if source_mentions(error, DNS_ERROR_MARKER) {
|
||||
Self::Dns
|
||||
} else {
|
||||
Self::Transport
|
||||
@@ -90,10 +94,10 @@ impl Unreachable {
|
||||
}
|
||||
}
|
||||
|
||||
fn names_no_host(error: &reqwest::Error) -> bool {
|
||||
fn source_mentions(error: &reqwest::Error, marker: &str) -> bool {
|
||||
let mut current = std::error::Error::source(error);
|
||||
while let Some(error) = current {
|
||||
if error.to_string().contains(DNS_ERROR_MARKER) {
|
||||
if error.to_string().contains(marker) {
|
||||
return true;
|
||||
}
|
||||
current = error.source();
|
||||
@@ -320,6 +324,29 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn a_host_in_blocked_address_space_is_named_as_such() {
|
||||
let error = web_push_http_client(&[])
|
||||
.expect("the http client builds")
|
||||
.post("https://localhost/push")
|
||||
.send()
|
||||
.await
|
||||
.expect_err("the request cannot complete");
|
||||
assert_eq!(Unreachable::of(&error), Unreachable::BlockedAddress);
|
||||
assert!(Unreachable::of(&error).is_permanent());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn a_listed_private_host_gets_through_to_connect() {
|
||||
let error = web_push_http_client(&["localhost".to_owned()])
|
||||
.expect("the http client builds")
|
||||
.post("https://localhost:1/push")
|
||||
.send()
|
||||
.await
|
||||
.expect_err("the request cannot complete");
|
||||
assert_eq!(Unreachable::of(&error), Unreachable::Transport);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn a_refused_connection_stays_retryable() {
|
||||
let error = error_for("http://127.0.0.1:1/").await;
|
||||
|
||||
Reference in new issue
Block a user