package main // Simply does Gemini requests and prints output. import ( "crypto/tls" "flag" "fmt" "io" "net/url" "os" "strings" ) func main() { // Parse command-line flags insecure := flag.Bool("insecure", false, "Skip TLS certificate verification") flag.Parse() // Get the URL from arguments args := flag.Args() if len(args) != 1 { fmt.Fprintf(os.Stderr, "Usage: gemget [--insecure] \n") os.Exit(1) } geminiURL := args[0] host := validateUrl(geminiURL) connect(geminiURL, host, *insecure) } func validateUrl(u string) string { // Parse the URL parsedURL, err := url.Parse(u) if err != nil { fmt.Fprintf(os.Stderr, "Error parsing URL: %v\n", err) os.Exit(1) } // Ensure it's a gemini URL if parsedURL.Scheme != "gemini" { fmt.Fprintf(os.Stderr, "Error: URL must use gemini:// scheme\n") os.Exit(1) } // Get host and port host := parsedURL.Host if !strings.Contains(host, ":") { host = host + ":1965" // Default Gemini port } return host } func connect(url string, host string, insecure bool) { // Configure TLS tlsConfig := &tls.Config{ InsecureSkipVerify: insecure, MinVersion: tls.VersionTLS12, } // Connect to the server conn, err := tls.Dial("tcp", host, tlsConfig) if err != nil { fmt.Fprintf(os.Stderr, "Error connecting to server: %v\n", err) os.Exit(1) } defer func() { _ = conn.Close() }() // Send the request (URL + CRLF) request := url + "\r\n" _, err = conn.Write([]byte(request)) if err != nil { fmt.Fprintf(os.Stderr, "Error sending request: %v\n", err) os.Exit(1) } // Read and print the response to stdout _, err = io.Copy(os.Stdout, conn) if err != nil { fmt.Fprintf(os.Stderr, "Error reading response: %v\n", err) os.Exit(1) } }