diff --git a/_examples/README.md b/_examples/README.md index 8e0475f7..9d42c9d7 100644 --- a/_examples/README.md +++ b/_examples/README.md @@ -23,6 +23,10 @@ Developers should read the official [documentation](https://godoc.org/gopkg.in/k * [Favicon](beginner/favicon/main.go) * [File Server](beginner/file-server/main.go) * [Send Files](beginner/send-files/main.go) + * [Stream Writer](beginner/stream-writer/main.go) + * [Listen UNIX Socket](beginner/listen-unix/main.go) + * [Listen TLS](beginner/listen-tls/main.go) + * [Listen Letsencrypt (Automatic Certifications)](beginner/listen-letsencrypt/main.go) * [Level: Intermediate](intermediate) * [Send An E-mail](intermediate/e-mail/main.go) * [Upload/Read Files](intermediate/upload-files/main.go) @@ -34,6 +38,8 @@ Developers should read the official [documentation](https://godoc.org/gopkg.in/k * [Localization and Internationalization](intermediate/i18n/main.go) * [Recovery](intermediate/recover/main.go) * [Graceful Shutdown](intermediate/graceful-shutdown/main.go) + * [Custom TCP Listener](intermediate/custom-listener/main.go) + * [Custom HTTP Server](intermediate/custom-httpserver/main.go) * [View Engine](intermediate/view) * [Overview](intermediate/view/overview/main.go) * [Embedding Templates Into Executable](intermediate/embedding-templates-into-app) @@ -58,10 +64,15 @@ Developers should read the official [documentation](https://godoc.org/gopkg.in/k * [Secure](intermediate/websockets/secure/main.go) * [Custom Go Client](intermediate/websockets/custom-go-client/main.go) * [Level: Advanced](advanced) + * [Transactions](advanced/transactions/main.go) * [HTTP Testing](advanced/httptest/main_test.go) * [Watch & Compile Typescript source files](advanced/typescript/main.go) * [Cloud Editor](advanced/cloud-editor/main.go) * [Online Visitors](advanced/online-visitors/main.go) * [URL Shortener using BoltDB](advanced/url-shortener/main.go) + * [Subdomains](advanced/subdomains) + * [Single](advanced/subdomains/single/main.go) + * [Multi](advanced/subdomains/multi/main.go) + * [Wildcard](advanced/subdomains/wildcard/main.go) > Take look at the [community examples](https://github.com/iris-contrib/examples) too! diff --git a/_examples/advanced/subdomains/multi/hosts b/_examples/advanced/subdomains/multi/hosts new file mode 100644 index 00000000..6b40c422 --- /dev/null +++ b/_examples/advanced/subdomains/multi/hosts @@ -0,0 +1,28 @@ +# Copyright (c) 1993-2009 Microsoft Corp. +# +# This is a sample HOSTS file used by Microsoft TCP/IP for Windows. +# +# This file contains the mappings of IP addresses to host names. Each +# entry should be kept on an individual line. The IP address should +# be placed in the first column followed by the corresponding host name. +# The IP address and the host name should be separated by at least one +# space. +# +# Additionally, comments (such as these) may be inserted on individual +# lines or following the machine name denoted by a '#' symbol. +# +# For example: +# +# 102.54.94.97 rhino.acme.com # source server +# 38.25.63.10 x.acme.com # x client host + +# localhost name resolution is handled within DNS itself. +127.0.0.1 localhost +::1 localhost +#-IRIS-For development machine, you have to configure your dns also for online, search google how to do it if you don't know + +127.0.0.1 domain.local +127.0.0.1 system.domain.local +127.0.0.1 dashboard.domain.local + +#-END IRIS- diff --git a/_examples/advanced/subdomains/multi/main.go b/_examples/advanced/subdomains/multi/main.go new file mode 100644 index 00000000..8a7bcbd8 --- /dev/null +++ b/_examples/advanced/subdomains/multi/main.go @@ -0,0 +1,39 @@ +package main + +import ( + "gopkg.in/kataras/iris.v6" + "gopkg.in/kataras/iris.v6/adaptors/httprouter" +) + +func main() { + app := iris.New() + app.Adapt(iris.DevLogger()) + // subdomains works with all available routers, like other features too. + app.Adapt(httprouter.New()) + + /* + * Setup static files + */ + + app.StaticWeb("/assets", "./public/assets") + app.StaticWeb("/upload_resources", "./public/upload_resources") + + dashboard := app.Party("dashboard.") + { + dashboard.Get("/", func(ctx *iris.Context) { + ctx.Writef("HEY FROM dashboard") + }) + } + system := app.Party("system.") + { + system.Get("/", func(ctx *iris.Context) { + ctx.Writef("HEY FROM system") + }) + } + + app.Get("/", func(ctx *iris.Context) { + ctx.Writef("HEY FROM frontend /") + }) + /* test this on firefox, because the domain is not real (because of .local), on firefox this will fail, but you can test it with other domain */ + app.Listen("domain.local:80") // for beginners: look ../hosts file +} diff --git a/_examples/advanced/subdomains/multi/public/assets/images/test.ico b/_examples/advanced/subdomains/multi/public/assets/images/test.ico new file mode 100644 index 00000000..5987ec74 Binary files /dev/null and b/_examples/advanced/subdomains/multi/public/assets/images/test.ico differ diff --git a/_examples/advanced/subdomains/multi/public/upload_resources/iris_favicon_32_32.ico b/_examples/advanced/subdomains/multi/public/upload_resources/iris_favicon_32_32.ico new file mode 100644 index 00000000..5987ec74 Binary files /dev/null and b/_examples/advanced/subdomains/multi/public/upload_resources/iris_favicon_32_32.ico differ diff --git a/_examples/advanced/subdomains/single/hosts b/_examples/advanced/subdomains/single/hosts new file mode 100644 index 00000000..8e5c20d7 --- /dev/null +++ b/_examples/advanced/subdomains/single/hosts @@ -0,0 +1,27 @@ +# Copyright (c) 1993-2009 Microsoft Corp. +# +# This is a sample HOSTS file used by Microsoft TCP/IP for Windows. +# +# This file contains the mappings of IP addresses to host names. Each +# entry should be kept on an individual line. The IP address should +# be placed in the first column followed by the corresponding host name. +# The IP address and the host name should be separated by at least one +# space. +# +# Additionally, comments (such as these) may be inserted on individual +# lines or following the machine name denoted by a '#' symbol. +# +# For example: +# +# 102.54.94.97 rhino.acme.com # source server +# 38.25.63.10 x.acme.com # x client host + +# localhost name resolution is handled within DNS itself. +127.0.0.1 localhost +::1 localhost +#-IRIS-For development machine, you have to configure your dns also for online, search google how to do it if you don't know + +127.0.0.1 mydomain.com +127.0.0.1 admin.mydomain.com + +#-END IRIS- diff --git a/_examples/advanced/subdomains/single/main.go b/_examples/advanced/subdomains/single/main.go new file mode 100644 index 00000000..eec51168 --- /dev/null +++ b/_examples/advanced/subdomains/single/main.go @@ -0,0 +1,43 @@ +// Package main register static subdomains, simple as parties, check ./hosts if you use windows +package main + +import ( + "gopkg.in/kataras/iris.v6" + "gopkg.in/kataras/iris.v6/adaptors/httprouter" +) + +func main() { + app := iris.New() + app.Adapt(iris.DevLogger()) + // subdomains works with all available routers, like other features too. + app.Adapt(httprouter.New()) + + // no order, you can register subdomains at the end also. + admin := app.Party("admin.") + { + // admin.mydomain.com + admin.Get("/", func(c *iris.Context) { + c.Writef("INDEX FROM admin.mydomain.com") + }) + // admin.mydomain.com/hey + admin.Get("/hey", func(c *iris.Context) { + c.Writef("HEY FROM admin.mydomain.com/hey") + }) + // admin.mydomain.com/hey2 + admin.Get("/hey2", func(c *iris.Context) { + c.Writef("HEY SECOND FROM admin.mydomain.com/hey") + }) + } + + // mydomain.com/ + app.Get("/", func(c *iris.Context) { + c.Writef("INDEX FROM no-subdomain hey") + }) + + // mydomain.com/hey + app.Get("/hey", func(c *iris.Context) { + c.Writef("HEY FROM no-subdomain hey") + }) + + app.Listen("mydomain.com:80") // for beginners: look ../hosts file +} diff --git a/_examples/advanced/subdomains/wildcard/hosts b/_examples/advanced/subdomains/wildcard/hosts new file mode 100644 index 00000000..743ed62f --- /dev/null +++ b/_examples/advanced/subdomains/wildcard/hosts @@ -0,0 +1,30 @@ +# Copyright (c) 1993-2009 Microsoft Corp. +# +# This is a sample HOSTS file used by Microsoft TCP/IP for Windows. +# +# This file contains the mappings of IP addresses to host names. Each +# entry should be kept on an individual line. The IP address should +# be placed in the first column followed by the corresponding host name. +# The IP address and the host name should be separated by at least one +# space. +# +# Additionally, comments (such as these) may be inserted on individual +# lines or following the machine name denoted by a '#' symbol. +# +# For example: +# +# 102.54.94.97 rhino.acme.com # source server +# 38.25.63.10 x.acme.com # x client host + +# localhost name resolution is handled within DNS itself. +127.0.0.1 localhost +::1 localhost +#-IRIS-For development machine, you have to configure your dns also for online, search google how to do it if you don't know +127.0.0.1 mydomain.com +127.0.0.1 username1.mydomain.com +127.0.0.1 username2.mydomain.com +127.0.0.1 username3.mydomain.com +127.0.0.1 username4.mydomain.com +127.0.0.1 username5.mydomain.com + +#-END IRIS- diff --git a/_examples/advanced/subdomains/wildcard/main.go b/_examples/advanced/subdomains/wildcard/main.go new file mode 100644 index 00000000..4cc48d46 --- /dev/null +++ b/_examples/advanced/subdomains/wildcard/main.go @@ -0,0 +1,71 @@ +// Package main an example on how to catch dynamic subdomains - wildcard. +// On the first example (subdomains_1) we saw how to create routes for static subdomains, subdomains you know that you will have. +// Here we will see an example how to catch unknown subdomains, dynamic subdomains, like username.mydomain.com:8080. +package main + +import ( + "gopkg.in/kataras/iris.v6" + "gopkg.in/kataras/iris.v6/adaptors/httprouter" +) + +// register a dynamic-wildcard subdomain to your server machine(dns/...) first, check ./hosts if you use windows. +// run this file and try to redirect: http://username1.mydomain.com:8080/ , http://username2.mydomain.com:8080/ , http://username1.mydomain.com/something, http://username1.mydomain.com/something/sadsadsa + +func main() { + app := iris.New() + app.Adapt(iris.DevLogger()) + // subdomains works with all available routers, like other features too. + app.Adapt(httprouter.New()) + + /* Keep note that you can use both type of subdomains (named and wildcard(*.) ) + admin.mydomain.com, and for other the Party(*.) but this is not this example's purpose + + admin := app.Party("admin.") + { + // admin.mydomain.com + admin.Get("/", func(ctx *iris.Context) { + ctx.Writef("INDEX FROM admin.mydomain.com") + }) + // admin.mydomain.com/hey + admin.Get("/hey", func(ctx *iris.Context) { + ctx.Writef("HEY FROM admin.mydomain.com/hey") + }) + // admin.mydomain.com/hey2 + admin.Get("/hey2", func(ctx *iris.Context) { + ctx.Writef("HEY SECOND FROM admin.mydomain.com/hey") + }) + }*/ + + // no order, you can register subdomains at the end also. + dynamicSubdomains := app.Party("*.") + { + dynamicSubdomains.Get("/", dynamicSubdomainHandler) + + dynamicSubdomains.Get("/something", dynamicSubdomainHandler) + + dynamicSubdomains.Get("/something/:param1", dynamicSubdomainHandlerWithParam) + } + + app.Get("/", func(ctx *iris.Context) { + ctx.Writef("Hello from mydomain.com path: %s", ctx.Path()) + }) + + app.Get("/hello", func(ctx *iris.Context) { + ctx.Writef("Hello from mydomain.com path: %s", ctx.Path()) + }) + + app.Listen("mydomain.com:8080") // for beginners: look ../hosts file +} + +func dynamicSubdomainHandler(ctx *iris.Context) { + username := ctx.Subdomain() + ctx.Writef("Hello from dynamic subdomain path: %s, here you can handle the route for dynamic subdomains, handle the user: %s", ctx.Path(), username) + // if http://username4.mydomain.com:8080/ prints: + // Hello from dynamic subdomain path: /, here you can handle the route for dynamic subdomains, handle the user: username4 +} + +func dynamicSubdomainHandlerWithParam(ctx *iris.Context) { + username := ctx.Subdomain() + ctx.Writef("Hello from dynamic subdomain path: %s, here you can handle the route for dynamic subdomains, handle the user: %s", ctx.Path(), username) + ctx.Writef("THE PARAM1 is: %s", ctx.Param("param1")) +} diff --git a/_examples/advanced/transactions/main.go b/_examples/advanced/transactions/main.go new file mode 100644 index 00000000..4f6995f5 --- /dev/null +++ b/_examples/advanced/transactions/main.go @@ -0,0 +1,56 @@ +package main + +import ( + "gopkg.in/kataras/iris.v6" + "gopkg.in/kataras/iris.v6/adaptors/httprouter" +) + +func main() { + app := iris.New() + app.Adapt(iris.DevLogger()) + // subdomains works with all available routers, like other features too. + app.Adapt(httprouter.New()) + + app.Get("/", func(ctx *iris.Context) { + ctx.BeginTransaction(func(t *iris.Transaction) { + // OPTIONAl STEP: , if true then the next transictions will not be executed if this transiction fails + // t.SetScope(iris.RequestTransactionScope) + + // OPTIONAL STEP: + // create a new custom type of error here to keep track of the status code and reason message + err := iris.NewTransactionErrResult() + + // we should use t.Context if we want to rollback on any errors lives inside this function clojure. + t.Context.Text(iris.StatusOK, "Blablabla this should not be sent to the client because we will fill the err with a message and status") + + // virtualize a fake error here, for the shake of the example + fail := true + if fail { + err.StatusCode = iris.StatusInternalServerError + // NOTE: if empty reason then the default or the custom http error will be fired (like ctx.EmitError) + err.Reason = "Error: Virtual failure!!" + } + + // OPTIONAl STEP: + // but useful if we want to post back an error message to the client if the transaction failed. + // if the reason is empty then the transaction completed succesfuly, + // otherwise we rollback the whole response writer's body, + // headers and cookies, status code and everything lives inside this transaction + t.Complete(err) + }) + + ctx.BeginTransaction(func(t *iris.Transaction) { + t.Context.HTML(iris.StatusOK, + "

This will sent at all cases because it lives on different transaction and it doesn't fails

") + // * if we don't have any 'throw error' logic then no need of scope.Complete() + }) + + // OPTIONAL, depends on the usage: + // at any case, what ever happens inside the context's transactions send this to the client + ctx.HTML(iris.StatusOK, "

Let's add a second html message to the response, "+ + "if the transaction was failed and it was request scoped then this message would "+ + "not been shown. But it has a transient scope(default) so, it is visible as expected!

") + }) + + app.Listen(":8080") +} diff --git a/_examples/beginner/listen-letsencrypt/main.go b/_examples/beginner/listen-letsencrypt/main.go new file mode 100644 index 00000000..782af887 --- /dev/null +++ b/_examples/beginner/listen-letsencrypt/main.go @@ -0,0 +1,35 @@ +// Package main provide one-line integration with letsencrypt.org +package main + +import ( + "gopkg.in/kataras/iris.v6" + "gopkg.in/kataras/iris.v6/adaptors/httprouter" +) + +func main() { + app := iris.New() + // output startup banner and error logs on os.Stdout + app.Adapt(iris.DevLogger()) + // set the router, you can choose gorillamux too + app.Adapt(httprouter.New()) + + app.Get("/", func(ctx *iris.Context) { + ctx.Writef("Hello from SECURE SERVER!") + }) + + app.Get("/test2", func(ctx *iris.Context) { + ctx.Writef("Welcome to secure server from /test2!") + }) + + app.Get("/redirect", func(ctx *iris.Context) { + ctx.Redirect("/test2") + }) + + // This will provide you automatic certification & key from letsencrypt.org's servers + // it also starts a second 'http://' server which will redirect all 'http://$PATH' requests to 'https://$PATH' + + // NOTE: may not work on local addresses like this, + // use it on a real domain, because + // it uses the "golang.org/x/crypto/acme/autocert" package. + app.ListenLETSENCRYPT("localhost:443") +} diff --git a/_examples/beginner/listen-tls/main.go b/_examples/beginner/listen-tls/main.go new file mode 100644 index 00000000..fb460164 --- /dev/null +++ b/_examples/beginner/listen-tls/main.go @@ -0,0 +1,37 @@ +package main + +import ( + "gopkg.in/kataras/iris.v6" + "gopkg.in/kataras/iris.v6/adaptors/httprouter" +) + +const host = "127.0.0.1:443" + +func main() { + app := iris.New() + // output startup banner and error logs on os.Stdout + app.Adapt(iris.DevLogger()) + // set the router, you can choose gorillamux too + app.Adapt(httprouter.New()) + + app.Get("/", func(ctx *iris.Context) { + ctx.Writef("Hello from the SECURE server") + }) + + app.Get("/mypath", func(ctx *iris.Context) { + ctx.Writef("Hello from the SECURE server on path /mypath") + }) + + // 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 + + iris.Proxy(":80", "https://"+host) + // start the MAIN server (HTTPS) on port 443, this is a blocking func + app.ListenTLS(host, "mycert.cert", "mykey.key") + + // now if you navigate to http://127.0.0.1/mypath it will + // send you back to https://127.0.0.1:443/mypath (https://127.0.0.1/mypath) + // + // go to the listen-letsencrypt example to view how you can integrate your server + // to get automatic certification and key from the letsencrypt.org 's servers. +} diff --git a/_examples/beginner/listen-unix/main.go b/_examples/beginner/listen-unix/main.go new file mode 100644 index 00000000..68632b7c --- /dev/null +++ b/_examples/beginner/listen-unix/main.go @@ -0,0 +1,22 @@ +package main + +import ( + "gopkg.in/kataras/iris.v6" + "gopkg.in/kataras/iris.v6/adaptors/httprouter" +) + +const host = "127.0.0.1:443" + +func main() { + app := iris.New() + // output startup banner and error logs on os.Stdout + app.Adapt(iris.DevLogger()) + // set the router, you can choose gorillamux too + app.Adapt(httprouter.New()) + + app.Get("/", func(ctx *iris.Context) { + ctx.Writef("Hello from the server") + }) + + app.ListenUNIX("/tmp/srv.sock", 0666) +} diff --git a/_examples/beginner/stream-writer/main.go b/_examples/beginner/stream-writer/main.go new file mode 100644 index 00000000..3b87aa85 --- /dev/null +++ b/_examples/beginner/stream-writer/main.go @@ -0,0 +1,56 @@ +package main + +import ( + "fmt" // just an optional helper + "io" + "time" // showcase the delay + + "gopkg.in/kataras/iris.v6" + "gopkg.in/kataras/iris.v6/adaptors/httprouter" +) + +func main() { + app := iris.New() + // output startup banner and error logs on os.Stdout + app.Adapt(iris.DevLogger()) + // set the router, you can choose gorillamux too + app.Adapt(httprouter.New()) + + timeWaitForCloseStream := 4 * time.Second + + app.Get("/", func(ctx *iris.Context) { + i := 0 + // goroutine in order to no block and just wait, + // goroutine is OPTIONAL and not a very good option but it depends on the needs + // Look the streaming_simple_2 for an alternative code style + // Send the response in chunks and wait for a second between each chunk. + go ctx.StreamWriter(func(w io.Writer) bool { + i++ + fmt.Fprintf(w, "this is a message number %d\n", i) // write + time.Sleep(time.Second) // imaginary delay + if i == 4 { + return false // close and flush + } + return true // continue write + }) + + // when this handler finished the client should be see the stream writer's contents + // simulate a job here... + time.Sleep(timeWaitForCloseStream) + }) + + app.Get("/alternative", func(ctx *iris.Context) { + // Send the response in chunks and wait for a second between each chunk. + ctx.StreamWriter(func(w io.Writer) bool { + for i := 1; i <= 4; i++ { + fmt.Fprintf(w, "this is a message number %d\n", i) // write + time.Sleep(time.Second) + } + + // when this handler finished the client should be see the stream writer's contents + return false // stop and flush the contents + }) + }) + + app.Listen(":8080") +} diff --git a/_examples/intermediate/custom-httpserver/main.go b/_examples/intermediate/custom-httpserver/main.go new file mode 100644 index 00000000..932208cd --- /dev/null +++ b/_examples/intermediate/custom-httpserver/main.go @@ -0,0 +1,33 @@ +package main + +import ( + "net/http" + + "gopkg.in/kataras/iris.v6" + "gopkg.in/kataras/iris.v6/adaptors/httprouter" +) + +func main() { + app := iris.New() + // output startup banner and error logs on os.Stdout + app.Adapt(iris.DevLogger()) + // set the router, you can choose gorillamux too + app.Adapt(httprouter.New()) + + app.Get("/", func(ctx *iris.Context) { + ctx.Writef("Hello from the server") + }) + + app.Get("/mypath", func(ctx *iris.Context) { + ctx.Writef("Hello from %s", ctx.Path()) + }) + + // call .Boot before use the 'app' as an http.Handler on a custom http.Server + app.Boot() + + // create our custom fasthttp server and assign the Handler/Router + fsrv := &http.Server{Handler: app, Addr: ":8080"} + fsrv.ListenAndServe() + + // navigate to http://127.0.0.1:8080/mypath +} diff --git a/_examples/intermediate/custom-listener/main.go b/_examples/intermediate/custom-listener/main.go new file mode 100644 index 00000000..39f08848 --- /dev/null +++ b/_examples/intermediate/custom-listener/main.go @@ -0,0 +1,33 @@ +package main + +import ( + "net" + + "gopkg.in/kataras/iris.v6" + "gopkg.in/kataras/iris.v6/adaptors/httprouter" +) + +func main() { + app := iris.New() + // output startup banner and error logs on os.Stdout + app.Adapt(iris.DevLogger()) + // set the router, you can choose gorillamux too + app.Adapt(httprouter.New()) + + app.Get("/", func(ctx *iris.Context) { + ctx.Writef("Hello from the server") + }) + + app.Get("/mypath", func(ctx *iris.Context) { + ctx.Writef("Hello from %s", ctx.Path()) + }) + + // create our custom listener + ln, err := net.Listen("tcp4", ":8080") + if err != nil { + panic(err) + } + + // use of the custom listener + app.Serve(ln) +} diff --git a/addr.go b/addr.go index fc8f01dd..9c4b6e24 100644 --- a/addr.go +++ b/addr.go @@ -37,18 +37,18 @@ func TCPKeepAlive(addr string) (net.Listener, error) { } // UNIX returns a new unix(file) Listener -func UNIX(addr string, mode os.FileMode) (net.Listener, error) { - if errOs := os.Remove(addr); errOs != nil && !os.IsNotExist(errOs) { - return nil, errRemoveUnix.Format(addr, errOs.Error()) +func UNIX(socketFile string, mode os.FileMode) (net.Listener, error) { + if errOs := os.Remove(socketFile); errOs != nil && !os.IsNotExist(errOs) { + return nil, errRemoveUnix.Format(socketFile, errOs.Error()) } - listener, err := net.Listen("unix", addr) + listener, err := net.Listen("unix", socketFile) if err != nil { return nil, errPortAlreadyUsed.AppendErr(err) } - if err = os.Chmod(addr, mode); err != nil { - return nil, errChmod.Format(mode, addr, err.Error()) + if err = os.Chmod(socketFile, mode); err != nil { + return nil, errChmod.Format(mode, socketFile, err.Error()) } return listener, nil @@ -84,14 +84,16 @@ func CERT(addr string, cert tls.Certificate) (net.Listener, error) { } // LETSENCRYPT returns a new Automatic TLS Listener using letsencrypt.org service -// receives two parameters, the first is the domain of the server -// and the second is optionally, the cache directory, if you skip it then the cache directory is "./certcache" +// receives three parameters, +// the first is the host of the server, +// second can be the server name(domain) or empty if skip verification is the expected behavior (not recommended) +// and the third is optionally, the cache directory, if you skip it then the cache directory is "./certcache" // if you want to disable cache directory then simple give it a value of empty string "" // // does NOT supports localhost domains for testing. // // this is the recommended function to use when you're ready for production state -func LETSENCRYPT(addr string, cacheDirOptional ...string) (net.Listener, error) { +func LETSENCRYPT(addr string, serverName string, cacheDirOptional ...string) (net.Listener, error) { if portIdx := strings.IndexByte(addr, ':'); portIdx == -1 { addr += ":443" } @@ -109,15 +111,22 @@ func LETSENCRYPT(addr string, cacheDirOptional ...string) (net.Listener, error) m := autocert.Manager{ Prompt: autocert.AcceptTOS, } // HostPolicy is missing, if user wants it, then she/he should manually - // configure the autocertmanager and use the `iris.Default.Serve` to pass that listener if cacheDir == "" { // then the user passed empty by own will, then I guess she/he doesnt' want any cache directory } else { m.Cache = autocert.DirCache(cacheDir) } - tlsConfig := &tls.Config{GetCertificate: m.GetCertificate} + + // use InsecureSkipVerify or ServerName to a value + if serverName == "" { + // if server name is invalid then bypass it + tlsConfig.InsecureSkipVerify = true + } else { + tlsConfig.ServerName = serverName + } + tlsLn := tls.NewListener(ln, tlsConfig) return tlsLn, nil diff --git a/iris.go b/iris.go index 490a8616..f4d52191 100644 --- a/iris.go +++ b/iris.go @@ -579,6 +579,7 @@ func (s *Framework) Listen(addr string) { ln, err := TCPKeepAlive(addr) if err != nil { s.handlePanic(err) + return } s.Must(s.Serve(ln)) @@ -620,14 +621,14 @@ func (s *Framework) ListenTLS(addr string, certFile, keyFile string) { // ListenLETSENCRYPT starts a server listening at the specific nat address // using key & certification taken from the letsencrypt.org 's servers // it's also starts a second 'http' server to redirect all 'http://$ADDR_HOSTNAME:80' to the' https://$ADDR' -// it creates a cache file to store the certifications, for performance reasons, this file by-default is "./letsencrypt.cache" +// it creates a cache file to store the certifications, for performance reasons, this file by-default is "./certcache" // if you skip the second parameter then the cache file is "./letsencrypt.cache" // if you want to disable cache then simple pass as second argument an empty empty string "" // // Note: HTTP/2 Push is not working with LETSENCRYPT, you have to use ListenTLS to enable HTTP/2 // Because net/http's author didn't exported the functions to tell the server that is using HTTP/2... // -// example: https://github.com/iris-contrib/examples/blob/master/letsencrypt/main.go +// example: https://github.com/kataras/iris/blob/v6/_examples/beginner/listen-letsencrypt/main.go func (s *Framework) ListenLETSENCRYPT(addr string, cacheFileOptional ...string) { addr = ParseHost(addr) @@ -643,9 +644,10 @@ func (s *Framework) ListenLETSENCRYPT(addr string, cacheFileOptional ...string) } } - ln, err := LETSENCRYPT(addr, cacheFileOptional...) + ln, err := LETSENCRYPT(addr, addr, cacheFileOptional...) if err != nil { s.handlePanic(err) + return } // starts a second server which listening on HOST:80 to redirect all requests to the HTTPS://HOST:PORT @@ -653,21 +655,23 @@ func (s *Framework) ListenLETSENCRYPT(addr string, cacheFileOptional ...string) s.Must(s.Serve(ln)) } -// ListenUNIX starts the process of listening to the new requests using a 'socket file', this works only on unix -// +// ListenUNIX starts the process of listening to the new requests using a 'socket file', +// Note: this works only on unix // // If you need to manually monitor any error please use `.Serve` instead. -func (s *Framework) ListenUNIX(addr string, mode os.FileMode) { - // *on unix listen we don't parse the host, because sometimes it causes problems to the user - if s.Config.VHost == "" { - s.Config.VHost = addr - // this will be set as the front-end listening addr - } - ln, err := UNIX(addr, mode) +// +// example: https://github.com/kataras/iris/blob/v6/_examples/beginner/listen-unix/main.go +func (s *Framework) ListenUNIX(socketFile string, mode os.FileMode) { + ln, err := UNIX(socketFile, mode) if err != nil { s.handlePanic(err) + return + } + // *on unix listen we don't parse the host, because sometimes it causes problems to the user + if s.Config.VHost == "" { + s.Config.VHost = ln.Addr().String() + // this will be set as the front-end listening addr } - s.Must(s.Serve(ln)) }