Skip to content

Commit

Permalink
feat: set user agent in webdav requests (#2284)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukevmorris authored Dec 3, 2024
1 parent a1c33d4 commit 5a65dc5
Show file tree
Hide file tree
Showing 12 changed files with 58 additions and 23 deletions.
10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -164,16 +164,16 @@ all = [
"webdav",
"oss",
]
azure = ["opendal/services-azblob", "reqsign"]
azure = ["opendal/services-azblob", "reqsign", "reqwest"]
default = ["all"]
gcs = ["opendal/services-gcs", "reqsign", "url", "reqwest/blocking"]
gha = ["opendal/services-ghac"]
gcs = ["opendal/services-gcs", "reqsign", "url", "reqwest"]
gha = ["opendal/services-ghac", "reqwest"]
memcached = ["opendal/services-memcached"]
native-zlib = []
oss = ["opendal/services-oss", "reqsign"]
oss = ["opendal/services-oss", "reqsign", "reqwest"]
redis = ["url", "opendal/services-redis"]
s3 = ["opendal/services-s3", "reqsign", "reqwest"]
webdav = ["opendal/services-webdav"]
webdav = ["opendal/services-webdav", "reqwest"]
# Enable features that will build a vendored version of openssl and
# statically linked with it, instead of linking against the system-wide openssl
# dynamically or statically.
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,10 @@ Known Caveats

* Symbolic links to sccache won't work. Use hardlinks: `ln sccache /usr/local/bin/cc`

### User Agent

* Requests sent to your storage option of choice will have a user agent header indicating the current sccache version, e.g. `sccache/0.8.2`.

Storage Options
---------------

Expand Down
9 changes: 5 additions & 4 deletions docs/Webdav.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
# WebDAV

Set `SCCACHE_WEBDAV_ENDPOINT` to a webdav service endpoint to store cache in a webdav service. Set `SCCACHE_WEBDAV_KEY_PREFIX` to specify the key prefix of cache.

The webdav cache is compatible with:
Users can configure sccache to cache incremental build artifacts in a remote WebDAV service.
The following services all expose a WebDAV interface and can be used as a backend:

- [Ccache HTTP storage backend](https://ccache.dev/manual/4.7.4.html#_http_storage_backend)
- [Bazel Remote Caching](https://bazel.build/remote/caching).
- [Gradle Build Cache](https://docs.gradle.org/current/userguide/build_cache.html)

Users can set `SCCACHE_WEBDAV_ENDPOINT` to those services directly.
Set `SCCACHE_WEBDAV_ENDPOINT` to an appropriate webdav service endpoint to enable remote caching.
Set `SCCACHE_WEBDAV_KEY_PREFIX` to specify the key prefix of cache.

## Credentials

Sccache is able to load credentials from the following sources:

- Set `SCCACHE_WEBDAV_USERNAME`/`SCCACHE_WEBDAV_PASSWORD` to specify the username/password pair for basic authentication.
- Set `SCCACHE_WEBDAV_TOKEN` to specify the token value for bearer token authentication.
5 changes: 4 additions & 1 deletion src/cache/azure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@ use opendal::services::Azblob;

use crate::errors::*;

use super::http_client::set_user_agent;

pub struct AzureBlobCache;

impl AzureBlobCache {
pub fn build(connection_string: &str, container: &str, key_prefix: &str) -> Result<Operator> {
let builder = Azblob::from_connection_string(connection_string)?
.container(container)
.root(key_prefix);
.root(key_prefix)
.http_client(set_user_agent());

let op = Operator::new(builder)?
.layer(LoggingLayer::default())
Expand Down
1 change: 1 addition & 0 deletions src/cache/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ use crate::config::Config;
use crate::config::{self, CacheType};
use async_trait::async_trait;
use fs_err as fs;

use serde::{Deserialize, Serialize};
use std::fmt;
use std::io::{self, Cursor, Read, Seek, Write};
Expand Down
5 changes: 4 additions & 1 deletion src/cache/gcs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ use reqwest::Client;
use serde::Deserialize;
use url::Url;

use super::http_client::set_user_agent;

fn rw_to_scope(mode: CacheMode) -> &'static str {
match mode {
CacheMode::ReadOnly => "https://www.googleapis.com/auth/devstorage.read_only",
Expand All @@ -45,7 +47,8 @@ impl GCSCache {
let mut builder = Gcs::default()
.bucket(bucket)
.root(key_prefix)
.scope(rw_to_scope(rw_mode));
.scope(rw_to_scope(rw_mode))
.http_client(set_user_agent());

if let Some(service_account) = service_account {
builder = builder.service_account(service_account);
Expand Down
5 changes: 4 additions & 1 deletion src/cache/gha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use opendal::Operator;
use crate::errors::*;
use crate::VERSION;

use super::http_client::set_user_agent;

/// A cache that stores entries in GHA Cache Services.
pub struct GHACache;

Expand All @@ -30,7 +32,8 @@ impl GHACache {
//
// User customization is theoretically supported, but I decided
// to see the community feedback first.
.root("/sccache");
.root("/sccache")
.http_client(set_user_agent());

builder = if version.is_empty() {
builder.version(&format!("sccache-v{VERSION}"))
Expand Down
9 changes: 9 additions & 0 deletions src/cache/http_client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use opendal::raw::HttpClient;
use reqwest::ClientBuilder;

/// Set the user agent (helps with monitoring on the server side)
pub fn set_user_agent() -> HttpClient {
let user_agent = format!("{}/{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
let client = ClientBuilder::new().user_agent(user_agent).build().unwrap();
HttpClient::with(client)
}
10 changes: 10 additions & 0 deletions src/cache/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,14 @@ pub mod s3;
#[cfg(feature = "webdav")]
pub mod webdav;

#[cfg(any(
feature = "azure",
feature = "gcs",
feature = "gha",
feature = "s3",
feature = "webdav",
feature = "oss"
))]
pub(crate) mod http_client;

pub use crate::cache::cache::*;
7 changes: 6 additions & 1 deletion src/cache/oss.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ use opendal::Operator;

use crate::errors::*;

use super::http_client::set_user_agent;

pub struct OSSCache;

// Implement the Object Storage Service for Alibaba cloud
Expand All @@ -26,7 +28,10 @@ impl OSSCache {
endpoint: Option<&str>,
no_credentials: bool,
) -> Result<Operator> {
let mut builder = Oss::default().bucket(bucket).root(key_prefix);
let mut builder = Oss::default()
.bucket(bucket)
.root(key_prefix)
.http_client(set_user_agent());

if let Some(endpoint) = endpoint {
builder = builder.endpoint(endpoint);
Expand Down
11 changes: 2 additions & 9 deletions src/cache/s3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
// limitations under the License.

use opendal::layers::LoggingLayer;
use opendal::raw::HttpClient;
use opendal::services::S3;
use opendal::Operator;
use reqwest::ClientBuilder;

use crate::errors::*;

use super::http_client::set_user_agent;

pub struct S3Cache;

impl S3Cache {
Expand Down Expand Up @@ -67,13 +67,6 @@ impl S3Cache {
}
}

/// Set the user agent (helps with monitoring on the server side)
fn set_user_agent() -> HttpClient {
let user_agent = format!("{}/{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"));
let client = ClientBuilder::new().user_agent(user_agent).build().unwrap();
HttpClient::with(client)
}

/// Resolve given endpoint along with use_ssl settings.
fn endpoint_resolver(endpoint: &str, use_ssl: Option<bool>) -> Result<String> {
let endpoint_uri: http::Uri = endpoint
Expand Down
5 changes: 4 additions & 1 deletion src/cache/webdav.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ use opendal::layers::LoggingLayer;
use opendal::services::Webdav;
use opendal::Operator;

use super::http_client::set_user_agent;

/// A cache that stores entries in a Webdav.
pub struct WebdavCache;

Expand All @@ -32,7 +34,8 @@ impl WebdavCache {
.root(key_prefix)
.username(username.unwrap_or_default())
.password(password.unwrap_or_default())
.token(token.unwrap_or_default());
.token(token.unwrap_or_default())
.http_client(set_user_agent());

let op = Operator::new(builder)?
.layer(LoggingLayer::default())
Expand Down

0 comments on commit 5a65dc5

Please sign in to comment.