95 lines
3.0 KiB
Markdown
95 lines
3.0 KiB
Markdown
---
|
|
author: ~khuxkm
|
|
published: true
|
|
title: gemini cgi guide
|
|
description: a guide to using CGI on gemini
|
|
category:
|
|
- publishing
|
|
- guides
|
|
- technical
|
|
---
|
|
|
|
## where to put CGI scripts
|
|
|
|
you can put CGI scripts anywhere. as long as you make the file executable and
|
|
have it output the correct format for gemini. the server calls a new instance
|
|
of the program for every request it has to handle, meaning that data isn't
|
|
saved between runs unless you manually save the data to a file or database and
|
|
load the data on the next run.
|
|
|
|
## what languages can be used to write CGI
|
|
|
|
any language that can read environment variables can be used for CGI. even
|
|
shell scripting can be used for CGI, given you provide the correct shebang.
|
|
|
|
## how to write a gemini CGI script
|
|
|
|
these are the environment variables gemserv (our trusty gemini server) gives a
|
|
CGI program:
|
|
|
|
- `GATEWAY_INTERFACE` - always `CGI/1.1` in our case
|
|
- `GEMINI_URL` - the full URL used to request the page, including any query
|
|
strings
|
|
- `PATH_INFO` - any extra path after the script itself (for instance,
|
|
`gemini://tilde.team/~khuxkm/test.cgi/test/one` gives a `PATH_INFO` of
|
|
`/test/one`)
|
|
- `REMOTE_ADDR`, `REMOTE_HOST`, `REMOTE_PORT` - the addr/host/port of the
|
|
connecting client, the former two useful for rate-limiting
|
|
- `SCRIPT_NAME` - the path component of the URL that corresponds to the script
|
|
being called
|
|
- `SERVER_NAME` - the name of the server, in our case `tilde.team`
|
|
- `SERVER_PROTOCOL` - always `GEMINI` in our case
|
|
- `SERVER_SOFTWARE` - always `gemserv` in our case
|
|
- `LC_CTYPE` - always `C.UTF-8` in our case (allows for UTF-8 output)
|
|
|
|
also, if the user supplies a cert:
|
|
|
|
- `AUTH_TYPE` - always `Certificate` if present; if not present, no cert is
|
|
supplied
|
|
- `TLS_CLIENT_HASH` - the hash of the certificate, prepended with the hash type
|
|
- `REMOTE_USER` - the Common Name of the certificate
|
|
|
|
in order to write a CGI program, simply use these environment variables to
|
|
figure out what you want to do and then do it. for a simple hello world:
|
|
|
|
```
|
|
#!/bin/sh
|
|
printf '20 text/gemini\r\n'
|
|
printf 'Hello world from CGI!\r\n'
|
|
```
|
|
|
|
do note that the first line MUST use \r\n as a terminator. after that, if
|
|
you're serving gemtext, you can use whatever LF/CRLF you want for line endings
|
|
as long as you stay consistent.
|
|
|
|
for a more complex hello world that asks for input, here's a python script that
|
|
asks for your name and says hello to you:
|
|
|
|
```
|
|
#!/usr/bin/python3
|
|
from urllib.parse import unquote
|
|
from os import environ
|
|
from sys import exit
|
|
|
|
if "QUERY_STRING" not in environ:
|
|
print("10 Please enter your name",end="\r\n")
|
|
exit()
|
|
name = unquote(environ["QUERY_STRING"])
|
|
|
|
print("20 text/gemini",end="\r\n")
|
|
print(f"Hello {name}!")
|
|
```
|
|
|
|
remember, anything that can read environment variables and write to stdout can
|
|
be used to make CGI, as long as the server can figure out how to execute it.
|
|
|
|
##how to set a CGI script as executable
|
|
|
|
The CGI script must be marked as executable in order to actually run.
|
|
|
|
To make the script executable, run this command:
|
|
|
|
```
|
|
chmod +x SCRIPT_NAME.cgi
|
|
```
|