nea-rs 0.4.0

A type-safe, sans-IO Rust client for Singapore NEA real-time weather and environmental APIs.
Documentation

Install

Add nea-rs and the satay-reqwest adapter (plus reqwest and tokio for the async example below):

cargo add nea-rs satay-reqwest reqwest
cargo add tokio --features macros,rt-multi-thread

These commands write the latest compatible versions into Cargo.toml for you. Recent reqwest releases use rustls by default, so HTTPS works without an extra TLS feature. If your app needs blocking clients, proxies, or other transport options, keep a direct reqwest dependency and enable features there. See Using other client backends and the Satay transport docs.

Example

Fetch the latest air temperature readings with reqwest and satay-reqwest:

use nea_rs::Api;
use satay_reqwest::ReqwestActionExt;
use satay_reqwest::reqwest::Client;
use std::env;
use std::error::Error;

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    let client = Client::new();
    let mut api = Api::new();
    if let Ok(key) = env::var("X_API_KEY") {
        api = api.x_api_key(key);
    }
    let response = api.air_temperature().send_with(&client).await?;
    println!("{response:#?}");
    Ok(())
}

From this repo, run the same logic as a binary example:

cargo run --example air_temperature

Optional: set X_API_KEY to your data.gov.sg API key. More runnable examples live under examples/.

Using other client backends

nea-rs is sans-IO: generated actions build http::Request<Vec<u8>> values and decode responses without performing IO. Pick the HTTP client that fits your application, or use the same boundary directly in tests, WASM, or custom transports.

See satay-rs for more details

ureq

cargo add nea-rs satay-ureq ureq
use nea_rs::Api;
use satay_ureq::UreqActionExt;
use satay_ureq::ureq;
use std::env;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    let mut api = Api::new();
    if let Ok(key) = env::var("X_API_KEY") {
        api = api.x_api_key(key);
    }

    let agent: ureq::Agent = ureq::Agent::config_builder()
        .http_status_as_error(false)
        .build()
        .into();

    let response = api.air_temperature().send_with(&agent)?;
    println!("{response:#?}");
    Ok(())
}

Configure the agent with http_status_as_error(false) so Satay can decode typed non-2xx responses instead of ureq treating them as transport errors.

reqwest (blocking)

Enable the blocking feature on both crates when you want a synchronous reqwest client:

cargo add nea-rs
cargo add satay-reqwest --features blocking
cargo add reqwest --features blocking
use nea_rs::Api;
use satay_reqwest::ReqwestBlockingActionExt;
use satay_reqwest::reqwest::blocking;
use std::env;
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
    let mut api = Api::new();
    if let Ok(key) = env::var("X_API_KEY") {
        api = api.x_api_key(key);
    }
    let response = api
        .air_temperature()
        .send_with(&blocking::Client::new())?;
    println!("{response:#?}");
    Ok(())
}

For more transport patterns (including WebSocket and custom adapters), see the Satay transport docs and the examples under satay-rs/examples/.

More examples

If you would like to see more examples, take a look at the examples folder

Security

Please see SECURITY.md for vulnerability reporting.

License

Licensed under either of:

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.