From 6dde906e15dae26528f9438798b3d950aff92c61 Mon Sep 17 00:00:00 2001 From: khuxkm fbexl Date: Tue, 9 Aug 2022 20:40:01 +0000 Subject: [PATCH] Add gemini CGI page Nobody told me it was awful, so I'm going to put it up. If any changes need to be made, they can be made. --- wiki/pages/gemini-cgi.md | 82 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 wiki/pages/gemini-cgi.md diff --git a/wiki/pages/gemini-cgi.md b/wiki/pages/gemini-cgi.md new file mode 100644 index 0000000..a6a0b9b --- /dev/null +++ b/wiki/pages/gemini-cgi.md @@ -0,0 +1,82 @@ +--- +author: ~khuxkm +published: true +title: gemini cgi guide +description: a guide to using CGI on gemini +category: + - main +--- + +## 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.