An open API service indexing awesome lists of open source software.

https://github.com/toomanybees/gemini_server

A Gemini protocol server
https://github.com/toomanybees/gemini_server

Last synced: about 1 year ago
JSON representation

A Gemini protocol server

Awesome Lists containing this project

README

          

# GeminiServer

A simple server for the Gemini protocol, with an API inspired by Sinatra.

## Usage

Use the built-in executable to serve the current directory.

```
$ gem install gemini_server
Successfully installed gemini_server-0.1.0
1 gem installed
$ gemini_server -h
Usage: gemini_server [options]
-p, --port PORT Port to listen on
--cert-path PATH Path to cert file
--key-path PATH Path to key file
--charset CHARSET Charset of text/* files
--lang LANG Language of text/* files
```

Or require the library to declare custom routes in Ruby.

```ruby
require "gemini_server"

server = GeminiServer.new

server.route("/greeting/:friend") do
if params["friend"] == "Gary"
gone "Gary and I aren't on speaking terms, sorry."
else
success "Hi there, #{params["friend"]}!"
end
end

server.route("/farewell") do
lang "pig-latin"
success "arewellfay!"
end

server.listen("0.0.0.0", 1965)
```

### Initialization options



cert*

A SSL certificate. Either a OpenSSL::X509::Certificate object, or a string.


cert_path*

Path to a SSL certificate file. Defaults to the value of the env variable GEMINI_CERT_PATH. Ignored if cert option is supplied.


key*

A SSL key. Either a OpenSSL::PKey object, or a string.


key_path*

Path to a private key file. Defaults to the value of the env variable GEMINI_KEY_PATH. Ignored if key option is supplied.

mime_type

Sets the default MIME type for successful responses. Defaults to text/gemini, or inferred by the name of the file being served.

charset

If set, includes the charset in the response's MIME type.

lang

If set, includes the language in the response's MIME type, if the MIME type is text/gemini. Per the Gemini spec, "Valid values for the "lang" parameter are comma-separated lists of one or more language tags as defined in RFC4646."

public_folder

Path to a location from which the server will serve static files. If not set, the server will not serve any static files.

views_folder

Path to the location of ERB templates. If not set, defaults to current directory.

*\* The option pairs `cert` and `cert_path`, and likewise `key` and `key_path`, are mutually exclusive, so they are technically optional. But per the Gemini spec, connections must use TLS, so it is a runtime error if neither option, nor either of the fallback env variables, are used.*

### Route handlers

To define a route handler, use `GeminiServer#route`:

```ruby
server = GeminiServer.new
server.route("/path/to/route/:variable") do
# route logic
end
```

The route method takes a [Mustermann](https://github.com/sinatra/mustermann) matcher string and a block.

Within the block, code has access to these methods:


params

Returns a hash of params parsed from the request path.

uri

Returns the full URI of the request.

mime_type(type)

Sets the MIME type of the response.

charset(ch)

Sets the charset of the response, overriding the server's default charset.

lang(l)

Sets the lang of the response, overriding the server's default lang.

erb(filename, locals: {})

Renders an ERB template located at filename, then sets status to success. MIME type is inferred by the template extension. The template will have access to any instance variables defined in the handler block, as well as any local variables passed in via the locals keyword param.

respond(code, meta, body=nil)

Sets the response code, meta, and optional body. It's probably easier to use erb method, or any of the convenience status methods in the next section.

### ERB templates

Using an ERB template automatically sets the status to `20` (success) because a success is the only type of response that can contain a body. It also tries to infer the MIME type from the template extension (excluding any `.erb`).

ERB rendering can define local variables, like in Sinatra:

```ruby
server.route("/hithere/:friend") do
erb "hithere.gmi", locals: { friend: params["friend"] }
end
```

```markdown

# Hi there!

Hi there, <%= friend %>.
```

ERB templates have the `params` hash available as a local var:

```ruby
server.route("/hithere/:friend") do
erb "hithere.gmi"
end
```

```markdown

# Hi there!

Hi there, <%= params["friend"] %>.
```

### Status methods

Each of these methods are available within a route handler block. Forgetting to use a status method defaults to a temporary failure. See [Gemini Specification](https://gemini.circumlunar.space/docs/specification.html) for an explanation of each response status.

* `input(prompt)`
* `sensitive_input(prompt)`
* `success(body, mime_type=nil)`
* `redirect_temporary(url)`
* `redirect_permanent(url)`
* `temporary_failure(explanation = "Temporary failure")`
* `server_unavailable(explanation = "Server unavailable")`
* `cgi_error(explanation = "CGI error")`
* `proxy_error(explanation = "Proxy error")`
* `slow_down(delay)`
* `permanent_failure(explanation = "Permanent failure")`
* `not_found(explanation = "Not found")`
* `gone(explanation = "Gone")`
* `proxy_request_refused(explanation = "Proxy request refused")`
* `bad_request(explanation = "Bad request")`
* `client_certificate_required(explanation = "Client certificate required")`
* `certificate_not_authorized(explanation = "Certificate not authorized")`
* `certificate_not_valid(explanation = "Certificate not valid")`

### Static file serving

To serve static files, set the initialization option `public_folder` to the location of your static files. If no route handlers match a request, the server will look for a static file to serve in that location instead. If the `public_folder` option is unset, no static files will be served.