Skip to content
This repository has been archived by the owner on Aug 3, 2023. It is now read-only.

Added URL support for preview command #1001

Merged
merged 14 commits into from
Apr 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ ws = "0.9.0"
[dev-dependencies]
assert_cmd = "0.11.1"
fs_extra = "1.1.0"
predicates = "1.0.2"

[features]
vendored-openssl = ['openssl/vendored']
117 changes: 70 additions & 47 deletions src/commands/preview/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ use fiddle_messenger::*;
mod http_method;
pub use http_method::HTTPMethod;

mod request_payload;
pub use request_payload::RequestPayload;

mod upload;
pub use upload::upload;

use crate::commands;

use uuid::Uuid;

use log::info;

use crate::http;
Expand All @@ -24,13 +25,13 @@ use std::sync::mpsc::channel;
use std::thread;
use ws::{Sender, WebSocket};

// Using this instead of just `https://cloudflareworkers.com` returns just the worker response to the CLI
const PREVIEW_ADDRESS: &str = "https://00000000000000000000000000000000.cloudflareworkers.com";
use url::Url;

pub fn preview(
mut target: Target,
user: Option<GlobalUser>,
method: HTTPMethod,
url: Url,
body: Option<String>,
livereload: bool,
verbose: bool,
Expand All @@ -42,10 +43,10 @@ pub fn preview(

let script_id = upload(&mut target, user.as_ref(), sites_preview, verbose)?;

let session = Uuid::new_v4().to_simple();
let preview_host = "example.com";
let https = true;
let https_str = if https { "https://" } else { "http://" };
let request_payload = RequestPayload::create(method, url, body);

let session = &request_payload.session;
let browser_url = &request_payload.browser_url;

if livereload {
// explicitly use 127.0.0.1, since localhost can resolve to 2 addresses
Expand All @@ -57,47 +58,33 @@ pub fn preview(

if !headless {
open_browser(&format!(
"https://cloudflareworkers.com/?wrangler_session_id={0}&wrangler_ws_port={1}&hide_editor#{2}:{3}{4}",
&session.to_string(), ws_port, script_id, https_str, preview_host,
))?;
"https://cloudflareworkers.com/?wrangler_session_id={0}&wrangler_ws_port={1}&hide_editor#{2}:{3}",
session, ws_port, script_id, browser_url
))?;
}

// don't do initial GET + POST with livereload as the expected behavior is unclear.
// Make a the initial request to the URL
client_request(&request_payload, &script_id, &sites_preview);

let broadcaster = server.broadcaster();
thread::spawn(move || server.run());
watch_for_changes(
target,
user.as_ref(),
session.to_string(),
broadcaster,
verbose,
headless,
request_payload,
)?;
} else {
if !headless {
open_browser(&format!(
"https://cloudflareworkers.com/?hide_editor#{0}:{1}{2}",
script_id, https_str, preview_host
"https://cloudflareworkers.com/?hide_editor#{0}:{1}",
script_id, browser_url
))?;
}

let cookie = format!(
"__ew_fiddle_preview={}{}{}{}",
script_id, session, https as u8, preview_host
);

let client = http::client();

let worker_res = match method {
HTTPMethod::Get => get(cookie, &client)?,
HTTPMethod::Post => post(cookie, &client, body)?,
};
let msg = if sites_preview {
"Your Worker is a Workers Site, please preview it in browser window.".to_string()
} else {
format!("Your Worker responded with: {}", worker_res)
};
message::preview(&msg);
client_request(&request_payload, &script_id, &sites_preview);
}

Ok(())
Expand All @@ -119,35 +106,63 @@ fn open_browser(url: &str) -> Result<(), failure::Error> {
Ok(())
}

fn get(cookie: String, client: &reqwest::blocking::Client) -> Result<String, failure::Error> {
let res = client.get(PREVIEW_ADDRESS).header("Cookie", cookie).send();
fn client_request(payload: &RequestPayload, script_id: &String, sites_preview: &bool) {
let client = http::client();

let method = &payload.method;
let url = &payload.service_url;
let body = &payload.body;

let cookie = payload.cookie(script_id);

let worker_res = match method {
HTTPMethod::Get => get(&url, &cookie, &client).unwrap(),
HTTPMethod::Post => post(&url, &cookie, &body, &client).unwrap(),
};

let msg = if *sites_preview {
"Your Worker is a Workers Site, please preview it in browser window.".to_string()
} else {
format!("Your Worker responded with: {}", worker_res)
};
message::preview(&msg);
}

fn get(
url: &String,
cookie: &String,
client: &reqwest::blocking::Client,
) -> Result<String, failure::Error> {
let res = client.get(url).header("Cookie", cookie).send();
Ok(res?.text()?)
}

fn post(
cookie: String,
url: &String,
cookie: &String,
body: &Option<String>,
client: &reqwest::blocking::Client,
body: Option<String>,
) -> Result<String, failure::Error> {
let res = match body {
Some(s) => client
.post(PREVIEW_ADDRESS)
.post(url)
.header("Cookie", cookie)
.body(s)
.body(format!("{}", s))
.send(),
None => client.post(PREVIEW_ADDRESS).header("Cookie", cookie).send(),
None => client.post(url).header("Cookie", cookie).send(),
};
let msg = format!("POST {}", PREVIEW_ADDRESS);
let msg = format!("POST {}", url);
message::preview(&msg);
Ok(res?.text()?)
}

fn watch_for_changes(
mut target: Target,
user: Option<&GlobalUser>,
session_id: String,
broadcaster: Sender,
verbose: bool,
headless: bool,
request_payload: RequestPayload,
) -> Result<(), failure::Error> {
let sites_preview: bool = target.site.is_some();

Expand All @@ -158,17 +173,25 @@ fn watch_for_changes(
commands::build(&target)?;

if let Ok(new_id) = upload(&mut target, user, sites_preview, verbose) {
let script_id = format!("{}", new_id);

let msg = FiddleMessage {
session_id: session_id.clone(),
data: FiddleMessageData::LiveReload { new_id },
session_id: request_payload.session.clone(),
data: FiddleMessageData::LiveReload {
new_id: new_id.clone(),
},
};

match broadcaster.send(serde_json::to_string(&msg)?) {
Ok(_) => {
message::preview("Updated preview with changes");
if !headless {
match broadcaster.send(serde_json::to_string(&msg)?) {
Ok(_) => {
message::preview("Updated preview with changes");
}
Err(_e) => message::user_error("communication with preview failed"),
}
Err(_e) => message::user_error("communication with preview failed"),
}

client_request(&request_payload, &script_id, &sites_preview);
}
}

Expand Down
60 changes: 60 additions & 0 deletions src/commands/preview/request_payload.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use url::Url;
use uuid::Uuid;

use super::http_method::HTTPMethod;

pub struct RequestPayload {
pub method: HTTPMethod,
pub https: u8,
pub session: String,
pub protocol: String,
pub domain: String,
pub path: String,
pub query: String,
pub browser_url: String,
pub service_url: String,
pub body: Option<String>,
}

impl RequestPayload {
pub fn create(method: HTTPMethod, url: Url, body: Option<String>) -> RequestPayload {
let session = Uuid::new_v4().to_simple().to_string();

let https = if url.scheme() == "https" { 1 } else { 0 };
let protocol = format!("{}://", url.scheme());

let domain = url.domain().unwrap().to_string();
let path = url.path().to_string();

let query = match url.query() {
Some(query) => format!("?{}", query),
None => "".to_string(),
};

let browser_url = format!("{}{}{}{}", protocol, domain, path, query);
let service_url = format!(
"{}{}{}",
"https://00000000000000000000000000000000.cloudflareworkers.com", path, query
);

RequestPayload {
method,
https,
session,
protocol,
domain,
path,
query,
browser_url,
service_url,
body,
}
}

pub fn cookie(&self, script_id: &String) -> String {
format!(
"__ew_fiddle_preview={}{}{}{}",
script_id, self.session, self.https, self.domain
)
}
}
29 changes: 25 additions & 4 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ use commands::HTTPMethod;
use console::style;
use exitfailure::ExitFailure;

use url::Url;

use wrangler::commands;
use wrangler::commands::kv::key::KVMetaData;
use wrangler::installer;
Expand Down Expand Up @@ -383,24 +385,31 @@ fn run() -> Result<(), failure::Error> {
.help("Body string to post to your preview worker request")
.index(2),
)
.arg(
Arg::with_name("url")
.help("URL to open in the worker preview")
.short("u")
.long("url")
.takes_value(true)
)
.arg(
Arg::with_name("env")
.help("environment to preview")
.help("Environment to preview")
.short("e")
.long("env")
.takes_value(true)
)
.arg(
Arg::with_name("watch")
.help("watch your project for changes and update the preview automagically")
.help("Watch your project for changes and update the preview automagically")
.long("watch")
.takes_value(false),
)
.arg(
Arg::with_name("verbose")
.long("verbose")
.takes_value(false)
.help("toggle verbose output"),
.help("Toggle verbose output"),
),
)
.subcommand(
Expand Down Expand Up @@ -605,6 +614,18 @@ fn run() -> Result<(), failure::Error> {

let method = HTTPMethod::from_str(matches.value_of("method").unwrap_or("get"))?;

let url = Url::parse(matches.value_of("url").unwrap_or("https://example.com"))?;

// Validate the URL scheme
failure::ensure!(
match url.scheme() {
"http" => true,
"https" => true,
_ => false,
},
"Invalid URL scheme (use either \"https\" or \"http\")"
);

let body = match matches.value_of("body") {
Some(s) => Some(s.to_string()),
None => None,
Expand All @@ -614,7 +635,7 @@ fn run() -> Result<(), failure::Error> {
let verbose = matches.is_present("verbose");
let headless = matches.is_present("headless");

commands::preview(target, user, method, body, watch, verbose, headless)?;
commands::preview(target, user, method, url, body, watch, verbose, headless)?;
} else if let Some(matches) = matches.subcommand_matches("dev") {
log::info!("Starting dev server");
let port = matches.value_of("port");
Expand Down
Loading