-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathREADME.gmi
More file actions
154 lines (114 loc) · 6.64 KB
/
README.gmi
File metadata and controls
154 lines (114 loc) · 6.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# Chaykin: Linked Data over the Small Web
A Linked Data server in Rust that makes the Semantic Web available over the Small Web (or "smolweb") through a variety of protocols, including Gemini, Titan, Spartan, Nex, and NPS.
=> gemini://geminiprotocol.net/ Gemini Protocol
=> gemini://transjovian.org/titan/index Titan Protocol
=> gemini://spartan.mozz.us/ Spartan Protocol
=> https://nightfall.city/nex/info/ Nex Protocol
=> https://nightfall.city/nps/info/ NPS Protocol
More on this in docs/about.gmi
## Features
* Multi-Protocol Server: Custom Tokio+Rustls implementation handling Gemini and Titan natively over TLS, alongside plaintext Spartan and Nex/NPS TCP listeners. Enabled protocols and ports can be configured.
* Linked Data Store: Consumes RDF data in Turtle or RDF/XML via rio and holds them into an in-memory store.
* Gemtext Mapping: A proposed serialization of RDF to the hypertext format of Gemini, offering a recursively browsable knowledge graph. A condensed syntax, which groups predicates by property, is also supported. The parser and serializer are available as a separate crate. The specification is documented in the `docs` directory.
* External Proxy: Acts as a browser for all the Linked Open Data out there.
### External Proxy Features
* Encoded URLs in the request path are fetched via reqwest.
* Accept: text/turtle is used for Content Negotiation, with fallback to application/rdf+xml: this should cover most Linked Data services.
* Fetched RDF is parsed and rendered.
* Links to other external resources are re-encoded to point back to the proxy.
* You can provide a custom TLS certificate via the --cert flag.
## Setup & Running
Pretty standard stuff:
1. Dependencies: Rust/Cargo>1.78; Mainly tokio, rustls, rcgen, rio_turtle, rio_xml, rio_api, and reqwest.
2. Build:
```sh
cargo build
```
To build its Docker image:
```sh
docker build -t chaykin .
```
(the above will build an image with a self-signed certificate)
3. Run:
Either launch the chaykin executable in server/target, or
```sh
cargo run
```
The server listens on `127.0.0.1:1965` by default (for Gemini/Titan). Go there with your favourite Gemini client, like
=> gemini://skyjake.fi/lagrange/ Lagrange (simple, stylish, with support for Spartan and, recently, for Titan as well)
=> http://metaloupe.com/alhena/alhena.html Alhena (maybe not as fancy, but flexible and multi-protocol) [http]
To run it in a Docker container (mapping the Spartan port to one that doesn't require a super user):
```sh
docker run -p 1965:1965 -p 3300:300 -p 1900:1900 -p 1915:1915 chaykin
```
### Configuration
You can configure the server using command-line arguments:
```sh
cargo run -- --help
```
Arguments:
* --host: IP address to bind to (default: 127.0.0.1)
* --protocols: Comma-separated list of enabled protocols. cargo run -- list-protocols to see the list (default: all)
* --gemini-port: Port number for Gemini/Titan to bind to (default: 1965)
* --spartan-port: Port number for Spartan (default: 300)
* --nex-port: Port number for Nex (default: 1900)
* --nps-port: Port number for NPS (default: 1915)
* --disable-titan: Disable Titan (assumes Gemini is enabled)
* --disable-nps: Disable NPS (assumes Nex is enabled)
* --file: Path to an initial RDF data file (default: sample_data.ttl)
* --cert: Path to TLS certificate (PEM)
* --key: Path to TLS private key (PEM)
* --lang: Preferred language for language-tagged literals in Gemtext (e.g. en, fr, de)
If no certificate/key is provided, a self-signed certificate is generated for development.
## Usage & Verification
The homepage at `localhost` for each protocol provides helpful hints on where to go from there. To try each protocol straight away:
### 1. Gemini (Port 1965)
Proxy an external resource (e.g. Another World on Wikidata), which must be URL-encoded::
=> http://www.wikidata.org/entity/Q257469 Another World on Wikidata
```sh
printf '%s\r\n' "gemini://localhost/http%3A%2F%2Fwww.wikidata.org%2Fentity%2FQ257469" | openssl s_client -connect 127.0.0.1:1965 -quiet
```
Fetch a local resource:
```sh
printf '%s\r\n' "gemini://localhost/me" | openssl s_client -connect 127.0.0.1:1965 -quiet
```
### 2. Titan (Port 1965, Gemini must be enabled)
Upload a URI to inspect via Titan payload:
```sh
{ printf "titan://localhost/;size=38;mime=text/plain\r\nhttp://www.wikidata.org/entity/Q257469"; sleep 1; } | openssl s_client -crlf -verify_quiet -connect localhost:1965
```
### 3. Spartan (Port 300)
NOTE: Binding to ports below 1024 (like 300) may require root privileges on Linux/Unix systems.
Connect and pass the target URI as the Spartan payload:
```sh
printf "localhost /submit 38\r\nhttp://www.wikidata.org/entity/Q257469" | nc localhost 300
```
### 4. Nex (Port 1900)
Input the URL-encoded path to get a raw text breakdown:
```sh
echo -e "/http%3A%2F%2Fwww.wikidata.org%2Fentity%2FQ257469\n" | nc localhost 1900
```
### 5. NPS (Port 1915, Nex must be enabled)
The following opens a temporary file in your default editor (which you must have specified via the `$EDITOR` environment variable): enter your entity URI and save, and it will be sent to the NPS server.
```sh
T=`mktemp` && $EDITOR $T && echo "." >> $T && nc localhost 1915 < $T
```
## TODO
Lots and lots, but mainly:
* Move to RDF support via Sophia and access existing triple stores.
* SPARQL API? Only if it can be implemented without compromising the basic principles of the Small Web (we're probably going to need a SPARQL engine that supports cross-protocol equivalence).
* Gemtext: also render statements for subjects other than the one in the request URI.
* Gemtext: context-sensitive links in Gemtext: make them spartan:// or gemini:// depending on the client request.
* Gemtext: where possible, add support for language-specific labels per client request (we don't have the luxury of an Accept-Language header here: there is a "lang" parameter in Gemini but that is set by the server in the response).
* Gemtext: support for quads, blank node expansion, RDF-star.
* Protocols: minor contemporary ones]: Guppy, Molerat, Scorpion, Scroll etc. The rule of thumb would be that there must be actively developed user-facing clients, such as browsers, supporting that protocol.
* Protocols: Good old ones e.g. Gopher, Finger...
* Consider Chaykin extensions to existing Small Web servers in Rust, like Agate.
=> https://docs.rs/sophia/ Sophia, a Rust crate for RDF
=> https://dbohdan.com/archive/scorpion/zzo38computer.org/smallweb.txt/ Overview of Small Web protocols
=> https://github.com/mbrubeck/agate Agate, a Gemini server in Rust
## Rights
Copyright (c) 2023-2026 Alessandro Adamou.
Chaykin is licensed under either of Apache License, Version 2.0 or MIT license at your option.
=> LICENSE-APACHE Apache License, Version 2.0
=> LICENSE-MIT MIT license