>

There are cases that we need to run both http server and https server so that the client can still have access to the web service.
If we want to force a https connection while still provide http api we can redirect the http request to the https.
This article talks about how to redirect a http connection to a https connection.


#### Serve the same Content on both HTTP and HTTPS ---

This is the simplest option and easily achievable:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main

import (
"fmt"
"net/http"
)

func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there!")
}

func main() {
http.HandleFunc("/", handler)
// Start the HTTPS server in a goroutine
go http.ListenAndServeTLS(":8081", "cert.pem", "key.pem", nil)
// Start the HTTP server
http.ListenAndServe(":8080", nil)
}

#### Redirect from HTTP to HTTPS ---

This is the most sensible option if you want to encrypt all your connections. To achieve this, you’ll need a function to redirect from HTTP to HTTPS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package main

import (
"fmt"
"net/http"
)

func redirectToHttps(w http.ResponseWriter, r *http.Request) {
// Redirect the incoming HTTP request. Note that "127.0.0.1:8081" will only work if you are accessing the server from your local machine.
http.Redirect(w, r, "https://127.0.0.1:8081"+r.RequestURI, http.StatusMovedPermanently)
}

func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there!")
}

func main() {
http.HandleFunc("/", handler)
// Start the HTTPS server in a goroutine
go http.ListenAndServeTLS(":8081", "cert.pem", "key.pem", nil)
// Start the HTTP server and redirect all incoming connections to HTTPS
http.ListenAndServe(":8080", http.HandlerFunc(redirectToHttps))
}

Or, we can use two separate ServeMux for the HTTP and HTTPS servers so that only specific paths (e.g. /admin/) will be redirected to HTTPS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package main

import (
"fmt"
"net/http"
)

func redirectToHttps(w http.ResponseWriter, r *http.Request) {
// Redirect the incoming HTTP request. Note that "127.0.0.1:8081" will only work if you are accessing the server from your local machine.
http.Redirect(w, r, "https://127.0.0.1:8081"+r.RequestURI, http.StatusMovedPermanently)
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there!")
}

func adminHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi admin!")
}

func main() {
// Create a new ServeMux for HTTP connections
httpMux := http.NewServeMux()
// Create a new ServeMux for HTTPS connections
httpsMux := http.NewServeMux()
// Redirect /admin/ paths to HTTPS
httpMux.Handle("/admin/", http.HandlerFunc(redirectToHttps))
// Accept everything else
httpMux.Handle("/", http.HandlerFunc(homeHandler))
// Accept everything on HTTPS
httpsMux.Handle("/", http.HandlerFunc(homeHandler))
httpsMux.Handle("/admin/", http.HandlerFunc(adminHandler))
// Start the HTTPS server in a goroutine
go http.ListenAndServeTLS(":8081", "cert.pem", "key.pem", httpsMux)
// Start the HTTP server and redirect all incoming connections to HTTPS
http.ListenAndServe(":8080", httpMux)
}



Reference
http://www.kaihag.com/https-and-go/