nntp-rs
High-performance async NNTP client library for Rust with compression and connection pooling.
Scope: This library is designed for reading and downloading from Usenet/NNTP servers (client-to-server). Server-to-server peering and article posting are out of scope.
Features
- Async/await - Built on Tokio for high-performance async I/O
- TLS/SSL - Secure connections via rustls (implicit TLS on port 563)
- Compression - RFC 8054 COMPRESS DEFLATE + XFEATURE COMPRESS GZIP with automatic fallback (50-80% bandwidth reduction)
- Connection pooling - bb8-based pool with configurable size
- Retry logic - Exponential backoff with jitter to prevent thundering herd
- Binary support - yEnc decoding, NZB parsing, PAR2 verification
- Zero unsafe code - Pure safe Rust
- Production-hardened - Strict clippy linting, comprehensive error handling, well-structured modules
Code Quality
This library maintains high standards for production readiness:
- Zero unsafe code - All safe Rust, verified with
#![forbid(unsafe_code)] - Strict linting - Enforced clippy rules including
#![deny(clippy::unwrap_used)]for production code - Comprehensive error handling - All production code uses
Resulttypes with descriptive errors viathiserror - Modular architecture - Large modules split into focused submodules for maintainability
src/client/- 13 focused modules (connection, I/O, auth, commands)src/article/- Parsing, building, and validation separatedsrc/par2/- Parsing and verification logic isolated
- Excellent test coverage - 1,400+ tests across all modules
- Well-documented - 2,900+ doc comments covering all public APIs
Installation
Add to your Cargo.toml:
[]
= "0.1"
Quick Start
Single Connection
use ;
use Arc;
async
Connection Pool (Recommended for high throughput)
use ;
async
Compression
This library supports two compression modes with automatic fallback:
- RFC 8054 COMPRESS DEFLATE - Full bidirectional session compression (best)
- XFEATURE COMPRESS GZIP - Headers-only compression (wider compatibility)
Compression is automatically negotiated when using the connection pool, or can be manually enabled:
let enabled = client.try_enable_compression.await?;
if enabled
TLS/Security
nntp-rs uses modern TLS with strong security defaults:
- TLS 1.3 preferred, TLS 1.2 supported (TLS 1.0/1.1 disabled per RFC 8996)
- Strong cipher suites with forward secrecy (ECDHE) and authenticated encryption (GCM/Poly1305)
- Certificate validation using Mozilla's CA bundle (webpki-roots)
- Hostname verification with SNI support
Configuration
// Secure connection (recommended)
let config = tls;
// Plaintext connection (not recommended)
let config = plain;
Article Parsing (RFC 5536)
nntp-rs provides comprehensive article parsing with validation and international character support:
Features
- Header parsing - All RFC 5536 required and optional headers
- Validation - Message-ID, newsgroup names, and date format validation
- RFC 2047 encoded words - Automatic decoding of international characters in headers (UTF-8, ISO-8859-1, Windows-1252)
- MIME detection - Content-Type parsing and multipart detection
- Path parsing - Extract server routing information
Example
use ;
// Parse an article
let article = parse?;
// Access headers
println!;
println!; // RFC 2047 encoded words automatically decoded
println!;
// Validate article format
let config = strict;
article.headers.validate?;
// Check MIME type
if article.is_mime
// Parse path
let servers = article.headers.parse_path;
println!;
RFC Compliance
| RFC | Title | Status | Test Coverage |
|---|---|---|---|
| RFC 3977 | NNTP Core Protocol | Reader commands | ~600 tests |
| RFC 4642 | TLS with NNTP | Implicit TLS only | Verified |
| RFC 4643 | Authentication | USER/PASS + SASL PLAIN | ~100 tests |
| RFC 5536 | Netnews Article Format | Complete | ~156 tests |
| RFC 8054 | Compression | Complete | ~30 tests |
| RFC 8143 | TLS Best Practices | Compliant | Verified |
| RFC 7525 | BCP 195 TLS | Compliant | Verified |
| RFC 8996 | Deprecate TLS 1.0/1.1 | Compliant | Verified |
| RFC 4644 | Streaming Feeds | Out of scope | - |
Total test coverage: ~1,400 tests (>95% real behavioral tests)
Note: RFC 4644 (streaming feeds) is for server-to-server peering and is out of scope for this client library.
What's Tested
- Core NNTP commands: GROUP, ARTICLE, HEAD, BODY, STAT, XOVER/OVER
- Authentication flows: AUTHINFO USER/PASS, SASL PLAIN
- Compression: COMPRESS DEFLATE, XFEATURE COMPRESS GZIP
- Response parsing and multi-line handling
- Connection pooling and retry logic
- Article format parsing (RFC 5536):
- Header parsing and validation (Message-ID, newsgroup names, dates)
- RFC 2047 encoded words (international characters in headers)
- MIME detection and Content-Type parsing
- Path header parsing
- yEnc decoding with CRC32 verification
- NZB parsing and segment ordering
- PAR2 file parsing and checksum extraction
Current Limitations
Out of Scope (by design)
This library focuses on client-to-server reading/downloading. The following server-to-server and posting features are intentionally not implemented:
- POST/IHAVE - Article posting (not a posting client)
- RFC 4644 - Streaming feeds (CHECK/TAKETHIS) for server-to-server peering
- yEnc encoding - Only decoding; not designed for uploading binaries
Not Yet Implemented
- STARTTLS - Only implicit TLS (port 563) is supported; STARTTLS upgrade not implemented
- RFC 6048 - Extended LIST commands
- PAR2 repair - Only verification; Reed-Solomon recovery not implemented
- Multi-server failover - Single server only
- Rate limiting - No bandwidth throttling
- Header caching - No persistent cache
API Reference
NntpClient
connect(config)- Connect to NNTP serverauthenticate()- Authenticate with username/passwordauthenticate_sasl(mechanism)- SASL authenticationtry_enable_compression()- Enable compression (returns true if successful)select_group(name)- Select a newsgroupfetch_article(id)- Fetch full articlefetch_head(id)- Fetch article headers onlyfetch_body(id)- Fetch article body onlyfetch_xover(range)- Fetch article overview dataquit()- Close connection gracefully
NntpPool
new(config, max_size)- Create pool with default retry configwith_retry_config(config, max_size, retry_config)- Create pool with custom retryget()- Get connection with automatic retryget_no_retry()- Get connection without retrystate()- Get pool statistics
License
MIT License - see LICENSE file for details.