data-gov-ckan 0.4.0

Client for Data.Gov CKAN
Documentation
# data-gov-ckan

Async Rust client for CKAN APIs. Typed models, ergonomic helpers, works with any CKAN-compatible portal.

[![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](../LICENSE)

> ## โš ๏ธ data.gov no longer uses CKAN
>
> As of 2026 the data.gov catalog is served by a purpose-built
> [Catalog API]https://resources.data.gov/catalog-api/ โ€” see the
> [`data-gov-catalog`]../data-gov-catalog/ crate in this workspace.
>
> **This crate is retained, not deprecated.** CKAN still powers many other
> open-data portals (European, state, municipal, and university instances) and
> the client works unchanged against any compliant CKAN deployment โ€” just
> point `Configuration::base_path` at your target host.
>
> **Maintenance status.** Active workspace development now focuses on the
> Catalog API. `data-gov-ckan` will continue to receive bug fixes and security
> patches, but new features are unlikely unless a contributor steps up.
> Issues and PRs are welcome.

## Requirements

- Rust **1.90+** (Rust 2024 edition)
- Cargo and git

```bash
rustup toolchain install stable
rustup default stable
```

## Install / depend

Use the published crate from crates.io:

```toml
[dependencies]
data-gov-ckan = "0.4"
tokio = { version = "1", features = ["full"] }
```

Working inside this repository? Point to the local path instead: `data-gov-ckan = { path = "../data-gov-ckan" }`. If you need the bleeding edge between releases, swap in the git dependency form: `data-gov-ckan = { git = "https://github.com/dspadea/data-gov-rs", package = "data-gov-ckan" }`.

## Highlights

- ๐Ÿ” Coverage of the common CKAN `action/*` endpoints (`package_search`,
  `package_show`, `organization_list`, `group_list`, `tag_list`, `user_list`,
  and the matching autocomplete helpers)
- โœ… Strongly typed models generated from the official OpenAPI spec
- ๐ŸŒ Configurable base URL, authentication, and user-agent handling
- โš™๏ธ Async support via `reqwest` + `tokio`
- ๐Ÿงช Wiremock-based unit tests plus optional live integration tests

## Quick start

```rust
use data_gov_ckan::{CkanClient, Configuration};
use std::sync::Arc;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = CkanClient::new(Arc::new(Configuration::default()));

    let results = client.package_search(Some("climate"), Some(10), Some(0), None).await?;
    println!("Found {} datasets", results.count.unwrap_or(0));

    if let Some(datasets) = results.results {
        for dataset in datasets.iter().take(3) {
            let title = dataset.title.as_deref().unwrap_or(&dataset.name);
            println!("โ€ข {title}");
        }
    }

    Ok(())
}
```

### Custom configuration & auth

```rust
use data_gov_ckan::{ApiKey, CkanClient, Configuration};
use std::sync::Arc;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let config = Configuration {
        base_path: "https://demo.ckan.org/api/3".to_string(),
        api_key: Some(ApiKey {
            prefix: None,
            key: "your-api-key".to_string(),
        }),
        ..Configuration::default()
    };

    let client = CkanClient::new(Arc::new(config));
    let dataset = client.package_show("example-dataset").await?;
    println!("Dataset: {}", dataset.title.as_deref().unwrap_or(&dataset.name));

    Ok(())
}
```

Filtering with Solr-style query strings:

```rust
let fq = r#"organization:"gsa-gov" AND res_format:"CSV""#;
let results = client.package_search(Some("budget"), Some(20), Some(0), Some(fq)).await?;
```

### Solr query syntax

The `q` (full-text) and `fq` (filter query) parameters are passed directly to
CKAN's Solr-backed `package_search` endpoint. Typical patterns:

- Wildcards: `q=climat*`
- Phrase search: `q="air quality"`
- Fielded filters: `fq=organization:epa-gov AND res_format:CSV`
- Range queries: `fq=metadata_modified:[2020-01-01T00:00:00Z TO NOW]`

Use `fq` for structured filtering and `q` for free-text searches. When building
`fq` strings programmatically, quote values containing spaces to ensure correct
Solr parsing.

## API surface

Core methods include `package_search`, `package_show`, `organization_list`, `group_list`, `tag_list`, and `user_list`. Autocomplete helpers cover datasets, organisations, groups, tags, and users. Errors are surfaced through the `CkanError` enum with variants for request, parse, and API failures.

## Development

```bash
git clone https://github.com/dspadea/data-gov-rs.git
cd data-gov-rs/data-gov-ckan
cargo build
cargo test        # unit + wiremock tests; live integration tests are #[ignore]'d
cargo run --example debug_search
cargo run --example raw_response
```

Live-network integration tests are marked `#[ignore]` and target a CKAN
instance you configure (legacy data.gov fixtures are kept for historical
reference). Run them explicitly with `cargo test -- --ignored`.

## Authentication options

- API keys: set `Configuration.api_key = Some(ApiKey { .. })`
- Basic auth: populate `Configuration.basic_auth`
- Custom headers: configure the inner `reqwest::Client` before passing the configuration into `CkanClient`

Reuse the same `CkanClient` for multiple requests to benefit from connection pooling. Combine async calls with `tokio::try_join!` for improved throughput.


## Disclaimer & license

This is an independent project and is not affiliated with data.gov or any government agency. For authoritative information, refer to the official [data.gov](https://www.data.gov/) portal.

Licensed under the [Apache License 2.0](LICENSE).