From 46220b726dce5425bf3f04ad49aa5cbc3d0f731e Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 3 Apr 2017 21:23:45 +0800 Subject: [PATCH 1/9] feat: support Let's Encrypt tls. --- .gitignore | 4 ++-- examples/auto-tls/main.go | 17 +++++++++++++++++ gin.go | 31 +++++++++++++++++++++++++++++++ vendor/vendor.json | 24 +++++++++++++++++++++--- 4 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 examples/auto-tls/main.go diff --git a/.gitignore b/.gitignore index 9f48f142..f3b636df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -Godeps/* -!Godeps/Godeps.json +vendor/* +!vendor/vendor.json coverage.out count.out diff --git a/examples/auto-tls/main.go b/examples/auto-tls/main.go new file mode 100644 index 00000000..2c0d89d9 --- /dev/null +++ b/examples/auto-tls/main.go @@ -0,0 +1,17 @@ +package main + +import ( + "github.com/gin-gonic/gin" +) + +func main() { + r := gin.Default() + + // Ping handler + r.GET("/ping", func(c *gin.Context) { + c.String(200, "pong") + }) + + // Listen and Server in 0.0.0.0:443 + r.RunAutoTLS(":443", "/var/www/.cache", "example.com") +} diff --git a/gin.go b/gin.go index 61ac5c00..4a3a8332 100644 --- a/gin.go +++ b/gin.go @@ -5,6 +5,7 @@ package gin import ( + "crypto/tls" "html/template" "net" "net/http" @@ -12,6 +13,7 @@ import ( "sync" "github.com/gin-gonic/gin/render" + "golang.org/x/crypto/acme/autocert" ) // Version is Framework's version @@ -255,6 +257,35 @@ func (engine *Engine) RunTLS(addr string, certFile string, keyFile string) (err return } +// RunAutoTLS attaches the router to a http.Server and starts listening and serving HTTPS (secure) requests. +// It obtains and refreshes certificates automatically, +// as well as providing them to a TLS server via tls.Config. +func (engine *Engine) RunAutoTLS(addr string, cache string, domain ...string) (err error) { + debugPrint("Listening and serving HTTPS on %s and host name is %s\n", addr, domain) + defer func() { debugPrintError(err) }() + m := autocert.Manager{ + Prompt: autocert.AcceptTOS, + } + + //your domain here + if len(domain) != 0 { + m.HostPolicy = autocert.HostWhitelist(domain...) + } + + // folder for storing certificates + if cache != "" { + m.Cache = autocert.DirCache(cache) + } + + s := &http.Server{ + Addr: addr, + TLSConfig: &tls.Config{GetCertificate: m.GetCertificate}, + Handler: engine, + } + err = s.ListenAndServeTLS("", "") + return +} + // RunUnix attaches the router to a http.Server and starts listening and serving HTTP requests // through the specified unix socket (ie. a file). // Note: this method will block the calling goroutine indefinitely unless an error happens. diff --git a/vendor/vendor.json b/vendor/vendor.json index 2bc5e194..e3b3e91b 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -54,11 +54,29 @@ "revisionTime": "2017-02-15T20:11:44Z" }, { - "checksumSHA1": "9jjO5GjLa0XF/nfWihF02RoH4qc=", + "checksumSHA1": "didOyrMN69DzlBd+BPSC28G2YG0=", + "path": "golang.org/x/crypto/acme", + "revision": "88915ccf7aeb91e9324fe7cf3eddd1531ced61ea", + "revisionTime": "2017-04-02T20:18:05Z" + }, + { + "checksumSHA1": "yfiamzDHcZXb6irWt7DfHVxCs44=", + "path": "golang.org/x/crypto/acme/autocert", + "revision": "88915ccf7aeb91e9324fe7cf3eddd1531ced61ea", + "revisionTime": "2017-04-02T20:18:05Z" + }, + { + "checksumSHA1": "Y+HGqEkYM15ir+J93MEaHdyFy0c=", "comment": "release-branch.go1.7", "path": "golang.org/x/net/context", - "revision": "d4c55e66d8c3a2f3382d264b08e3e3454a66355a", - "revisionTime": "2016-10-18T08:54:36Z" + "revision": "ffcf1bedda3b04ebb15a168a59800a73d6dc0f4d", + "revisionTime": "2017-03-29T01:43:45Z" + }, + { + "checksumSHA1": "WHc3uByvGaMcnSoI21fhzYgbOgg=", + "path": "golang.org/x/net/context/ctxhttp", + "revision": "ffcf1bedda3b04ebb15a168a59800a73d6dc0f4d", + "revisionTime": "2017-03-29T01:43:45Z" }, { "checksumSHA1": "/oZpHfYc+ZgOwYAhlvcMhmETYpw=", From 70d0a4c5bab95de89d1d9fb057f6f1cc0defb554 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 3 Apr 2017 22:51:56 +0800 Subject: [PATCH 2/9] fix: build only from Go version 1.7 onward --- gin.go | 31 ------------------------------- gin1.7.go | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 31 deletions(-) create mode 100644 gin1.7.go diff --git a/gin.go b/gin.go index 4a3a8332..61ac5c00 100644 --- a/gin.go +++ b/gin.go @@ -5,7 +5,6 @@ package gin import ( - "crypto/tls" "html/template" "net" "net/http" @@ -13,7 +12,6 @@ import ( "sync" "github.com/gin-gonic/gin/render" - "golang.org/x/crypto/acme/autocert" ) // Version is Framework's version @@ -257,35 +255,6 @@ func (engine *Engine) RunTLS(addr string, certFile string, keyFile string) (err return } -// RunAutoTLS attaches the router to a http.Server and starts listening and serving HTTPS (secure) requests. -// It obtains and refreshes certificates automatically, -// as well as providing them to a TLS server via tls.Config. -func (engine *Engine) RunAutoTLS(addr string, cache string, domain ...string) (err error) { - debugPrint("Listening and serving HTTPS on %s and host name is %s\n", addr, domain) - defer func() { debugPrintError(err) }() - m := autocert.Manager{ - Prompt: autocert.AcceptTOS, - } - - //your domain here - if len(domain) != 0 { - m.HostPolicy = autocert.HostWhitelist(domain...) - } - - // folder for storing certificates - if cache != "" { - m.Cache = autocert.DirCache(cache) - } - - s := &http.Server{ - Addr: addr, - TLSConfig: &tls.Config{GetCertificate: m.GetCertificate}, - Handler: engine, - } - err = s.ListenAndServeTLS("", "") - return -} - // RunUnix attaches the router to a http.Server and starts listening and serving HTTP requests // through the specified unix socket (ie. a file). // Note: this method will block the calling goroutine indefinitely unless an error happens. diff --git a/gin1.7.go b/gin1.7.go new file mode 100644 index 00000000..dd8a65a9 --- /dev/null +++ b/gin1.7.go @@ -0,0 +1,40 @@ +// +build go1.7 + +package gin + +import ( + "crypto/tls" + "net/http" + + "golang.org/x/crypto/acme/autocert" +) + +// RunAutoTLS attaches the router to a http.Server and starts listening and serving HTTPS (secure) requests. +// It obtains and refreshes certificates automatically, +// as well as providing them to a TLS server via tls.Config. +// only from Go version 1.7 onward +func (engine *Engine) RunAutoTLS(addr string, cache string, domain ...string) (err error) { + debugPrint("Listening and serving HTTPS on %s and host name is %s\n", addr, domain) + defer func() { debugPrintError(err) }() + m := autocert.Manager{ + Prompt: autocert.AcceptTOS, + } + + //your domain here + if len(domain) != 0 { + m.HostPolicy = autocert.HostWhitelist(domain...) + } + + // folder for storing certificates + if cache != "" { + m.Cache = autocert.DirCache(cache) + } + + s := &http.Server{ + Addr: addr, + TLSConfig: &tls.Config{GetCertificate: m.GetCertificate}, + Handler: engine, + } + err = s.ListenAndServeTLS("", "") + return +} From d17e0a31b8ffd2df3a85734dfca5314b9e152a80 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 3 Apr 2017 23:30:46 +0800 Subject: [PATCH 3/9] fix: remove hard code for cache. --- examples/auto-tls/main.go | 5 ++++- gin1.7.go | 22 +++++++++------------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/examples/auto-tls/main.go b/examples/auto-tls/main.go index 2c0d89d9..896d3a9e 100644 --- a/examples/auto-tls/main.go +++ b/examples/auto-tls/main.go @@ -2,16 +2,19 @@ package main import ( "github.com/gin-gonic/gin" + "golang.org/x/crypto/acme/autocert" ) func main() { r := gin.Default() + gin.AutoTLSManager.Cache = autocert.DirCache("/var/www/.cache") + // Ping handler r.GET("/ping", func(c *gin.Context) { c.String(200, "pong") }) // Listen and Server in 0.0.0.0:443 - r.RunAutoTLS(":443", "/var/www/.cache", "example.com") + r.RunAutoTLS("example.com") } diff --git a/gin1.7.go b/gin1.7.go index dd8a65a9..7599fdf0 100644 --- a/gin1.7.go +++ b/gin1.7.go @@ -9,30 +9,26 @@ import ( "golang.org/x/crypto/acme/autocert" ) +var AutoTLSManager = autocert.Manager{ + Prompt: autocert.AcceptTOS, +} + // RunAutoTLS attaches the router to a http.Server and starts listening and serving HTTPS (secure) requests. // It obtains and refreshes certificates automatically, // as well as providing them to a TLS server via tls.Config. // only from Go version 1.7 onward -func (engine *Engine) RunAutoTLS(addr string, cache string, domain ...string) (err error) { - debugPrint("Listening and serving HTTPS on %s and host name is %s\n", addr, domain) +func (engine *Engine) RunAutoTLS(domain ...string) (err error) { + debugPrint("Listening and serving HTTPS on host name is %s\n", domain) defer func() { debugPrintError(err) }() - m := autocert.Manager{ - Prompt: autocert.AcceptTOS, - } //your domain here if len(domain) != 0 { - m.HostPolicy = autocert.HostWhitelist(domain...) - } - - // folder for storing certificates - if cache != "" { - m.Cache = autocert.DirCache(cache) + AutoTLSManager.HostPolicy = autocert.HostWhitelist(domain...) } s := &http.Server{ - Addr: addr, - TLSConfig: &tls.Config{GetCertificate: m.GetCertificate}, + Addr: ":443", + TLSConfig: &tls.Config{GetCertificate: AutoTLSManager.GetCertificate}, Handler: engine, } err = s.ListenAndServeTLS("", "") From 6b0ae2a64a8e4444e56e8a316e700a5434e5365a Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 3 Apr 2017 23:34:00 +0800 Subject: [PATCH 4/9] docs: update example. --- examples/auto-tls/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/auto-tls/main.go b/examples/auto-tls/main.go index 896d3a9e..9495c0ac 100644 --- a/examples/auto-tls/main.go +++ b/examples/auto-tls/main.go @@ -16,5 +16,5 @@ func main() { }) // Listen and Server in 0.0.0.0:443 - r.RunAutoTLS("example.com") + r.RunAutoTLS("example1.com", "example2.com") } From fb502ca58b20561415b7d8b3d00aa987521b130d Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 3 Apr 2017 23:42:21 +0800 Subject: [PATCH 5/9] docs: update --- gin1.7.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gin1.7.go b/gin1.7.go index 7599fdf0..59de3d0b 100644 --- a/gin1.7.go +++ b/gin1.7.go @@ -9,6 +9,7 @@ import ( "golang.org/x/crypto/acme/autocert" ) +// AutoTLSManager is a stateful certificate manager built on top of acme.Client. var AutoTLSManager = autocert.Manager{ Prompt: autocert.AcceptTOS, } @@ -21,7 +22,7 @@ func (engine *Engine) RunAutoTLS(domain ...string) (err error) { debugPrint("Listening and serving HTTPS on host name is %s\n", domain) defer func() { debugPrintError(err) }() - //your domain here + // HostPolicy controls which domains the Manager will attempt if len(domain) != 0 { AutoTLSManager.HostPolicy = autocert.HostWhitelist(domain...) } From 0cb7cf88cb8758452b35d87b804c73906a324cb1 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Tue, 4 Apr 2017 14:19:04 +0800 Subject: [PATCH 6/9] docs: add comment. --- examples/auto-tls/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/auto-tls/main.go b/examples/auto-tls/main.go index 9495c0ac..49544c52 100644 --- a/examples/auto-tls/main.go +++ b/examples/auto-tls/main.go @@ -8,6 +8,7 @@ import ( func main() { r := gin.Default() + // folder for storing certificates gin.AutoTLSManager.Cache = autocert.DirCache("/var/www/.cache") // Ping handler From 2da17294c906173561bec1707fb6d03c823f701c Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Tue, 4 Apr 2017 14:19:44 +0800 Subject: [PATCH 7/9] feat: listen https. --- gin1.7.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gin1.7.go b/gin1.7.go index 59de3d0b..919c80f3 100644 --- a/gin1.7.go +++ b/gin1.7.go @@ -28,7 +28,7 @@ func (engine *Engine) RunAutoTLS(domain ...string) (err error) { } s := &http.Server{ - Addr: ":443", + Addr: ":https", TLSConfig: &tls.Config{GetCertificate: AutoTLSManager.GetCertificate}, Handler: engine, } From f8520b83f912848dea56595ca7ec2f652a72b4ee Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 17 Apr 2017 13:41:47 +0800 Subject: [PATCH 8/9] update Signed-off-by: Bo-Yi Wu --- README.md | 59 +++++++++++++++++++++++++++++++++++ examples/auto-tls/example1.go | 19 +++++++++++ examples/auto-tls/example2.go | 26 +++++++++++++++ examples/auto-tls/main.go | 21 ------------- gin1.7.go | 37 ---------------------- 5 files changed, 104 insertions(+), 58 deletions(-) create mode 100644 examples/auto-tls/example1.go create mode 100644 examples/auto-tls/example2.go delete mode 100644 examples/auto-tls/main.go delete mode 100644 gin1.7.go diff --git a/README.md b/README.md index 883f9d50..535ee4eb 100644 --- a/README.md +++ b/README.md @@ -777,6 +777,65 @@ func main() { } ``` +### Support Let's Encrypt + +example for 1-line LetsEncrypt HTTPS servers. + +[embedmd]:# (examples/auto-tls/example1.go go) +```go +package main + +import ( + "log" + + "github.com/gin-gonic/autotls" + "github.com/gin-gonic/gin" +) + +func main() { + r := gin.Default() + + // Ping handler + r.GET("/ping", func(c *gin.Context) { + c.String(200, "pong") + }) + + log.Fatal(autotls.Run(r, "example1.com", "example2.com")) +} +``` + +example for custom autocert manager. + +[embedmd]:# (examples/auto-tls/example2.go go) +```go +package main + +import ( + "log" + + "github.com/gin-gonic/autotls" + "github.com/gin-gonic/gin" + "golang.org/x/crypto/acme/autocert" +) + +func main() { + r := gin.Default() + + // Ping handler + r.GET("/ping", func(c *gin.Context) { + c.String(200, "pong") + }) + + m := autocert.Manager{ + Prompt: autocert.AcceptTOS, + HostPolicy: autocert.HostWhitelist("example1.com", "example2.com"), + Cache: autocert.DirCache("/var/www/.cache"), + } + + log.Fatal(autotls.RunWithManager(r, m)) +} +``` + ### Graceful restart or stop Do you want to graceful restart or stop your web server? diff --git a/examples/auto-tls/example1.go b/examples/auto-tls/example1.go new file mode 100644 index 00000000..fa9f4008 --- /dev/null +++ b/examples/auto-tls/example1.go @@ -0,0 +1,19 @@ +package main + +import ( + "log" + + "github.com/gin-gonic/autotls" + "github.com/gin-gonic/gin" +) + +func main() { + r := gin.Default() + + // Ping handler + r.GET("/ping", func(c *gin.Context) { + c.String(200, "pong") + }) + + log.Fatal(autotls.Run(r, "example1.com", "example2.com")) +} diff --git a/examples/auto-tls/example2.go b/examples/auto-tls/example2.go new file mode 100644 index 00000000..ab8b81e7 --- /dev/null +++ b/examples/auto-tls/example2.go @@ -0,0 +1,26 @@ +package main + +import ( + "log" + + "github.com/gin-gonic/autotls" + "github.com/gin-gonic/gin" + "golang.org/x/crypto/acme/autocert" +) + +func main() { + r := gin.Default() + + // Ping handler + r.GET("/ping", func(c *gin.Context) { + c.String(200, "pong") + }) + + m := autocert.Manager{ + Prompt: autocert.AcceptTOS, + HostPolicy: autocert.HostWhitelist("example1.com", "example2.com"), + Cache: autocert.DirCache("/var/www/.cache"), + } + + log.Fatal(autotls.RunWithManager(r, m)) +} diff --git a/examples/auto-tls/main.go b/examples/auto-tls/main.go deleted file mode 100644 index 49544c52..00000000 --- a/examples/auto-tls/main.go +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import ( - "github.com/gin-gonic/gin" - "golang.org/x/crypto/acme/autocert" -) - -func main() { - r := gin.Default() - - // folder for storing certificates - gin.AutoTLSManager.Cache = autocert.DirCache("/var/www/.cache") - - // Ping handler - r.GET("/ping", func(c *gin.Context) { - c.String(200, "pong") - }) - - // Listen and Server in 0.0.0.0:443 - r.RunAutoTLS("example1.com", "example2.com") -} diff --git a/gin1.7.go b/gin1.7.go deleted file mode 100644 index 919c80f3..00000000 --- a/gin1.7.go +++ /dev/null @@ -1,37 +0,0 @@ -// +build go1.7 - -package gin - -import ( - "crypto/tls" - "net/http" - - "golang.org/x/crypto/acme/autocert" -) - -// AutoTLSManager is a stateful certificate manager built on top of acme.Client. -var AutoTLSManager = autocert.Manager{ - Prompt: autocert.AcceptTOS, -} - -// RunAutoTLS attaches the router to a http.Server and starts listening and serving HTTPS (secure) requests. -// It obtains and refreshes certificates automatically, -// as well as providing them to a TLS server via tls.Config. -// only from Go version 1.7 onward -func (engine *Engine) RunAutoTLS(domain ...string) (err error) { - debugPrint("Listening and serving HTTPS on host name is %s\n", domain) - defer func() { debugPrintError(err) }() - - // HostPolicy controls which domains the Manager will attempt - if len(domain) != 0 { - AutoTLSManager.HostPolicy = autocert.HostWhitelist(domain...) - } - - s := &http.Server{ - Addr: ":https", - TLSConfig: &tls.Config{GetCertificate: AutoTLSManager.GetCertificate}, - Handler: engine, - } - err = s.ListenAndServeTLS("", "") - return -} From 03a76c00ea02bd5fcbde25442261b6c5372b3948 Mon Sep 17 00:00:00 2001 From: Bo-Yi Wu Date: Mon, 17 Apr 2017 13:43:33 +0800 Subject: [PATCH 9/9] revert vendor.json Signed-off-by: Bo-Yi Wu --- vendor/vendor.json | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/vendor/vendor.json b/vendor/vendor.json index e3b3e91b..2bc5e194 100644 --- a/vendor/vendor.json +++ b/vendor/vendor.json @@ -54,29 +54,11 @@ "revisionTime": "2017-02-15T20:11:44Z" }, { - "checksumSHA1": "didOyrMN69DzlBd+BPSC28G2YG0=", - "path": "golang.org/x/crypto/acme", - "revision": "88915ccf7aeb91e9324fe7cf3eddd1531ced61ea", - "revisionTime": "2017-04-02T20:18:05Z" - }, - { - "checksumSHA1": "yfiamzDHcZXb6irWt7DfHVxCs44=", - "path": "golang.org/x/crypto/acme/autocert", - "revision": "88915ccf7aeb91e9324fe7cf3eddd1531ced61ea", - "revisionTime": "2017-04-02T20:18:05Z" - }, - { - "checksumSHA1": "Y+HGqEkYM15ir+J93MEaHdyFy0c=", + "checksumSHA1": "9jjO5GjLa0XF/nfWihF02RoH4qc=", "comment": "release-branch.go1.7", "path": "golang.org/x/net/context", - "revision": "ffcf1bedda3b04ebb15a168a59800a73d6dc0f4d", - "revisionTime": "2017-03-29T01:43:45Z" - }, - { - "checksumSHA1": "WHc3uByvGaMcnSoI21fhzYgbOgg=", - "path": "golang.org/x/net/context/ctxhttp", - "revision": "ffcf1bedda3b04ebb15a168a59800a73d6dc0f4d", - "revisionTime": "2017-03-29T01:43:45Z" + "revision": "d4c55e66d8c3a2f3382d264b08e3e3454a66355a", + "revisionTime": "2016-10-18T08:54:36Z" }, { "checksumSHA1": "/oZpHfYc+ZgOwYAhlvcMhmETYpw=",