mirror of
https://github.com/librespot-org/librespot.git
synced 2025-10-04 10:19:27 +02:00
Resolve AP through proxy as well
This commit is contained in:
parent
3bdc5e0073
commit
1a04e3b899
6 changed files with 63 additions and 37 deletions
|
@ -1,8 +1,10 @@
|
|||
const AP_FALLBACK: &'static str = "ap.spotify.com:443";
|
||||
const APRESOLVE_ENDPOINT: &'static str = "http://apresolve.spotify.com/";
|
||||
|
||||
use futures::{future, Future, Stream};
|
||||
use hyper::{self, Client, Uri};
|
||||
use futures::{Future, Stream};
|
||||
use hyper::client::HttpConnector;
|
||||
use hyper::{self, Client, Method, Request, Uri};
|
||||
use hyper_proxy::{Intercept, Proxy, ProxyConnector};
|
||||
use serde_json;
|
||||
use std::str::FromStr;
|
||||
use tokio_core::reactor::Handle;
|
||||
|
@ -14,11 +16,29 @@ pub struct APResolveData {
|
|||
ap_list: Vec<String>,
|
||||
}
|
||||
|
||||
fn apresolve(handle: &Handle) -> Box<Future<Item = String, Error = Error>> {
|
||||
fn apresolve(handle: &Handle, proxy: &Option<String>) -> Box<Future<Item = String, Error = Error>> {
|
||||
let url = Uri::from_str(APRESOLVE_ENDPOINT).expect("invalid AP resolve URL");
|
||||
let use_proxy = proxy.is_some();
|
||||
|
||||
let client = Client::new(handle);
|
||||
let response = client.get(url);
|
||||
let mut req = Request::new(Method::Get, url.clone());
|
||||
let response = match proxy {
|
||||
&Some(ref val) => {
|
||||
let proxy_url = Uri::from_str(&val).expect("invalid http proxy");
|
||||
let proxy = Proxy::new(Intercept::All, proxy_url);
|
||||
let connector = HttpConnector::new(4, handle);
|
||||
let proxy_connector = ProxyConnector::from_proxy_unsecured(connector, proxy);
|
||||
if let Some(headers) = proxy_connector.http_headers(&url) {
|
||||
req.headers_mut().extend(headers.iter());
|
||||
req.set_proxy(true);
|
||||
}
|
||||
let client = Client::configure().connector(proxy_connector).build(handle);
|
||||
client.request(req)
|
||||
}
|
||||
_ => {
|
||||
let client = Client::new(handle);
|
||||
client.request(req)
|
||||
}
|
||||
};
|
||||
|
||||
let body = response.and_then(|response| {
|
||||
response.body().fold(Vec::new(), |mut acc, chunk| {
|
||||
|
@ -32,8 +52,19 @@ fn apresolve(handle: &Handle) -> Box<Future<Item = String, Error = Error>> {
|
|||
let data =
|
||||
body.and_then(|body| serde_json::from_str::<APResolveData>(&body).chain_err(|| "invalid JSON"));
|
||||
|
||||
let ap = data.and_then(|data| {
|
||||
let ap = data.ap_list.first().ok_or("empty AP List")?;
|
||||
let ap = data.and_then(move |data| {
|
||||
let mut aps = data.ap_list.iter().filter(|ap| {
|
||||
if use_proxy {
|
||||
// It is unlikely that the proxy will accept CONNECT on anything other than 443.
|
||||
Uri::from_str(ap)
|
||||
.ok()
|
||||
.map_or(false, |uri| uri.port().map_or(false, |port| port == 443))
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
|
||||
let ap = aps.next().ok_or("empty AP List")?;
|
||||
Ok(ap.clone())
|
||||
});
|
||||
|
||||
|
@ -47,17 +78,11 @@ pub(crate) fn apresolve_or_fallback<E>(
|
|||
where
|
||||
E: 'static,
|
||||
{
|
||||
if proxy.is_some() {
|
||||
// TODO: Use a proper proxy library and filter out a 443 proxy instead of relying on fallback.
|
||||
// The problem with current libraries (hyper-proxy, reqwest) is that they depend on TLS
|
||||
// and this is a dependency we might not want.
|
||||
Box::new(future::result(Ok(AP_FALLBACK.into())))
|
||||
} else {
|
||||
let ap = apresolve(handle).or_else(|e| {
|
||||
warn!("Failed to resolve Access Point: {}", e.description());
|
||||
warn!("Using fallback \"{}\"", AP_FALLBACK);
|
||||
Ok(AP_FALLBACK.into())
|
||||
});
|
||||
Box::new(ap)
|
||||
}
|
||||
let ap = apresolve(handle, proxy).or_else(|e| {
|
||||
warn!("Failed to resolve Access Point: {}", e.description());
|
||||
warn!("Using fallback \"{}\"", AP_FALLBACK);
|
||||
Ok(AP_FALLBACK.into())
|
||||
});
|
||||
|
||||
Box::new(ap)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue