The Gopher Protocol in Brief
Tags: gopher, protocol, sockets
Published: 2019-03-08 22:57:45

---
title: The Gopher Protocol in Brief
published: true
description: A brief explanation of how the Gopher protocol works.
tags: gopher, protocol, sockets
cover_image: https://thepracticaldev.s3.amazonaws.com/i/x03ovz6fl5k16nvm1w74.jpg
---

Gopher is a protocol for fetching information that dates back to 1993. It's often regarded as a predecessor of sorts to the HTTP protocol that serves as the backbone of the Web as we know it today, however its simplicity and structure gives it a lot of worth.

Gopher is a very simple protocol to work with, and one lunch break could net you basically all you need to know about the protocol. Let me give a rundown.

I'll use `(NL)` in this article to refer to a newline. According to RFC 1436, this is the equivalent of `\r\n`, or a Windows/DOS newline. Note that Gopher selectors use tab characters (`\t`) instead of spaces to separate fields, so you'll need to replace them with tabs in the examples.

# Request
The client firsts make a connection to a remote host (a quite necessary step to be frank).

Once this connection is established, the client sends text to the server with the path it wants to access, if applicable, a query string separated by a tab, and followed then a newline, like this:
`/fruits	pineapple(NL)`

Alternatively, the client can just send a newline, and the server will treat it as listing root `/`.

# Response
This is all the information the server needs to process the request. The server then sends over raw data, sometimes ending with a newline followed by a period character (as described in RFC 1436). It then closes the connection.

Unlike HTTP, which uses headers for server responses, Gopher leaves it up to the client to interpret it; this is why a Gopher URL should have an item type in it so the client knows what it will receive.s That brings us to...

# URL Schemas
So, that means, instead of this to receive a text document:
`gopher://gopher.floodgap.com/gopher/proxy`

You should use this, to explicitly tell the client that it'll receive plain text:
`gopher://gopher.floodgap.com/0/gopher/proxy`

Other (older?) implementations of the Gopher URL are like this, where the item type and path are not separated by a slash:
`gopher://gopher.floodgap.com/0gopher/proxy`

While this is how it is laid out in RFC 2466, "The gopher URI Scheme", I am not in favor of it. Reason being is how using the malformed URL from earlier would tell the client that it is to fetch `opher/proxy` and treat it as a `g` (which happens to be the GIF) item type. Having the slash after the type would make it easier for the client to tell if a URL doesn't have an item type specified, since all types are one character.

# Directories/Menus
Gopher servers can send whatever files and raw data to the client, but what ties it all together are menus. Here's an example menu response, playing off of the fruits example from earlier.

```
1Back to ThingSearch	/	thingsearch.uh	70
iHere are your results for "pineapple".	/	error.host	0
```
Each line in a Gopher menu is a selector, which leads to a resource on a specific server. This can be the same host and port, or another server. Each field is separated by a tab, with the exception of the selector's display text:
- The type, which tells the client how to understand the resource when it is fetched from the server.
- The display text, without any tab characters. The general rule of thumb is that it should be formatted for a screen of 67 characters across at max. This is not necessarily for technical reasons, however.
- The path where the resource is located. In information selectors, this can be left blank.
- The host of the server.
- The port of the server, which is typically 70.
- An extra field could be used to signify that the resource is Gopher+-enabled, although clients that don't support it should be able to ignore it. This isn't shown in the example.

For the menu to be parsed correctly, all of these fields must be present, except the extra field for Gopher+, which is optional.

I've separated a sample of the types that can be used in a menu into four basic categories.

## Item types

**Text:**
- `0`: Plain text

**Menus:**
- `1`: Directory/Menu
- `7`: Search service (Directory/Menu that accepts a query)

**Binaries:**
- `4`: HQX file (old Mac archives)
- `5`: PC binary
- `9`: Generic binary (your best bet)
- `g`: GIF image
- `I`: Generic image (be careful when parsing, Gopher item types are case-sensitive)
- `s`: WAV sound (for MP3s and other formats, you should use type `9`)

**Information:**
- `3`: An error
- `i`: Informational text

The `3` and `i` selectors, even being just information, should still have all of the above required fields filled in. (The path can be blank so long as the tabs are there.) The example above uses a fake host and port. It could be anything, doesn't matter all too much. This way, the few clients that don't interpret information selectors as such will at least have somewhere fake to link to.

## Gophermaps
A Gophermap is a file in a directory representing a Gopher menu used by many modern Gopher servers (Gophernicus, Pygopherd, and of course Bucktooth that introduced it). Gophermaps also have a simplified syntax, where the server acts as a preprocessor and will fill in fields and take care of things like relative directories as needed. Additionally, lines without tabs are turned into information selectors automatically.

In a Gophermap, if you're linking to another resource on the same server, you could have a selector that's like this:
`1Food	food/`
and the server will take that and blow it up into a full Gopher selector, filling in the blanks:
`1Food	/things/food	127.0.0.1	70`
In this example, the Gophermap is in the directory `/things`, the server fills that into the path so the client can understand it. The server knows that it is being advertised on host `127.0.0.1` and port `70` from its configuration, so it fills that in.

Here's another example with some information:
`The quick brown fox jumps over the lazy dog.`
Because it doesn't have any tab characters, this is turned into something along the lines of:
`iThe quick brown fox jumps over the lazy dog.	/	error.host(T)0`

In essence, when using a Gophermap file, the server does the heavy lifting so the client doesn't need to make assumptions when parsing the final Gopher menu.

# External links
- [RFC 1436 "The Internet Gopher Protocol"](https://tools.ietf.org/html/rfc1436)
- [RFC 2466 "The gopher URI scheme"](https://tools.ietf.org/html/rfc2466)
- [The SDF's Gopher tutorial](https://sdf.org/?tutorials/gopher)
- [Gopher on Wikipedia](https://en.wikipedia.org/wiki/Gopher_(protocol))

Common Gopher servers that use Gophermaps:
- [Bucktooth](gopher://gopher.floodgap.com:70/1/buck) [<sup>(proxy)</sup>](https://gopherlens-py.dotcomboom.repl.co/?url=gopher://gopher.floodgap.com:70/1/buck) (Perl, introduced the Gophermap format)
- [Pygopherd](https://github.com/jgoerzen/pygopherd) (Python 2.x)
- [Gophernicus](https://github.com/prologic/gophernicus) (C)

These are a couple of my related projects:
- [Gophermap Editor](https://gmap.dotcomboom.repl.co) (HTML5)
- [Pituophis](https://github.com/dotcomboom/Pituophis) (Python 3 client/server library)