Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/rust/src/downloads.rs
2885 views
1
// Licensed to the Software Freedom Conservancy (SFC) under one
2
// or more contributor license agreements. See the NOTICE file
3
// distributed with this work for additional information
4
// regarding copyright ownership. The SFC licenses this file
5
// to you under the Apache License, Version 2.0 (the
6
// "License"); you may not use this file except in compliance
7
// with the License. You may obtain a copy of the License at
8
//
9
// http://www.apache.org/licenses/LICENSE-2.0
10
//
11
// Unless required by applicable law or agreed to in writing,
12
// software distributed under the License is distributed on an
13
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
// KIND, either express or implied. See the License for the
15
// specific language governing permissions and limitations
16
// under the License.
17
18
use crate::files::parse_version;
19
use crate::Logger;
20
use anyhow::anyhow;
21
use anyhow::Error;
22
use reqwest::{Client, StatusCode};
23
use serde::{Deserialize, Serialize};
24
use std::fs::File;
25
use std::io::copy;
26
use std::io::Cursor;
27
use tempfile::{Builder, TempDir};
28
29
#[tokio::main]
30
pub async fn download_to_tmp_folder(
31
http_client: &Client,
32
url: String,
33
log: &Logger,
34
) -> Result<(TempDir, String), Error> {
35
let tmp_dir = Builder::new().prefix("selenium-manager").tempdir()?;
36
log.trace(format!(
37
"Downloading {} to temporal folder {:?}",
38
url,
39
tmp_dir.path()
40
));
41
42
let response = http_client.get(&url).send().await?;
43
let status_code = response.status();
44
if status_code != StatusCode::OK {
45
return Err(anyhow!(format!(
46
"Unsuccessful response ({}) for URL {}",
47
status_code, url
48
)));
49
}
50
51
let target_path;
52
let mut tmp_file = {
53
let target_name = response
54
.url()
55
.path_segments()
56
.and_then(|segments| segments.last())
57
.and_then(|name| if name.is_empty() { None } else { Some(name) })
58
.unwrap_or("tmp.bin");
59
60
log.trace(format!("File to be downloaded: {}", target_name));
61
let target_name = tmp_dir.path().join(target_name);
62
target_path = String::from(target_name.to_str().unwrap());
63
64
log.trace(format!(
65
"File downloaded to temporal folder: {}",
66
target_path
67
));
68
File::create(target_name)?
69
};
70
let mut content = Cursor::new(response.bytes().await?);
71
copy(&mut content, &mut tmp_file)?;
72
73
Ok((tmp_dir, target_path))
74
}
75
76
pub fn read_version_from_link(
77
http_client: &Client,
78
url: &str,
79
log: &Logger,
80
) -> Result<String, Error> {
81
parse_version(read_content_from_link(http_client, url)?, log)
82
}
83
84
#[tokio::main]
85
pub async fn read_content_from_link(http_client: &Client, url: &str) -> Result<String, Error> {
86
Ok(http_client.get(url).send().await?.text().await?)
87
}
88
89
#[tokio::main]
90
pub async fn read_redirect_from_link(
91
http_client: &Client,
92
url: String,
93
log: &Logger,
94
) -> Result<String, Error> {
95
parse_version(
96
http_client.get(&url).send().await?.url().path().to_string(),
97
log,
98
)
99
}
100
101
pub fn parse_json_from_url<T>(http_client: &Client, url: &str) -> Result<T, Error>
102
where
103
T: Serialize + for<'a> Deserialize<'a>,
104
{
105
let content = read_content_from_link(http_client, url)?;
106
match serde_json::from_str(&content) {
107
Ok(json) => Ok(json),
108
Err(err) => Err(anyhow!(format!(
109
"Error parsing JSON from URL {} {}",
110
url, err
111
))),
112
}
113
}
114
115