This is a server framework in Node.js for the Gemini Protocol based on Express.
TLS is a required part of the Gemini protocol. You can generate keys/certificates using
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365 -nodes -subj '/CN=localhost'
npm install gemini-server
const gemini = require('gemini-server');
const app = gemini(options)
where options is an object with the following properties:
cert: certificate file key: key file
This uses the express conventions, with the modification that the only method is on
.
app.on(path, handler);
or
app.on(path, ...middleware, handler);
Where handler
is a function which takes in a Request
and a Response
, and returns nothing.
And middleware
is 0 or more functions which take (req, res, next)
and return nothing.
A middleware function should call next()
to continue onto the next function for handling.
It should not call next
and should instead set the res
object if it should return.
NOTE: middleware looks similar to express middleware, but isn't compatible.
Examples of path:
/
for the root of the site
/foo
/foo/bar
/user/:name
*
Examples of handler:
function(req, res){ // do stuff }
general form
gemini.static(dir)
serve a directory
gemini.redirect(url)
redirect to a url
Examples of middleware:
gemini.requireInput(prompt="Input requested")
Proceed to handler only if user input is given, otherwise request input.
gemini.requireCert
Proceed to handler only if user certificate is provided, otherwise request a certificate.
NOTE: not yet implemented
gemini.static(dir)
will serve the files in a directory
app.on('/someFiles', gemini.static('src/files'));
gemini.redirect(url)
will redirect to the specified url
app.on('/redirectMe', gemini.redirect('/goingHereInstead'));
app.on('/redirectOther', gemini.redirect('http://example.com'));
The request object is passed to request handlers.
req.url
The URL object of the request
req.path
The path component of the url
req.query
The query component of the url (used for handling input)
req.cert
The certificate object, if the client sent one
req.fingerprint
The fingerprint of the certificate object, if the client sent one
The response object is passed to request handlers.
Methods on it can be chained, as each both returns and modifies the request object.
res.status(s)
Set the status of the response (see the gemini docs).
s is an int
res.getStatus()
return the current status associated with the response
res.file(filename)
serve the specified file
res.data(d)
or res.data(d, mimeType='text/plain')
Serve raw data as text, or as whatever format you want if you specify the mime type.
res.input(prompt, sensitive=false)
Prompt the client for input. Prompt should be a string. sensitive
defaults to false, and should be true if the input is sensitive.
res.certify(info="Please include a certificate.")
Request a certificate from the client. Useful for sessions or login. Optional info message.
res.redirect(url)
Redirect the client to the specified url.
const fs = require('fs');
const gemini = require('gemini-server');
const options = {
cert: fs.readFileSync('cert.pem'),
key: fs.readFileSync('key.pem')
};
//Create gemini instance with cert and key
const app = gemini(options);
//On a request to / serve a gemini file
//This automatically detects the mime type and sends that as a header
app.on('/', (req, res) => {
res.file('test.gemini');
});
//Request input from the user
app.on('/input', (req, res) => {
if(req.query){
res.data('you typed ' + req.query);
}else{
res.input('type something');
}
});
app.on('/testMiddlewear', gemini.requireInput("enter something"), (req, res) => {
res.data('thanks. you typed ' + req.query);
});
app.on('/other', (req, res) => {
res.data('welcome to the other page');
})
app.on('/test', gemini.static('./public/things'));
app.on('/redirectMe', gemini.redirect('/other'));
app.on('/cert', (req, res) => {
if(!req.fingerprint){
res.certify();
}else{
res.data('thanks for the cert');
}
})
app.on('/protected', gemini.requireCert, (req, res) => {
res.data('only clients with certificates can get here');
});
//start listening. Optionally specify port and callback
app.listen(() => {
console.log("Listening...");
});
- Documentation
- Utility functions
- Static directory serving
- automatic index file
- Static directory serving
- Certificates
- Middleware support
- Session helper functions
- Router
- View engines