v0.13.9-ha_addon
This commit is contained in:
+19
-16
@@ -67,23 +67,26 @@ fn request_base_path(state: &AppState, headers: &HeaderMap) -> String {
|
||||
}
|
||||
|
||||
fn forwarded_prefix(headers: &HeaderMap) -> Option<String> {
|
||||
let raw = headers
|
||||
.get("x-forwarded-prefix")?
|
||||
.to_str()
|
||||
.ok()?
|
||||
.split(',')
|
||||
.next()?
|
||||
.trim();
|
||||
if raw.is_empty() || raw == "/" {
|
||||
return Some(String::new());
|
||||
// Home Assistant ingress uses X-Ingress-Path. Generic reverse proxies
|
||||
// commonly use X-Forwarded-Prefix, so support both with HA taking
|
||||
// precedence when both are present.
|
||||
for header in ["x-ingress-path", "x-forwarded-prefix"] {
|
||||
let Some(raw) = headers.get(header).and_then(|value| value.to_str().ok()) else {
|
||||
continue;
|
||||
};
|
||||
let raw = raw.split(',').next().unwrap_or_default().trim();
|
||||
if raw.is_empty() || raw == "/" {
|
||||
return Some(String::new());
|
||||
}
|
||||
if raw.contains('?')
|
||||
|| raw.contains('#')
|
||||
|| raw.split('/').any(|part| matches!(part, "." | ".."))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
return Some(format!("/{}", raw.trim_matches('/')));
|
||||
}
|
||||
if raw.contains('?')
|
||||
|| raw.contains('#')
|
||||
|| raw.split('/').any(|part| matches!(part, "." | ".."))
|
||||
{
|
||||
return None;
|
||||
}
|
||||
Some(format!("/{}", raw.trim_matches('/')))
|
||||
None
|
||||
}
|
||||
async fn app_js() -> Response {
|
||||
static_response(
|
||||
|
||||
@@ -51,8 +51,9 @@ fn local_ipv4_config_for_target(target: Ipv4Addr) -> Result<Option<LocalIpv4Conf
|
||||
fn local_ipv4_config_for_target(_target: Ipv4Addr) -> Result<Option<LocalIpv4Config>> { Ok(None) }
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
fn interface_ipv4_config(interface: &str) -> Result<(Ipv4Addr, Ipv4Addr)> {
|
||||
fn interface_ipv4_config(selector: &str) -> Result<(Ipv4Addr, Ipv4Addr)> {
|
||||
use std::{ffi::CStr, ptr};
|
||||
let requested_ip = selector.parse::<Ipv4Addr>().ok();
|
||||
unsafe {
|
||||
let mut addrs: *mut libc::ifaddrs = ptr::null_mut();
|
||||
if libc::getifaddrs(&mut addrs) != 0 { return Err(std::io::Error::last_os_error()).context("getifaddrs failed"); }
|
||||
@@ -60,11 +61,14 @@ fn interface_ipv4_config(interface: &str) -> Result<(Ipv4Addr, Ipv4Addr)> {
|
||||
let mut found = None;
|
||||
while !current.is_null() {
|
||||
let ifa = &*current;
|
||||
if !ifa.ifa_name.is_null() && !ifa.ifa_addr.is_null() {
|
||||
if !ifa.ifa_name.is_null()
|
||||
&& !ifa.ifa_addr.is_null()
|
||||
&& (*ifa.ifa_addr).sa_family as i32 == libc::AF_INET
|
||||
{
|
||||
let name = CStr::from_ptr(ifa.ifa_name).to_string_lossy();
|
||||
if name == interface && (*ifa.ifa_addr).sa_family as i32 == libc::AF_INET {
|
||||
let addr = &*(ifa.ifa_addr as *const libc::sockaddr_in);
|
||||
let ip = Ipv4Addr::from(addr.sin_addr.s_addr.to_ne_bytes());
|
||||
let addr = &*(ifa.ifa_addr as *const libc::sockaddr_in);
|
||||
let ip = Ipv4Addr::from(addr.sin_addr.s_addr.to_ne_bytes());
|
||||
if name == selector || requested_ip == Some(ip) {
|
||||
let broadcast = if !ifa.ifa_netmask.is_null() {
|
||||
let mask_addr = &*(ifa.ifa_netmask as *const libc::sockaddr_in);
|
||||
let mask = Ipv4Addr::from(mask_addr.sin_addr.s_addr.to_ne_bytes());
|
||||
@@ -77,7 +81,7 @@ fn interface_ipv4_config(interface: &str) -> Result<(Ipv4Addr, Ipv4Addr)> {
|
||||
current = ifa.ifa_next;
|
||||
}
|
||||
libc::freeifaddrs(addrs);
|
||||
found.ok_or_else(|| anyhow!("interface {interface} has no IPv4 address"))
|
||||
found.ok_or_else(|| anyhow!("interface or local IPv4 address {selector} was not found"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user