Fix 403 forbidden errors
This commit is contained in:
parent
ca6a6414f8
commit
e9023eec02
|
@ -1,2 +1,3 @@
|
||||||
/target
|
/target
|
||||||
Dockerfile
|
Dockerfile
|
||||||
|
port-file
|
|
@ -1 +1,2 @@
|
||||||
/target
|
/target
|
||||||
|
port-file
|
|
@ -23,6 +23,9 @@ RUN cargo build --release
|
||||||
# Runner stage.
|
# Runner stage.
|
||||||
FROM alpine
|
FROM alpine
|
||||||
|
|
||||||
|
RUN apk update && \
|
||||||
|
apk add curl
|
||||||
|
|
||||||
ARG UNAME=port_updater
|
ARG UNAME=port_updater
|
||||||
ARG UID=1000
|
ARG UID=1000
|
||||||
ARG GID=1000
|
ARG GID=1000
|
||||||
|
|
|
@ -6,8 +6,9 @@ Currently the only configuration method is through environmental variables:
|
||||||
|
|
||||||
| Name | Description | Example | Required |
|
| Name | Description | Example | Required |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| PORT_UPD_QBITTORRENT_LOGIN | The login information for the webui. | admin | false |
|
| PORT_UPD_QBITTORRENT_LOGIN | The login information for the webui. | `admin` | false |
|
||||||
| PORT_UPD_QBITTORRENT_PASSWORD | The password for the webui. | adminadmin | false |
|
| PORT_UPD_QBITTORRENT_PASSWORD | The password for the webui. | `adminadmin` | false |
|
||||||
| PORT_UPD_QBITTORRENT_PORT | The port of the webui. | 8080 | true |
|
| PORT_UPD_QBITTORRENT_PORT | The port of the webui. | `8080` | true |
|
||||||
| PORT_UPD_QBITTORRENT_HOST | The host of the webui. | localhost | true |
|
| PORT_UPD_QBITTORRENT_HOST | The host of the webui. | `localhost` | true |
|
||||||
|
| PORT_UPD_QBITTORRENT_HTTPS | Set to `true` if the connection to the webui is https encrypted. | `false` | true |
|
||||||
| PORT_UPD_PORT_FILE | The path to the file that contains the port. | `/tmp/gluetun/forwarded_port` | true |
|
| PORT_UPD_PORT_FILE | The path to the file that contains the port. | `/tmp/gluetun/forwarded_port` | true |
|
||||||
|
|
54
src/main.rs
54
src/main.rs
|
@ -1,7 +1,9 @@
|
||||||
use std::{path::Path, time::Duration, sync::Arc, collections::HashMap};
|
use std::{path::Path, time::Duration, sync::Arc, collections::HashMap};
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
use figment::{Figment, providers::Env};
|
use figment::{Figment, providers::Env};
|
||||||
use notify::{RecursiveMode, Watcher, Event, EventKind, event::{ModifyKind, DataChange}};
|
use notify::{RecursiveMode, Watcher, Event, EventKind, event::{ModifyKind, DataChange}};
|
||||||
|
use reqwest::StatusCode;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Deserialize)]
|
#[derive(Debug, PartialEq, Deserialize)]
|
||||||
|
@ -40,11 +42,12 @@ fn main() -> anyhow::Result<()> {
|
||||||
std::thread::sleep(Duration::from_secs(10));
|
std::thread::sleep(Duration::from_secs(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
while reqwest::blocking::get(config.qbit_full_url()).and_then(|r| r.error_for_status()).is_err() {
|
/* let url = format!("{}/api/v2/app/version", config.qbit_full_url());
|
||||||
println!("Couldn't reach qbittorrent at {}", config.qbit_full_url());
|
while let Err(e) = reqwest::blocking::get(&url) {//.and_then(|r| r.error_for_status()) {
|
||||||
|
println!("Couldn't reach qbittorrent at {} ({})", url, e);
|
||||||
println!("Trying again in 10 seconds");
|
println!("Trying again in 10 seconds");
|
||||||
std::thread::sleep(Duration::from_secs(10));
|
std::thread::sleep(Duration::from_secs(10));
|
||||||
}
|
} */
|
||||||
|
|
||||||
let config_clone = config.clone();
|
let config_clone = config.clone();
|
||||||
let mut watcher = notify::recommended_watcher(move |res: Result<Event, notify::Error>| {
|
let mut watcher = notify::recommended_watcher(move |res: Result<Event, notify::Error>| {
|
||||||
|
@ -53,7 +56,12 @@ fn main() -> anyhow::Result<()> {
|
||||||
//println!("e: {:?}", e);
|
//println!("e: {:?}", e);
|
||||||
if e.kind == EventKind::Modify(ModifyKind::Data(DataChange::Content))
|
if e.kind == EventKind::Modify(ModifyKind::Data(DataChange::Content))
|
||||||
|| e.kind.is_create() || e.kind.is_access() {
|
|| e.kind.is_create() || e.kind.is_access() {
|
||||||
update_port(config_clone.clone()).unwrap();
|
|
||||||
|
while let Err(e) = update_port(config_clone.clone()) {
|
||||||
|
println!("Could not update qbittorrent port! ({e})");
|
||||||
|
println!("Trying again in 10 seconds");
|
||||||
|
std::thread::sleep(Duration::from_secs(10));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => println!("watch error: {:?}", e),
|
Err(e) => println!("watch error: {:?}", e),
|
||||||
|
@ -61,7 +69,11 @@ fn main() -> anyhow::Result<()> {
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// update the port once on start in the case that gluetun got connected before this started
|
// update the port once on start in the case that gluetun got connected before this started
|
||||||
update_port(config.clone()).unwrap();
|
while let Err(e) = update_port(config.clone()) {
|
||||||
|
println!("Could not update qbittorrent port! ({e})");
|
||||||
|
println!("Trying again in 10 seconds");
|
||||||
|
std::thread::sleep(Duration::from_secs(10));
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
watcher.watch(port_path, RecursiveMode::Recursive)?;
|
watcher.watch(port_path, RecursiveMode::Recursive)?;
|
||||||
|
@ -73,31 +85,29 @@ fn update_port(config: Arc<Config>) -> anyhow::Result<()> {
|
||||||
|
|
||||||
let client = reqwest::blocking::Client::new();
|
let client = reqwest::blocking::Client::new();
|
||||||
|
|
||||||
let mut cookie_header = "".to_string();
|
|
||||||
|
|
||||||
if let (Some(login), Some(pass)) = (config.qbittorrent_login.clone(),
|
|
||||||
config.qbittorrent_password.clone()) {
|
|
||||||
|
|
||||||
let login_url = format!("{}/api/v2/auth/login", qbit_url);
|
let login_url = format!("{}/api/v2/auth/login", qbit_url);
|
||||||
|
|
||||||
let mut form = HashMap::new();
|
let mut form = HashMap::new();
|
||||||
|
if let (Some(login), Some(pass)) = (config.qbittorrent_login.clone(),
|
||||||
|
config.qbittorrent_password.clone()) {
|
||||||
form.insert("username", login);
|
form.insert("username", login);
|
||||||
form.insert("password", pass);
|
form.insert("password", pass);
|
||||||
|
}
|
||||||
|
|
||||||
let res = client.get(login_url)
|
let res = client.post(login_url)
|
||||||
.form(&form)
|
.form(&form)
|
||||||
.send()?;
|
.send()?;
|
||||||
|
|
||||||
let cookie = res.headers().get("Set-Cookie").expect("Login failed");
|
let cookie = if let Some(cookie) = res.headers().get(reqwest::header::SET_COOKIE) {
|
||||||
let cookie = cookie.to_str().unwrap();
|
let cookies: Vec<_> = cookie.to_str().unwrap().split(";").collect();
|
||||||
|
let sid = cookies.iter().find(|c| c.starts_with("SID=")).unwrap();
|
||||||
let sid_start = cookie.find("SID=").unwrap();
|
format!("{};", sid)
|
||||||
let sid_end = cookie.find(";").unwrap();
|
} else if res.status() == StatusCode::FORBIDDEN {
|
||||||
let sid = &cookie[sid_start..sid_end];
|
return Err(anyhow!("Failure to auth, credentials are incorrect!"));
|
||||||
let cookie = format!("SID={};", sid);
|
} else {
|
||||||
|
res.error_for_status()?;
|
||||||
cookie_header = cookie;
|
"".to_string()
|
||||||
}
|
};
|
||||||
|
|
||||||
let new_port = std::fs::read_to_string(&config.port_file)?;
|
let new_port = std::fs::read_to_string(&config.port_file)?;
|
||||||
let new_port = new_port.trim();
|
let new_port = new_port.trim();
|
||||||
|
@ -109,7 +119,7 @@ fn update_port(config: Arc<Config>) -> anyhow::Result<()> {
|
||||||
let url = format!("{}/api/v2/app/setPreferences", qbit_url);
|
let url = format!("{}/api/v2/app/setPreferences", qbit_url);
|
||||||
let _body = client.post(url)
|
let _body = client.post(url)
|
||||||
.form(&form)
|
.form(&form)
|
||||||
.header("Cookie", cookie_header)
|
.header("Cookie", cookie)
|
||||||
.send()?
|
.send()?
|
||||||
.error_for_status()?;
|
.error_for_status()?;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue