I'd appreciate some help with the most basic possible CGI program with a form input. I don't want to run a listener or use a framework or do anything beyond the most basic possible example. This is just to get my feet in the door, and I will add the bells and whistles later.

Here's a simple CGI app without a form input:

package main

import "fmt"
import "os"

func main() {
        ip := os.Getenv("REMOTE_ADDR")
        fmt.Printf("Content-type: text/plain

")
        fmt.Println(ip)
}

This prints my IP address when I go to https://example.com/cgi-bin/ip

However, the following code results in a 502 error:

package main

import (
        "fmt"
        "net/http"
        s "strings"
)

func main() {
        var r *http.Request

        fmt.Printf("Content-type: text/html

")
        fmt.Println("<!DOCTYPE html>")
        fmt.Println("<title>login</title>")
        r.ParseForm()
        username := r.FormValue("username")
        password := r.FormValue("password")
        if s.Compare(password, username) == 0 {
                fmt.Println("<p>invalid username/password")
        }
}

The nginx log says:

2017/04/29 22:55:12 [error] 45768#0: *802 upstream prematurely closed FastCGI stdout while reading response header from upstream, client: 192.0.2.80, server: example.com, request: "POST /cgi-bin/login HTTP/2.0", upstream: "fastcgi://unix:run/slowcgi.sock:", host: "example.com", referrer: "https://example.com/login.html"

The HTML for this form is:

<!DOCTYPE html>
<title>Username and password</title>

<form action="/cgi-bin/login" method="post">
<table>
<tr><td>Username:</td><td><input type="text" name="username"></td></tr>
<tr><td>Password:</td><td><input type="password" name="password"></td></tr>
<tr><td> </td><td><input type="submit" value="Submit"></td></tr>
</table>
</form>

Another note: this is nginx on OpenBSD, using slowcgi(8). Since my toy "ip" program works, I believe my Go code is the problem.

What am I doing wrong in my Go code? Thank you!

EDIT: I now have the following code, which doesn't compile. What am I doing wrong?

package main

import (
        "fmt"
        "os"
        "net/http/cgi"
)

func main() {
        httpReq, err := cgi.Request()
        if err != nil {
                fmt.Fprintf(os.Stderr, err.Error())
                os.Exit(1)
        }

        r := httpReq.ParseForm()
        username := r.FormValue("username")
        password := r.FormValue("password")

        fmt.Printf("Content-type: text/html

")
        fmt.Printf("<!DOCTYPE html>
")
        fmt.Printf("<p>username: %s
", username)
        fmt.Printf("<p>password: %s
", password)
}