Skip to content

Commit

Permalink
feat: remove use of portpicker
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomio committed May 10, 2022
1 parent ac8456f commit b58415e
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 39 deletions.
10 changes: 0 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Expand Up @@ -33,7 +33,6 @@ dotenv = "0.15.0"
futures-util = "0.3.21"
http = "0.2.7"
once_cell = "1.10.0"
portpicker = "0.1.1"
rayon = "1.5.2"
regress = "0.4.1"
serde_json = "1.0.81"
Expand Down
2 changes: 2 additions & 0 deletions README.md
Expand Up @@ -30,6 +30,8 @@
- `REDIS_URL` - the address of your redis database (required)
- `FULLSCREEN_SCREENSHOT` - if set, it will screenshot the whole website (optional)
- `CHECK_IF_NSFW` - if set, it will check if the url is marked as NSFW (optional)
- `GOOGLE_CHROME_PATH` - the path to the chrome executable (optional)
- `CHROMEDRIVER_PATH` - the path to the chromedriver executable (optional)

### Railway

Expand Down
71 changes: 43 additions & 28 deletions src/main.rs
Expand Up @@ -12,15 +12,14 @@ use actix_web::middleware::Compress;
use actix_web::{web, App, Error, HttpServer};
use cdp::ChromeCommand;
use fantoccini::{Client, ClientBuilder};
use portpicker::pick_unused_port;
use providers::{Provider, Storage};
use reqwest::Client as ReqwestClient;
use serde_json::{Map, Value};
use tokio::process::Command;
use tokio_process_stream::ProcessLineStream;
use tokio_stream::StreamExt;
use tracing_actix_web::TracingLogger;
use util::{evaluate_on_new_document, initialize_tracing, load_env};
use util::{evaluate_on_new_document, initialize_tracing, is_heroku, load_env};

pub mod cdp;
pub mod error;
Expand All @@ -38,17 +37,27 @@ pub struct State {
pub reqwest: ReqwestClient,
}

static HEROKU_GOOGLE_CHROME_PATH: &str = "/app/.apt/usr/bin/google_chrome";
static HEROKU_CHROMEDRIVER_PATH: &str = "/app/.chromedriver/bin/chromedriver";

#[actix_web::main]
async fn main() -> anyhow::Result<()> {
load_env();
initialize_tracing();

let driver_port = pick_unused_port().expect("No port available");
let is_heroku = is_heroku();

tokio::spawn(async move {
let mut chromedriver = Command::new("chromedriver");
let path = match env::var("CHROMEDRIVER_PATH") {
Ok(path) => path,
Err(_) => match is_heroku {
true => HEROKU_CHROMEDRIVER_PATH.to_owned(),
false => "chromedriver".to_owned(),
},
};

let mut chromedriver = Command::new(path);
chromedriver.stdout(Stdio::piped()).stderr(Stdio::piped());
chromedriver.arg(format!("--port={driver_port}"));

let mut stream =
ProcessLineStream::try_from(chromedriver).expect("Failed to convert command to stream");
Expand All @@ -58,41 +67,47 @@ async fn main() -> anyhow::Result<()> {
}
});

let debug_port = pick_unused_port().expect("No port available");
let mut capabilities = Map::new();
let chrome_opts = if let Ok(shim) = env::var("GOOGLE_CHROME_SHIM") {
serde_json::json!({
"binary": shim,
let chrome_opts = match env::var("GOOGLE_CHROME_PATH") {
Ok(path) => serde_json::json!({
"binary": path,
"args": [
"--disable-gpu",
"--no-sandbox",
"--disable-dev-shm-usage",
"--headless",
"--whitelisted-ips=",
format!("--remote-debugging-port={debug_port}")
"--whitelisted-ips="
]
})
} else {
serde_json::json!({
"args": [
"--disable-gpu",
"--no-sandbox",
"--disable-dev-shm-usage",
"--headless",
"--whitelisted-ips=",
format!("--remote-debugging-port={debug_port}")
]
})
}),
Err(_) => match is_heroku {
true => serde_json::json!({
"binary": HEROKU_GOOGLE_CHROME_PATH,
"args": [
"--disable-gpu",
"--no-sandbox",
"--disable-dev-shm-usage",
"--headless",
"--whitelisted-ips="
]
}),
false => serde_json::json!({
"args": [
"--disable-gpu",
"--no-sandbox",
"--disable-dev-shm-usage",
"--headless",
"--whitelisted-ips="
]
}),
},
};

capabilities.insert("goog:chromeOptions".to_owned(), chrome_opts);

let client = ClientBuilder::rustls()
.capabilities(capabilities)
.connect(&format!("http://localhost:{driver_port}"))
.await?;
let client =
ClientBuilder::rustls().capabilities(capabilities).connect("http://localhost:9515").await?;

info!("Connected to chromedriver at localhost:{driver_port}");
info!("Connected to chromedriver at localhost:9515");

// To hide headless nature (for Cloudflare, etc.)
tokio::join!(
Expand Down
5 changes: 5 additions & 0 deletions src/util.rs
@@ -1,3 +1,4 @@
use std::env;
use std::ops::Not;
use std::path::Path;
use std::str::pattern::{Pattern, SearchStep, Searcher};
Expand Down Expand Up @@ -90,6 +91,10 @@ pub fn initialize_tracing() {
tracing::subscriber::set_global_default(subscriber).expect("Failed to initialize logger");
}

pub fn is_heroku() -> bool {
env::var("HEROKU").is_ok() || env::var("DYNO").is_ok()
}

pub async fn evaluate_on_new_document(client: &Client, js: String, args: Vec<Value>) {
let expr = format!(
"({js})({})",
Expand Down

0 comments on commit b58415e

Please sign in to comment.