Skip to content

Instantly share code, notes, and snippets.

@lanrat
Last active November 1, 2015 04:54
Show Gist options
  • Select an option

  • Save lanrat/0e7745adc42bc24296cb to your computer and use it in GitHub Desktop.

Select an option

Save lanrat/0e7745adc42bc24296cb to your computer and use it in GitHub Desktop.
Serve HTTP & HTTPS on same port example
package main
import (
"crypto/tls"
"fmt"
"io"
"log"
"net"
"net/http"
"net/url"
)
var (
addr = "127.0.0.1:8080"
config *tls.Config
)
type Conn struct {
net.Conn
b byte
e error
f bool
}
func (c *Conn) Read(b []byte) (int, error) {
if c.f {
c.f = false
b[0] = c.b
if len(b) > 1 && c.e == nil {
n, e := c.Conn.Read(b[1:])
if e != nil {
c.Conn.Close()
}
return n + 1, e
} else {
return 1, c.e
}
}
return c.Conn.Read(b)
}
type SplitListener struct {
net.Listener
}
func (l *SplitListener) Accept() (net.Conn, error) {
c, err := l.Listener.Accept()
if err != nil {
return nil, err
}
b := make([]byte, 1)
_, err = c.Read(b)
if err != nil {
c.Close()
if err != io.EOF {
return nil, err
}
}
con := &Conn{
Conn: c,
b: b[0],
e: err,
f: true,
}
if b[0] == 22 {
log.Println("HTTPS")
return tls.Server(con, config), nil
}
log.Println("HTTP")
return con, nil
}
func main() {
var err error
config = &tls.Config{}
if config.NextProtos == nil {
config.NextProtos = []string{"http/1.1"}
}
config.Certificates = make([]tls.Certificate, 1)
config.Certificates[0], err = tls.LoadX509KeyPair("cert.pem", "key.pem")
if err != nil {
log.Fatal(err)
}
ln, err := net.Listen("tcp", addr)
if err != nil {
log.Fatal(err)
}
http.HandleFunc("/", hello)
log.Fatal(http.Serve(
&SplitListener{Listener: ln},
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.TLS == nil {
u := url.URL{
Scheme: "https",
Opaque: r.URL.Opaque,
User: r.URL.User,
Host: addr,
Path: r.URL.Path,
RawQuery: r.URL.RawQuery,
Fragment: r.URL.Fragment,
}
http.Redirect(w, r, u.String(), http.StatusMovedPermanently)
} else {
http.DefaultServeMux.ServeHTTP(w, r)
}
})))
}
func hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "Hello world!")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment