Skip to content

sansob/scconfig-rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

scconfig-rs

CI crates.io docs.rs License: MIT Rust 1.85+

scconfig-rs is a production-oriented Rust library for consuming Spring Cloud Config Server from non-Spring applications.

It is built for Rust services that need:

  • typed configuration loading from the standard Spring Environment endpoint
  • YAML and Java properties output from the alternative format endpoints
  • arbitrary file retrieval through the plain-text resource endpoint
  • binary-safe downloads for files such as .p12, .jks, or any other non-text asset
  • a clean async API with explicit request models, error types, and documentation

What This Library Supports

Spring Cloud Config endpoints

  • GET /{application}/{profile}
  • GET /{application}/{profile}/{label}
  • GET /{application}/{profile}.yml
  • GET /{application}/{profile}.yaml
  • GET /{application}/{profile}.properties
  • GET /{application}/{profile}/{label}.yml
  • GET /{application}/{profile}/{label}.yaml
  • GET /{application}/{profile}/{label}.properties
  • GET /{application}/{profile}/{label}/{path}
  • GET /{application}/{profile}/{path}?useDefaultLabel=true

Configuration format support

All file extensions are supported on the resource endpoint.

Built-in parsing and typed deserialization are available for:

  • JSON
  • YAML / YML
  • TOML
  • Java properties

Unknown extensions are still supported. The library returns them as UTF-8 text when possible, or as raw bytes otherwise.

Installation

From crates.io:

[dependencies]
scconfig-rs = "0.1.3"
serde = { version = "1", features = ["derive"] }
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }

Quick Start

use scconfig_rs::{EnvironmentRequest, SpringConfigClient};
use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct AppConfig {
    server: ServerConfig,
    features: FeatureFlags,
}

#[derive(Debug, Deserialize)]
struct ServerConfig {
    port: u16,
}

#[derive(Debug, Deserialize)]
struct FeatureFlags {
    enabled: bool,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = SpringConfigClient::builder("http://localhost:8888")?
        .default_label("main")
        .build()?;

    let request = EnvironmentRequest::new("inventory-service", ["dev"])?;
    let config: AppConfig = client.fetch_typed(&request).await?;

    println!("{config:#?}");
    Ok(())
}

Alternative Format Example

use scconfig_rs::{EnvironmentFormat, EnvironmentRequest, SpringConfigClient};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = SpringConfigClient::builder("http://localhost:8888")?.build()?;

    let request = EnvironmentRequest::new("inventory-service", ["dev"])?
        .label("main")
        .resolve_placeholders(true);

    let yaml = client
        .fetch_environment_as_text(&request, EnvironmentFormat::Yaml)
        .await?;

    println!("{yaml}");
    Ok(())
}

Arbitrary File Example

use scconfig_rs::{ResourceRequest, SpringConfigClient};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = SpringConfigClient::builder("http://localhost:8888")?
        .default_label("main")
        .build()?;

    let request = ResourceRequest::new("inventory-service", ["dev"], "nginx.conf")?;
    let resource = client.fetch_resource(&request).await?;

    println!("{}", resource.text()?);
    Ok(())
}

Binary File Example

use scconfig_rs::{ConfigDocument, ResourceRequest, SpringConfigClient};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = SpringConfigClient::builder("http://localhost:8888")?
        .default_label("main")
        .build()?;

    let request = ResourceRequest::new("inventory-service", ["prod"], "keystore.p12")?;
    let resource = client.fetch_resource(&request).await?;

    match resource.parse()? {
        ConfigDocument::Binary(bytes) => println!("downloaded {} bytes", bytes.len()),
        other => println!("received {:?}", other.format()),
    }

    Ok(())
}

Bootstrap From Environment

use scconfig_rs::BootstrapConfig;
use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct AppConfig {
    server: ServerConfig,
}

#[derive(Debug, Deserialize)]
struct ServerConfig {
    port: u16,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let bootstrap = BootstrapConfig::from_env()?;
    let config: AppConfig = bootstrap.load_typed().await?;

    println!("server.port={}", config.server.port);
    Ok(())
}

Supported bootstrap environment variables:

  • SPRING_CONFIG_SERVER_URL required
  • SPRING_APPLICATION_NAME required
  • SPRING_PROFILES_ACTIVE optional, defaults to default
  • SPRING_CONFIG_LABEL optional
  • SPRING_CONFIG_USERNAME optional
  • SPRING_CONFIG_PASSWORD optional
  • SPRING_CONFIG_BEARER_TOKEN optional
  • SPRING_CONFIG_INSECURE_TLS optional, defaults to false
  • SPRING_CONFIG_TIMEOUT_SECS optional

When bootstrapping against development Config Server endpoints that use private or self-signed certificates, set SPRING_CONFIG_INSECURE_TLS=true to disable both certificate and hostname validation for bootstrap requests only.

Development TLS

For local development or controlled smoke tests against self-signed or otherwise untrusted certificates, the builder can disable TLS validation explicitly:

use scconfig_rs::{EnvironmentRequest, SpringConfigClient};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = SpringConfigClient::builder("https://config.dev.example.org")?
        .danger_accept_invalid_tls(true)
        .build()?;

    let request = EnvironmentRequest::new("sample-api", ["dev"])?;
    let environment = client.fetch_environment(&request).await?;

    println!("{}", environment.name);
    Ok(())
}

Available builder methods:

  • danger_accept_invalid_certs(true) disables certificate validation
  • danger_accept_invalid_hostnames(true) disables hostname validation
  • danger_accept_invalid_tls(true) disables both

These options are unsafe for production and should only be used when you fully control the target environment.

Design Notes

  • The Environment endpoint is the preferred source when you want typed Rust structs.
  • The library preserves Spring property-source precedence. Earlier property sources win.
  • Labels containing / are automatically encoded as (_), matching Spring Cloud Config server rules.
  • Resource downloads always request application/octet-stream, which keeps binary retrieval safe without breaking text-based files.
  • Smart scalar coercion is enabled for typed binding. Strings such as "8080" and "true" can bind to numeric and boolean fields.

Error Handling

All fallible operations return scconfig_rs::Error.

Errors include:

  • invalid base URL or request input
  • transport failures
  • non-success HTTP responses with response body captured
  • invalid JSON, YAML, TOML, or Java properties content
  • UTF-8 decoding failures for text resources
  • typed binding failures

Included Examples

References

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages