Seren Gemini Server
The old source code from when Seren had a dedicated Gemini server running on a Linode:
const tls = require('tls')
const fs = require('fs')
const path = require('path')
const rootDirectory = 'gmi/'
const fileExists = async path => !!(await fs.promises.stat(path).catch(e => false))
console.log('Seren Server')
var options = {
key: fs.readFileSync("seren_server_key.pem"),
cert: fs.readFileSync("seren_server_cert.pem"),
rejectUnauthorized: true
}
var server = tls.createServer(options, function(socket) {
socket.on('data', (buf) => {
let url = new URL(buf.toString())
console.log('Gemini request: ' + url)
var requestPath = url.pathname.substring(1)
if(requestPath.length == 0) requestPath = "index.gmi"
if(requestPath.endsWith("/")) requestPath = path.join(requestPath, "index.gmi")
if(requestPath.indexOf('\0') !== -1) {
errorResponse(socket, 59, 'Poison null byte found: ' + requestPath)
return
}
var entityPath = path.join(rootDirectory, requestPath)
if (entityPath.indexOf(rootDirectory) !== 0) {
errorResponse(socket, 59, 'Unsafe path found: ' + entityPath)
return
}
serveFile(socket, entityPath)
})
socket.on('error', console.error)
socket.on('end', () => {
console.log('Client closed connection')
})
});
async function serveFile(socket, file){
const exists = await fileExists(file)
if(exists){
const content = await fs.promises.readFile(file);
let mime
if(file.endsWith('.gmi')){
mime = 'text/gemini'
}else if(file.endsWith('.png')) {
mime = 'image/png'
}else if(file.endsWith('.jpg') || file.endsWith('.jpeg')) {
mime = 'image/jpeg'
}else if(file.endsWith('.png')) {
mime = 'image/png'
}else if(file.endsWith('.svg')) {
mime = 'image/svg+xml'
}else if(file.endsWith('.mp3')) {
mime = 'audio/mpeg'
}else if(file.endsWith('.xml')){
mime = 'application/xml'
}else if(file.endsWith('.apk')){
mime = 'application/vnd.android.package-archive'
}else{
errorResponse(client, 59, '' + file + ' unrecognised file type')
return
}
socket.write('20 ' + mime + '\r\n')
socket.write(content)
socket.end()
}else{
errorResponse(socket, 51, 'Not found: ' + file)
}
}
function errorResponse(socket, code, message){
socket.write('' + code + message + '\r\n')
socket.end()
}
server.listen(1965)