Issue 1:
by angrygoats:

What steps will reproduce the problem?

Compile this program:
package sum

func sum(a []int) int
{ // returns an int
s := 0;
for i := 0; i < len(a); i++ {
s += a[i]
}
return s
}

(note brace at start of function definition is on new line)

What is the expected output? What do you see instead?

I'm not 100% sure, but I think this should compile. Instead I get:
sum.go:4: syntax error near int

What is your $GOOS? $GOARCH?
linux 386

Which revision are you using? (hg identify)
2701d4abb3f2

Please provide any additional information below.

I've run a bisection (with 'hg bisect') and the revision that seems to have
caused the change in behaviour was:

The first bad revision is:
changeset: 4395:26b9258d76e4
user: Russ Cox <rsc@golang.org>
date: Fri Dec 11 15:59:41 2009 -0800
summary: gc: semicolons

Issue 2:
Solution (Note to Les Googlers)

My question was, as I misinterpreted the documentation.

GetCertificate == SNICallback

You cannot cast net.Conn to http.Conn, you can only cast net.Listener to http.Listener

i.e. server := &http.Serve{}; server.Server(tlsListener)

See examples at

https://github.com/coolaj86/golang-https-example/tree/https-server

https://github.com/coolaj86/golang-https-example

The crux of the issue In 68 lines:

package main

import (
"crypto/tls"
"fmt"
"net"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
)

type myHandler struct{}

func (m *myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
fmt.Println(r.Host)
fmt.Println(r.Method)
fmt.Println(r.RequestURI)
fmt.Println(r.URL) // also has many keys, such as Query
for k, v := range r.Header {
fmt.Println(k, v)
}
fmt.Println(r.Body)

// End the request
fmt.Fprintf(w, "Hi there, %s %q? Wow!\n\nWith Love,\n\t%s", r.Method, r.URL.Path[1:], r.Host)
}

func main() {
port := uint(8443)
certsPath := "/etc/letsencrypt/live"
defaultHost := "localhost.daplie.com"

fmt.Printf("Loading Certificates %s/%s/{privkey.pem,fullchain.pem}\n", certsPath, defaultHost)

privkeyPath := filepath.Join(certsPath, defaultHost, "privkey.pem")
certPath := filepath.Join(certsPath, defaultHost, "fullchain.pem")
cert, err := tls.LoadX509KeyPair(certPath, privkeyPath)
if err != nil {
fmt.Fprintf(os.Stderr, "Couldn't load default certificates: %s\n", err)
os.Exit(1)
}

addr := ":" + strconv.Itoa(int(port))

conn, err := net.Listen("tcp", addr)
if nil != err {
fmt.Fprintf(os.Stderr, "Couldn't bind to TCP socket %q: %s\n", addr, err)
os.Exit(1)
}

tlsConfig := new(tls.Config)
tlsConfig.Certificates = []tls.Certificate{cert}
tlsConfig.GetCertificate = func(clientHello *tls.ClientHelloInfo) (*tls.Certificate, error) {
return &cert, nil
}
tlsListener := tls.NewListener(conn, tlsConfig)

server := &http.Server{
Addr: addr,
Handler: &myHandler{},
}

host := strings.ToLower(defaultHost)
fmt.Printf("Listening on https://%s:%d\n", host, port)
server.Serve(tlsListener)
}

Original Question

https://LetsEncrypt.org's release is just around the corner, but it's currently not possible to dynamically retrieve and renew certificates in go with an active http server.

To do so requires fixing a tiny regression introduced sometime between the move from httputils and now. See https://golang.org/pkg/net/http/httputil/#ServerConn.

We need to re-expose http.NewConn and http.conn.Serve.

See the diff: coolaj86@1a30898

I've got a working demo of dynamically loading certificates with this change here:

https://gist.github.com/coolaj86/16ed8fd810e19dec71be

I've already signed the CLA and with a little coaching I'm sure I could turn my example into an appropriate test case, but I'm way out of my league with the 37-page explanation of how to make a pull request...

See also #11649