11 releases (5 breaking)
new 0.6.2 | Oct 30, 2024 |
---|---|
0.6.1 | Oct 30, 2024 |
0.5.1 | Oct 30, 2024 |
0.4.0 | Oct 30, 2024 |
0.1.2 | Oct 29, 2024 |
#212 in Data structures
297 downloads per month
245KB
3.5K
SLoC
cdg_api
A simple Rust library to interact with the US Congress API.
Overview
cdg_api
provides a Rust interface for interacting with the US Congress API. It simplifies constructing API endpoints, building URLs with parameters, and retrieving legislative data. Whether fetching information about bills, members, amendments, or laws, cdg_api
offers a streamlined and type-safe approach to accessing this data.
Currently Unavailable Endpoints for Making Non-Manual Calls
The following API endpoints are currently unavailable for making calls, although response objects may be available for most, if not all, of them.
Manual calls can still be made to these endpoints using the Endpoints::Manual
variant. For more information, refer to the Using Endpoints::Manual
for Custom Endpoints example.
/committee-report
/committee-print
/committee-meeting
/hearing
/congressional-record
/daily-congressional-record
/bound-congressional-record
/house-communication
/house-requirement
/senate-communication
Fully Supported Endpoints
The library fully supports the following API endpoints:
/member
/bill
/law
/amendment
/committee
/nomination
/treaty
/summaries
/congress
Features
-
Modular Design: Organized into distinct modules for maintainability and scalability.
endpoints
: Enums and functions representing available API endpoints, includingEndpoints::Manual
for custom endpoints.url_builders
: Utility functions for constructing API URLs with query parameters.param_models
: Models and enums for different query parameters.response_models
: Data structures for API responses, including specific models and the versatileGenericResponse
.client
:CongressApiClient
struct for interacting with the API.request_handlers
: Functions for making HTTP requests and handling responses.
-
Convenient Request Utilities:
CongressApiClient
: Centralized client managing API keys, constructing URLs, making requests, and deserializing responses.
-
Flexible Response Handling:
GenericResponse
: A catch-all response model for endpoints without a specific response type or when the response model is unknown.parse_generic_response
: A method to parseGenericResponse
into a specific response model when the structure is known.
Installation
Add cdg_api
to your Cargo.toml
:
[dependencies]
cdg_api = "*"
Or use cargo
to add the dependency:
cargo add cdg_api
Getting Started
Setting Up Your API Key
Obtain an API key from the US Congress API. Provide it to the CongressApiClient
either via an environment variable or direct initialization:
-
Environment Variable:
export CDG_API_KEY="your_api_key_here"
-
Direct Initialization:
use cdg_api::CongressApiClient; let client = CongressApiClient::new(Some("your_api_key_here".to_string())).unwrap();
Note: Using environment variables is recommended to avoid hardcoding sensitive information.
Usage
Using CongressApiClient
CongressApiClient
allows you to interact with various API endpoints. Below are examples demonstrating how to fetch different types of data, including the new Endpoints::Manual
variant.
Example 1: Fetching Members
Fetch a list of current members of Congress and display their names, party affiliations, and states.
use cdg_api::CongressApiClient;
use cdg_api::endpoints::{Endpoints, NewEndpoint};
use cdg_api::param_models::{FormatType, MemberListParams};
use cdg_api::response_models::MembersResponse;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = CongressApiClient::new(None)?; // Use API key from environment
// Define parameters
let params = MemberListParams {
format: Some(FormatType::Json),
limit: Some(10),
current_member: Some(true),
..MemberListParams::default()
};
// Create the endpoint
let endpoint = Endpoints::new_member_list(params);
// Fetch the data
let response: MembersResponse = client.fetch(endpoint)?;
// Process the response
for member in response.members {
println!("{}, {}, {}\n", member.name, member.state, member.party_name);
}
Ok(())
}
Example 2: Fetching Bills
Fetch a list of bills and display their titles, types, and numbers.
use cdg_api::CongressApiClient;
use cdg_api::endpoints::{Endpoints, NewEndpoint};
use cdg_api::param_models::{FormatType, BillByTypeParams, BillType};
use cdg_api::response_models::BillsResponse;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let client = CongressApiClient::new(None)?;
// Define parameters
let params = BillByTypeParams {
format: Some(FormatType::Json),
limit: Some(10),
..BillByTypeParams::default()
};
// Create the endpoint
let endpoint = Endpoints::new_bill_by_type(118, BillType::Hr, params);
// Fetch the data
let response: BillsResponse = client.fetch(endpoint)?;
// Process the response
for bill in response.bills {
println!("{}, {}, {}\n", bill.title, bill.bill_type, bill.number);
}
Ok(())
}
Example 3: Using GenericResponse
with parse_generic_response
Fetch detailed information about a specific bill using GenericResponse
and parse it into a specific response model.
use cdg_api::CongressApiClient;
use cdg_api::endpoints::{Endpoints, NewEndpoint};
use cdg_api::param_models::{BillDetailsParams, BillType, FormatType};
use cdg_api::response_models::{BillDetailsResponse, GenericResponse};
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
let client = CongressApiClient::new(None)?; // Use API key from environment
// Define parameters for bill details
let params = BillDetailsParams {
format: Some(FormatType::Json),
..BillDetailsParams::default()
};
// Specify the bill to fetch (e.g., H.R. 1234 from the 118th Congress)
let endpoint = Endpoints::new_bill_details(118, BillType::Hr, 148, params);
// Fetch the data as GenericResponse
let response: GenericResponse = client.fetch(endpoint)?;
// Parse the response as BillDetailsResponse
let bill_details: BillDetailsResponse = response.parse_generic_response()?;
let bill = bill_details.bill;
println!("Bill: {}", bill.number);
println!("Title: {}", bill.title);
println!("Summary: {:#?}", bill.summaries);
Ok(())
}
Example 4: Using Endpoints::Manual
for Custom Endpoints
Fetch data from a manually specified endpoint string using Endpoints::Manual
.
use cdg_api::CongressApiClient;
use cdg_api::endpoints::{Endpoints, NewEndpoint};
use cdg_api::response_models::{DailyCongressionalRecordResponse, GenericResponse};
use std::error::Error;
fn main() -> Result<(), Box<dyn Error>> {
let client = CongressApiClient::new(None)?; // Use API key from environment
// Manually specify the endpoint string
let endpoint = Endpoints::new_manual("/daily-congressional-record?format=json".to_string());
// Fetch the data as GenericResponse
let response: GenericResponse = client.fetch(endpoint)?;
// Parse the response into DailyCongressionalRecordResponse
match response.parse_generic_response::<DailyCongressionalRecordResponse>() {
Ok(daily_record) => {
let record = daily_record.daily_congressional_record;
for issue in record {
println!("Issue Number: {}", issue.issue_number);
println!("Volume Number: {}", issue.volume_number);
println!("Issue Date: {}", issue.issue_date);
println!("Congress: {}", issue.congress);
println!("Session Number: {}", issue.session_number);
println!("URL: {}", issue.url);
println!("Sections:");
if let Some(full) = issue.full_issue {
println!("Full Record: {:#?}", full);
}
println!("----------------------------");
}
},
Err(e) => {
println!("Failed to parse response: {}", e);
}
}
Ok(())
}
Using GenericResponse
for Manual Endpoints
When using Endpoints::Manual
, GenericResponse
allows you to handle responses dynamically without predefined response models. You can parse the response into any specific model if you know its structure, enhancing flexibility.
Modules
endpoints
: Enums and functions representing available API endpoints, includingEndpoints::Manual
for custom endpoint strings.url_builders
: Helper functions for constructing complete API URLs with query parameters.param_models
: Data models and enums for API query parameters, ensuring type-safe requests.response_models
: Data structures for API responses, including specific models andGenericResponse
.client
:CongressApiClient
struct and methods for interacting with the API.request_handlers
: Functions for making HTTP requests and handling responses, supportingreqwest
andcurl+jq
.
Error Handling
The library defines a custom error type ApiClientError
to handle various error scenarios, including HTTP errors, URL construction issues, deserialization failures, and environment variable access problems. The fetch
method returns Result<T, ApiClientError>
, allowing for precise error handling.
Error Variants
ApiClientError::Http
: HTTP-related errors, including network issues and non-success status codes.ApiClientError::Deserialization
: Errors during deserializing the API response.ApiClientError::Url
: Errors constructing the API URL.ApiClientError::EnvVar
: Missing API key in environment variables.
Other Projects
loc_api
: A Rust library for interacting with the Library of Congress API.
License
This project is licensed under the terms of the MIT license.
Repository
Dependencies
~4–18MB
~222K SLoC