From 6f83c48a10a890eb4ef9219ee9cc278b5eff0f7f Mon Sep 17 00:00:00 2001 From: Gerasimos Maropoulos Date: Fri, 29 Jul 2016 01:33:20 +0300 Subject: [PATCH] Update to v4.0.0-alpha.5 - Letsencrypt integration https://github.com/kataras/iris/issues/220 . 4 Fixes. Read HISTORY.md ## 4.0.0-alpha.4 -> 4.0.0-alpha.5 - **NEW FEATURE**: Letsencrypt.org integration[*](https://github.com/kataras/iris/issues/220) - example [here](https://github.com/iris-contrib/examples/blob/master/letsencrypt/main.go) - **FIX**: (ListenUNIX adds :80 to filename)[https://github.com/kataras/iris/issues/321] - **FIX**: (Go-Bindata + ctx.Render)[https://github.com/kataras/iris/issues/315] - **FIX** (auto-gzip doesn't really compress data in latest code)[https://github.com/kataras/iris/issues/312] --- HISTORY.md | 9 +++++++++ README.md | 7 ++++--- config/server.go | 5 +++++ http.go | 37 ++++++++++++++++++++++++++++--------- iris.go | 40 +++++++++++++++++++++++++++++++++++++++- 5 files changed, 85 insertions(+), 13 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index decd350e..7dfd2043 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -3,6 +3,15 @@ **How to upgrade**: remove your `$GOPATH/src/github.com/kataras/iris` folder, open your command-line and execute this command: `go get -u github.com/kataras/iris/iris`. +## 4.0.0-alpha.4 -> 4.0.0-alpha.5 + +- **NEW FEATURE**: Letsencrypt.org integration[*](https://github.com/kataras/iris/issues/220) + - example [here](https://github.com/iris-contrib/examples/blob/master/letsencrypt/main.go) +- **FIX**: (ListenUNIX adds :80 to filename)[https://github.com/kataras/iris/issues/321] +- **FIX**: (Go-Bindata + ctx.Render)[https://github.com/kataras/iris/issues/315] +- **FIX** (auto-gzip doesn't really compress data in latest code)[https://github.com/kataras/iris/issues/312] + + ## 4.0.0-alpha.3 -> 4.0.0-alpha.4 diff --git a/README.md b/README.md index 4788cfde..b353b89c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ License -Releases +Releases Practical Guide/Docs
@@ -136,7 +136,7 @@ I recommend writing your API tests using this new library, [httpexpect](https:// Versioning ------------ -Current: **v4.0.0-alpha.4** +Current: **v4.0.0-alpha.5** > Iris is an active project @@ -149,6 +149,7 @@ Todo - [x] Refactor & extend sessions, split the different databases functionality to the iris-contrib[*](https://github.com/iris-contrib/sessiondb) - [x] Refactor & extends the rest render engine in order to be able to developer to use their own implemention for rendering restful types, like, for example a custom JSON implementation using no-standard go package for encode/decode[*](https://github.com/iris-contrib/response) - [x] Move the iris/websocket package's source code inside iris/websocket.go one file, to be easier to use by users without import a new package[*](https://github.com/kataras/iris/blob/master/websocket.go) +- [x] LetsEncrypt.org integration[*](https://github.com/kataras/iris/issues/220) - [ ] Implement all [opened community's feature requests](https://github.com/kataras/iris/issues?q=is%3Aissue+is%3Aopen+label%3A%22feature+request%22) - [ ] Extend i18n middleware for easier and better internalization support - [ ] Create a router as optional plugin, for optional path parts. Its name, 'ryan', taken from the community-member and donator who requested this feature @@ -179,7 +180,7 @@ License can be found [here](LICENSE). [Travis]: http://travis-ci.org/kataras/iris [License Widget]: https://img.shields.io/badge/license-MIT%20%20License%20-E91E63.svg?style=flat-square [License]: https://github.com/kataras/iris/blob/master/LICENSE -[Release Widget]: https://img.shields.io/badge/release-v4.0.0--alpha.4-blue.svg?style=flat-square +[Release Widget]: https://img.shields.io/badge/release-v4.0.0--alpha.5-blue.svg?style=flat-square [Release]: https://github.com/kataras/iris/releases [Chat Widget]: https://img.shields.io/badge/community-chat-00BCD4.svg?style=flat-square [Chat]: https://kataras.rocket.chat/channel/iris diff --git a/config/server.go b/config/server.go index 87b3e174..f94274e6 100644 --- a/config/server.go +++ b/config/server.go @@ -47,6 +47,11 @@ type Server struct { ListeningAddr string CertFile string KeyFile string + // AutoTLS enable to get certifications from the Letsencrypt + // when this configuration field is true, the CertFile & KeyFile are empty, no need to provide a key. + // + // example: https://github.com/iris-contrib/examples/blob/master/letsencyrpt/main.go + AutoTLS bool // Mode this is for unix only Mode os.FileMode // MaxRequestBodySize Maximum request body size. diff --git a/http.go b/http.go index e7d24fca..52e86cc3 100644 --- a/http.go +++ b/http.go @@ -2,6 +2,7 @@ package iris import ( "bytes" + "crypto/tls" "net" "net/http" "net/http/pprof" @@ -13,6 +14,7 @@ import ( "time" "github.com/iris-contrib/errors" + "github.com/iris-contrib/letsencrypt" "github.com/iris-contrib/logger" "github.com/kataras/iris/config" "github.com/kataras/iris/utils" @@ -282,7 +284,7 @@ func (s *Server) IsOpened() bool { // IsSecure returns true if server uses TLS, otherwise false func (s *Server) IsSecure() bool { - return s.tls + return s.tls || s.Config.AutoTLS // for any case } // Listener returns the net.Listener which this server (is) listening to @@ -300,26 +302,31 @@ func (s *Server) Host() string { // Port returns the port which server listening for // if no port given with the ListeningAddr, it returns 80 -func (s *Server) Port() (port int) { +func (s *Server) Port() int { a := s.Host() if portIdx := strings.IndexByte(a, ':'); portIdx != -1 { p, err := strconv.Atoi(a[portIdx+1:]) if err != nil { - port = 80 + if s.Config.AutoTLS { + return 443 + } + return 80 } else { - port = p + return p } - } else { - port = 80 } - return + if s.Config.AutoTLS { + return 443 + } + return 80 + } // Scheme returns http:// or https:// if SSL is enabled func (s *Server) Scheme() string { scheme := "http://" // we need to be able to take that before(for testing &debugging) and after server's listen - if s.IsSecure() || (s.Config.CertFile != "" && s.Config.KeyFile != "") { + if s.IsSecure() || (s.Config.CertFile != "" && s.Config.KeyFile != "") || s.Config.AutoTLS { scheme = "https://" } // but if virtual scheme is setted and it differs from the real scheme, return the vscheme @@ -397,8 +404,20 @@ func (s *Server) serve(l net.Listener) error { if s.Config.CertFile != "" && s.Config.KeyFile != "" { s.tls = true return s.Server.ServeTLS(s.listener, s.Config.CertFile, s.Config.KeyFile) + } else if s.Config.AutoTLS { + var m letsencrypt.Manager + if err := m.CacheFile("letsencrypt.cache"); err != nil { + return err + } + tlsConfig := &tls.Config{GetCertificate: m.GetCertificate} + + ln := tls.NewListener(l, tlsConfig) + s.tls = true + s.mu.Lock() + s.listener = ln + s.mu.Unlock() } - s.tls = false + return s.Server.Serve(s.listener) } diff --git a/iris.go b/iris.go index 6e0bdc08..659b6065 100644 --- a/iris.go +++ b/iris.go @@ -85,7 +85,7 @@ import ( const ( // Version of the iris - Version = "4.0.0-alpha.4" + Version = "4.0.0-alpha.5" banner = ` _____ _ |_ _| (_) @@ -433,6 +433,21 @@ func ListenTLS(addr string, certFile string, keyFile string) { Default.ListenTLS(addr, certFile, keyFile) } +// ListenTLSAuto starts a server listening at the specific nat address +// using key & certification taken from the letsencrypt.org 's servers +// it also starts a second 'http' server to redirect all 'http://$ADDR_HOSTNAME:80' to the' https://$ADDR' +// +// Notes: +// if you don't want the last feature you should use this method: +// iris.ListenTo(config.Server{ListeningAddr: "mydomain.com:443", AutoTLS: true}) +// it's a blocking function +// Limit : https://github.com/iris-contrib/letsencrypt/blob/master/lets.go#L142 +// +// example: https://github.com/iris-contrib/examples/blob/master/letsencyrpt/main.go +func ListenTLSAuto(addr string) { + Default.ListenTLSAuto(addr) +} + // ListenTLS Starts a https server with certificates, // if you use this method the requests of the form of 'http://' will fail // only https:// connections are allowed @@ -448,6 +463,29 @@ func (s *Framework) ListenTLS(addr string, certFile, keyFile string) { s.Must(s.ListenTo(config.Server{ListeningAddr: addr, CertFile: certFile, KeyFile: keyFile})) } +// ListenTLSAuto starts a server listening at the specific nat address +// using key & certification taken from the letsencrypt.org 's servers +// it also starts a second 'http' server to redirect all 'http://$ADDR_HOSTNAME:80' to the' https://$ADDR' +// +// Notes: +// if you don't want the last feature you should use this method: +// iris.ListenTo(config.Server{ListeningAddr: "mydomain.com:443", AutoTLS: true}) +// it's a blocking function +// Limit : https://github.com/iris-contrib/letsencrypt/blob/master/lets.go#L142 +// +// example: https://github.com/iris-contrib/examples/blob/master/letsencyrpt/main.go +func (s *Framework) ListenTLSAuto(addr string) { + if portIdx := strings.IndexByte(addr, ':'); portIdx == -1 { + addr += ":443" + } + addr = config.ServerParseAddr(addr) + + // start a secondary server (HTTP) on port 80, this is a non-blocking func + // redirects all http to the main server which is tls/ssl on port :443 + s.AddServer(config.Server{ListeningAddr: ":80", RedirectTo: "https://" + addr}) + s.Must(s.ListenTo(config.Server{ListeningAddr: addr, AutoTLS: true})) +} + // ListenUNIX starts the process of listening to the new requests using a 'socket file', this works only on unix // // It panics on error if you need a func to return an error, use the ListenTo