💾 Archived View for source.community › ckaznocha › gemini › raw › main › doc.go captured on 2024-05-26 at 15:02:31.

View Raw

More Information

⬅️ Previous capture (2023-07-10)

-=-=-=-=-=-=-

/*
Package gemini provides a server implementation for the Gemini protocol.

This package should feel familiar to people comfortable with Go's net/http
however it differs where it makes sense.

Handlers receive a context directly rather than attaching it to a request.

There is no support for starting a server without TLS.

The ResponseWriter provides methods for handing different response types rather
than a single abstract response.

An example of a server using this package. The server greets a user, accepting
input from either a prompt or a client cert. The example includes a graceful
shutdown, log handler, and a shutdown func:

	package main

	import (
		"context"
		"fmt"
		"log"
		"os"
		"os/signal"

		"source.community/ckaznocha/gemini"
	)

	func greetHandler(ctx context.Context, w gemini.ResponseWriter, r *gemini.Request) {
		var name string

		switch {
		case r.Subject != nil:
			name = r.Subject.CommonName
		case r.URI.Query != "":
			name = r.URI.RawQuery
		default:
			w.Input(ctx, "What is your name?", false)

			return
		}

		fmt.Fprintf(w.Success(ctx, ""), "Hello, %s!", name)
	}

	func main() {
		logger := log.New(
			os.Stdout,
			"[Gemini Example] ",
			log.LstdFlags|log.LUTC|log.Lmicroseconds|log.Lmsgprefix|log.Lshortfile,
		)

		logger.Println("Server starting")

		mux := gemini.NewServeMux()

		mux.HandleFunc("/greet", greetHandler)

		s := &gemini.Server{
			Handler: mux,
			LogHandler: func(message string, isError bool) {
				logger.Printf("gemini server: %s", message)
			},
		}

		s.RegisterOnShutdown(func() {
			s.LogHandler("shutting down", false)
		})

		ctx, cancel := context.WithCancel(context.Background())
		defer cancel()

		logger.Println("Server started")

		go func() {
			defer cancel()

			s.LogHandler("starting", false)
			err := s.ListenAndServeTLS("", "testdata/cert.pem", "testdata/key.pem")
			s.LogHandler(fmt.Sprintf("exited: %s\n", err), true)
		}()

		ctx, stop := signal.NotifyContext(ctx, os.Interrupt)
		defer stop()

		<-ctx.Done()

		logger.Println("Shutdown starting")
		defer logger.Println("Shutdown complete")

		if err := s.Shutdown(context.Background()); err != nil {
			logger.Printf("Error during shutdown: %s\n", err)
		}
	}

package gemini