nex_protocol/lib.rs
1//! An implementation of the [Nex protocol](nex://nightfall.city/nex/info/specification.txt)
2//! (`nex://`, TCP port 1900): an async client, a directory-serving server, a
3//! listing parser, and a small CLI.
4//!
5//! Nex is the minimal smolweb protocol, from nightfall.city, inspired by
6//! gopher and gemini. The whole wire format: the client connects and sends a
7//! path (which may be empty); the server responds with text or binary data
8//! and closes the connection. No TLS, no status codes, no headers, no state.
9//! Directory content is plain text where each line beginning `=> ` followed
10//! by a URL is a link; an empty path or a path ending in `/` is a directory;
11//! a document's display type follows its file extension, defaulting to plain
12//! text.
13//!
14//! This crate is independent and unaffiliated with the protocol's author.
15//! The crates.io name is qualified (`nex-protocol`) because the bare `nex`
16//! name is used by an unrelated project.
17//!
18//! ```no_run
19//! # async fn run() -> Result<(), nex_protocol::ClientError> {
20//! let body = nex_protocol::fetch("nex://nightfall.city/", &Default::default()).await?;
21//! println!("{}", String::from_utf8_lossy(&body));
22//! # Ok(()) }
23//! ```
24
25/// Nex's port ("Afterall, night falls at 7pm!").
26pub const NEX_PORT: u16 = 1900;
27
28mod client;
29mod listing;
30mod server;
31
32pub use client::{ClientError, FetchOptions, fetch, fetch_path};
33pub use listing::{ListingLine, parse_listing};
34pub use server::{FileHandler, Handler, Request, ServerConfig, serve};
35
36/// Whether a request path names a directory, per the spec: an empty path or
37/// one ending in `/`.
38pub fn is_directory_path(path: &str) -> bool {
39 path.is_empty() || path.ends_with('/')
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45
46 #[test]
47 fn directory_paths_per_spec() {
48 assert!(is_directory_path(""));
49 assert!(is_directory_path("/"));
50 assert!(is_directory_path("/nexlog/"));
51 assert!(!is_directory_path("/about.txt"));
52 }
53}