Coder Social home page Coder Social logo

sternenseemann / spacecookie Goto Github PK

View Code? Open in Web Editor NEW
46.0 3.0 5.0 309 KB

gopher library & server written in Haskell

Home Page: https://sternenseemann.github.io/spacecookie/

License: GNU General Public License v3.0

Haskell 96.52% Nix 3.48%
gopher gopher-server haskell gopher-protocol server systemd network

spacecookie's Introduction

spacecookie

Haskell gopher server daemon and library.

Features

  • implements RFC1436
  • optionally supports common protocol extensions:
  • supports gophermaps (see below)
  • supports systemd socket activation
  • provides a library for custom gopher applications (see documentation)

Non-Features

spacecookie intentionally does not support:

  • HTTP, Gemini: Multi protocol support is a non-goal for spacecookie. For HTTP you can proxy pretty easily, however.
  • Search: Gopher supports search transactions, but the spacecookie daemon doesn't offer the possibility to add a search engine to a gopherspace. It is however entirely possible to implement an index search server using the spacecookie library

Installation

Documentation

Configuration

spacecookie is configured via a JSON configuration file. All available options are documented in spacecookie.json(5). This repository also contains an example configuration file in etc/spacecookie.json.

Running

After you've created your config file just start spacecookie like this:

spacecookie /path/to/spacecookie.json

spacecookie runs as a simple process and doesn't fork or write a PID file. Therefore any supervisor (systemd, daemontools, ...) can be used to run it as a daemon.

With systemd

spacecookie supports systemd socket activation. To set it up you'll need to install spacecookie.service and spacecookie.socket like so:

cp ./etc/spacecookie.{service,socket} /etc/systemd/system/
systemctl daemon-reload
systemctl enable spacecookie.socket
systemctl start  spacecookie.socket
systemctl start  spacecookie.service # optional, started by the socket automatically if needed

Of course make sure that all the used paths are correct!

How the systemd integration works is explained in spacecookie(1).

On NixOS

NixOS provides a service module for spacecookie: services.spacecookie. Setting up spacecookie is as simple as adding the following line to your configuration.nix:

services.spacecookie.enable = true;

For all available options, refer to the NixOS manual:

Adding Content

spacecookie acts as a simple file server, only excluding files or directories that start with a dot. It generates gopher menus automatically, but you can also use custom ones by adding a gophermap file.

spacecookie checks for .gophermap in every directory it serves and, if present, uses the menu specified in there.

Such a file looks like this:

You can just start writing text that
will be displayed by the gopher client
without a link to a file. Empty lines are
also possible.

1Menu Entry for a directory full of funny stuff	/funny
IFunny Image	/funny.jpg
gcat gif	/cat.gif
0about me	/about.txt
1Floodgap's gopher server	/	gopher.floodgap.com	70

As you can see, it largely works like the actual gopher menu a server will send to clients, but allows to omit redundant information and to insert lines that are purely informational and not associated with a file. spacecookie.gophermap(5) explains syntax and semantics in more detail.

The format is compatible with the ones supported by Bucktooth and pygopherd. If you notice any incompatibilities, please open an issue.

Portability

spacecookie is regularly tested on GNU/Linux via CI, but should also work on other Unix-like operating systems. Most portability problems arise due to haskell-socket which is for example known not to work on OpenBSD.

Windows support would be possible, but could be tricky as gopher expects Unix-style directory separators in paths. I personally don't want to invest time into it, but would accept patches adding Windows support.

spacecookie's People

Contributors

sternenseemann avatar verbosemode avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

spacecookie's Issues

CGI Support

Optional CGI support could be interesting. Could starting point could be looking at how geomyidae (gopher://bitreich.org/1/scm/geomyidae/) passes info to CGI scripts. Also should check how/whether other server implementations do CGI.

Systemd Support

Add systemd support for the server executable (socket activation and notify service type).

Work in Progress, see the systemd-support branch

Current Progress:

  • Write rudimentary Systemd-Support using a patched version of the systemd haskell package
  • Further testing
  • Either rewrite the integration or patch the systemd haskell package, so spacecookie does not have to depend on network
    • Wait for feedback on the PR
  • Update documentation and suggested systemd .service files.
  • Test on non-systemd and non-linux (see #9) systems
  • Get a NixOS service into nixpkgs

This is the new feature I am planning for 0.2.1.0.

More thorough filetypeMap?

I was poking through your code and noticed the filetypeMap.

Would you like a more thorough utility for such? I have a half-baked, but functional utility filesig which provides a mapping for a ton of files based off of file signatures (and I think even file extensions? although hit's been a while). I can update this library if you are interested in it.

Let users configure custom file type mappings

We have a map like this:

M.Map FilePath GopherFileType

The configuration option could look like this, allowing to override the mapping:

{
  "file-types": {
    "apng": "I"
  }
}

Also the default fallback should be configurable (currently File).

Configuration file format overhaul

JSON is not a configuration file format. I'll keep supporting it in the future, since it is convenient for the NixOS module.

As we keep JSON, we should maybe look into something aeson based, maybe YAML? Otherwies toml or ini seems fine.

spacecookie closes connection before curl can read everything sometimes

To reproduce curl -vv -s -f an gopher url for spacecookie a few times, eventually you will have curl failing with 56 similar to this:

…
The file type characters are defined in [RFC1436](https://tools.ietf.org/html/rfc1436#page-10).
* Recv failure: Connection reset by peer
* Closing connection 0
Detailed documentation on the gophermap format [can be found here](./docs/gophermap-pygo⏎         

Pass request context to handler

Would break library interface unfortunately, but having something like

data GopherRequest
  = GopherRequest
  { grSelector :: ByteString
  , grAddress :: (Word16, Word16, Word16, Word16, Word16, Word16, Word16, Word16)  -- ipv6 address
  }

Could be very useful for applications which want to kind of differentiate different users.

Improve Logging

  • Allow it to be disabled when using the library
  • Allow Configuration of log format (disable timestamp, more?)
  • Make less verbose, i. e. only one log line per successful connection.
  • Option to hide IP addresses

Reverse proxy

On my server I have two different gopherholes I want to expose to the world. Currently they run on different ports. I'd like to be able to configure spacecookie to act as a reverse proxy to sort incoming gopher requests to a configured gopherhole. For example, a simple configuration could be detecting the base directory of "forum/" in the selector and forwarding selector to a configured gopherhole and sending its response back.

I suppose all I really want is the ability to have spacecookie map certain base directories to certain gopherholes, and everything can be communicated via a consistent port.

Would you like me to work on a PR for this concept? Would you like to implement?

I'm posting using my phone and sorry if my English is poor.

Provide TLS-enabling configuration with stunnel or similar

Recently it seems to be a trend to TLS-enable gopher servers and even some gopher clients seem to support TLS. I don't think it's a good idea to support it in spacecookie, since it is a non-standard feature, but it seems like a good idea to figure out, how TLS typically is set up for gopher and provide an stunnel (?) based example configuration for TLS with spacecookie.

The best way to set up an encrypted spacecookie remains to use a hidden service (but we should close #13 for that).

Serve non dot .gophermap files as directory responses

Sometimes I want to have multiple gophermaps per directory and I want to use the .gophermap parsing behavior. I noticed I have to use "manually" written gophermaps if I want to have multiple gophermaps in one directory. The solution is to adhere to the RFC (I forget the number) convention on URIs in gopherspace, where /1/ in the beginning/as the prefix of the selector, for instance, denotes that the selector targets a menu and should be interpreted as such.

My specific use case: In burrow I want to provide an index per phlog tag in separate menus, and I don't like that I would have to create a directory and a .gophermap for each tag index in order to take advantage of the .gophermap parsing behavior.

Bind only to a link local address

This behavior can already be achieved when using a systemd based setup, but we should probably support it also in a systemd-less scenario. Binding to a specified address could be how to solve it, but link local is the most important in case you want to proxy spacecookie somehow or point a TOR hidden service to it without leaking the gopher space on the regular address.

Improved Error Handling

A lot of the times a error occurs, the default exception is thrown.

  • Premature disconnect
  • File read errors (config file)

Allow user logging

The current log system is alright, but doesn't allow the user to log anything. I'm also kind of unhappy that we always have a TimeFastLogger although it may not be used (glcTimed = False).

I think a good way forward is to rework logging again completely and let the user set an IO action for logging. Additionally I think the LogMessage sum type needs to be simplified somehow, without sacrificing the ability to hide private data.

This should be done before 0.3.0.0 since I don't want to break the API twice in a row.

build fails with aeson-2.0

spacecookie                    > /tmp/stack-e91b7c5fd4ba17cb/spacecookie-1.0.0.0/server/Network/Spacecookie/Config.hs:28:28: error:
spacecookie                    >     • Couldn't match expected type ‘Key’ with actual type ‘Text’
spacecookie                    >     • In the second argument of ‘(.:?)’, namely ‘x’
spacecookie                    >       In the expression: v .:? x
spacecookie                    >       In an equation for ‘maybePath’: maybePath [x] v = v .:? x
spacecookie                    >    |
spacecookie                    > 28 | maybePath [x]    v = v .:? x
spacecookie                    >    |                            ^
spacecookie                    > 
spacecookie                    > /tmp/stack-e91b7c5fd4ba17cb/spacecookie-1.0.0.0/server/Network/Spacecookie/Config.hs:29:28: error:
spacecookie                    >     • Couldn't match expected type ‘Key’ with actual type ‘Text’
spacecookie                    >     • In the second argument of ‘(.:?)’, namely ‘x’
spacecookie                    >       In the first argument of ‘(>>=)’, namely ‘v .:? x’
spacecookie                    >       In the expression: v .:? x >>= fmap join . traverse (maybePath xs)
spacecookie                    >    |
spacecookie                    > 29 | maybePath (x:xs) v = v .:? x >>= fmap join . traverse (maybePath xs)
spacecookie                    >    |                            ^

Mode for no config file/all defaults for testing

Feature request.

It would be great if I could arbitrarily launch spacecookie when I build random gopherholes as a test and I just want to see what the product looks like after I build it, without having to create a config file to test locally.

I want to, for testing purposes, be able to use spacecookie without specifying a config file.

Fix exception handling

Currently all exceptions except IOExceptions are kind of ignored. This should be fixed and handled properly™. Probably removing MonadError altogether would do the trick.

Most notably it is not possible to handle SocketExceptions with MonadError.

Port to network >= 3.1.1.0

I believe network should now offer everything we need and socket has become unmaintained, dropping out of Stackage Nightly recently.

Improve systemd socket activation UX

The bad thing currently is that the configuration has to match in two places: a) the spacecookie.socket file and b) the spacecookie.json config. This can be improved by:

  • Learning more about the socket from systemd if possible without a direct dependency?
  • Logging a warning if something is strange about the socket, i. e. addresses not matching.

Tests

  • Test build of example program, sanity check
  • integration tests
  • Unit tests for library
    • gophermaps
    • gophermap parse failures
    • path sanitization
    • file type detection
    • ...
  • Test config parsing for server

Support relative paths in gophermaps

       selector
              The  selector  is  the  name  of  the file on the server.  If it
              begins with a slash, it is an absolute path;  otherwise,  it  is
              interpreted relative to the directory that the gophermap file is
              in.  If no selector is specified, the description is  also  used
              as the selector.

spacecookie currently interprets relative selectors wrong.

User documentation improvements

Probably best option is to add manpages:

  • spacecookie(1) Usage, Configuration, License, …
  • spacecookie.json(5)
  • spacecookie-gophermap(5)
  • Redo README.md

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.