mirror of
https://github.com/kataras/iris.git
synced 2025-12-21 03:47:04 +00:00
Add More Examples & Categorized in Folders & TOC
Former-commit-id: ce4d711a75a4ba08ffab075e6baa88724725885b
This commit is contained in:
57
_examples/examples/intermediate/basicauth/main.go
Normal file
57
_examples/examples/intermediate/basicauth/main.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/middleware/basicauth"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger()) // adapt a simple internal logger to print any errors
|
||||
app.Adapt(httprouter.New()) // adapt a router, you can use gorillamux too
|
||||
|
||||
authConfig := basicauth.Config{
|
||||
Users: map[string]string{"myusername": "mypassword", "mySecondusername": "mySecondpassword"},
|
||||
Realm: "Authorization Required", // defaults to "Authorization Required"
|
||||
ContextKey: "mycustomkey", // defaults to "user"
|
||||
Expires: time.Duration(30) * time.Minute,
|
||||
}
|
||||
|
||||
authentication := basicauth.New(authConfig)
|
||||
app.Get("/", func(ctx *iris.Context) { ctx.Redirect("/admin") })
|
||||
// to global app.Use(authentication) (or app.UseGlobal before the .Listen)
|
||||
// to routes
|
||||
/*
|
||||
app.Get("/mysecret", authentication, func(ctx *iris.Context) {
|
||||
username := ctx.GetString("mycustomkey") // the Contextkey from the authConfig
|
||||
ctx.Writef("Hello authenticated user: %s ", username)
|
||||
})
|
||||
*/
|
||||
|
||||
// to party
|
||||
|
||||
needAuth := app.Party("/admin", authentication)
|
||||
{
|
||||
//http://localhost:8080/admin
|
||||
needAuth.Get("/", func(ctx *iris.Context) {
|
||||
username := ctx.GetString("mycustomkey") // the Contextkey from the authConfig
|
||||
ctx.Writef("Hello authenticated user: %s from: %s ", username, ctx.Path())
|
||||
})
|
||||
// http://localhost:8080/admin/profile
|
||||
needAuth.Get("/profile", func(ctx *iris.Context) {
|
||||
username := ctx.GetString("mycustomkey") // the Contextkey from the authConfig
|
||||
ctx.Writef("Hello authenticated user: %s from: %s ", username, ctx.Path())
|
||||
})
|
||||
// http://localhost:8080/admin/settings
|
||||
needAuth.Get("/settings", func(ctx *iris.Context) {
|
||||
username := authConfig.User(ctx) // shortcut for ctx.GetString("mycustomkey")
|
||||
ctx.Writef("Hello authenticated user: %s from: %s ", username, ctx.Path())
|
||||
})
|
||||
}
|
||||
|
||||
// open http://localhost:8080/admin
|
||||
app.Listen(":8080")
|
||||
}
|
||||
82
_examples/examples/intermediate/cache-markdown/main.go
Normal file
82
_examples/examples/intermediate/cache-markdown/main.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
)
|
||||
|
||||
var testMarkdownContents = `## Hello Markdown
|
||||
|
||||
This is a sample of Markdown contents
|
||||
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
All features of Sundown are supported, including:
|
||||
|
||||
* **Compatibility**. The Markdown v1.0.3 test suite passes with
|
||||
the --tidy option. Without --tidy, the differences are
|
||||
mostly in whitespace and entity escaping, where blackfriday is
|
||||
more consistent and cleaner.
|
||||
|
||||
* **Common extensions**, including table support, fenced code
|
||||
blocks, autolinks, strikethroughs, non-strict emphasis, etc.
|
||||
|
||||
* **Safety**. Blackfriday is paranoid when parsing, making it safe
|
||||
to feed untrusted user input without fear of bad things
|
||||
happening. The test suite stress tests this and there are no
|
||||
known inputs that make it crash. If you find one, please let me
|
||||
know and send me the input that does it.
|
||||
|
||||
NOTE: "safety" in this context means *runtime safety only*. In order to
|
||||
protect yourself against JavaScript injection in untrusted content, see
|
||||
[this example](https://github.com/russross/blackfriday#sanitize-untrusted-content).
|
||||
|
||||
* **Fast processing**. It is fast enough to render on-demand in
|
||||
most web applications without having to cache the output.
|
||||
|
||||
* **Thread safety**. You can run multiple parsers in different
|
||||
goroutines without ill effect. There is no dependence on global
|
||||
shared state.
|
||||
|
||||
* **Minimal dependencies**. Blackfriday only depends on standard
|
||||
library packages in Go. The source code is pretty
|
||||
self-contained, so it is easy to add to any project, including
|
||||
Google App Engine projects.
|
||||
|
||||
* **Standards compliant**. Output successfully validates using the
|
||||
W3C validation tool for HTML 4.01 and XHTML 1.0 Transitional.
|
||||
|
||||
[this is a link](https://github.com/kataras/iris) `
|
||||
|
||||
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("/hi", app.Cache(func(c *iris.Context) {
|
||||
c.WriteString("Hi this is a big content, do not try cache on small content it will not make any significant difference!")
|
||||
}, time.Duration(10)*time.Second))
|
||||
|
||||
bodyHandler := func(ctx *iris.Context) {
|
||||
ctx.Markdown(iris.StatusOK, testMarkdownContents)
|
||||
}
|
||||
|
||||
expiration := time.Duration(5 * time.Second)
|
||||
|
||||
app.Get("/", app.Cache(bodyHandler, expiration))
|
||||
|
||||
// if expiration is <=time.Second then the cache tries to set the expiration from the "cache-control" maxage header's value(in seconds)
|
||||
// // if this header doesn't founds then the default is 5 minutes
|
||||
app.Get("/cache_control", app.Cache(func(ctx *iris.Context) {
|
||||
ctx.HTML(iris.StatusOK, "<h1>Hello!</h1>")
|
||||
}, -1))
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
43
_examples/examples/intermediate/cors/main.go
Normal file
43
_examples/examples/intermediate/cors/main.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/cors"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger())
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
crs := cors.New(cors.Options{
|
||||
AllowedOrigins: []string{"*"},
|
||||
AllowCredentials: true,
|
||||
})
|
||||
|
||||
app.Adapt(crs) // this line should be added
|
||||
// adaptor supports cors allowed methods, middleware does not.
|
||||
|
||||
// if you want per-route-only cors
|
||||
// then you should check https://github.com/iris-contrib/middleware/tree/master/cors
|
||||
|
||||
v1 := app.Party("/api/v1")
|
||||
{
|
||||
v1.Post("/home", func(c *iris.Context) {
|
||||
app.Log(iris.DevMode, "lalala")
|
||||
c.WriteString("Hello from /home")
|
||||
})
|
||||
v1.Get("/g", func(c *iris.Context) {
|
||||
app.Log(iris.DevMode, "lalala")
|
||||
c.WriteString("Hello from /home")
|
||||
})
|
||||
v1.Post("/h", func(c *iris.Context) {
|
||||
app.Log(iris.DevMode, "lalala")
|
||||
c.WriteString("Hello from /home")
|
||||
})
|
||||
}
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
77
_examples/examples/intermediate/e-mail/main.go
Normal file
77
_examples/examples/intermediate/e-mail/main.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/kataras/go-mailer"
|
||||
"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())
|
||||
|
||||
// change these to your own settings
|
||||
cfg := mailer.Config{
|
||||
Host: "smtp.mailgun.org",
|
||||
Username: "postmaster@sandbox661c307650f04e909150b37c0f3b2f09.mailgun.org",
|
||||
Password: "38304272b8ee5c176d5961dc155b2417",
|
||||
Port: 587,
|
||||
}
|
||||
// change these to your e-mail to check if that works
|
||||
|
||||
// create the service
|
||||
mailService := mailer.New(cfg)
|
||||
|
||||
var to = []string{"kataras2006@hotmail.com"}
|
||||
|
||||
// standalone
|
||||
|
||||
//mailService.Send("iris e-mail test subject", "</h1>outside of context before server's listen!</h1>", to...)
|
||||
|
||||
//inside handler
|
||||
app.Get("/send", func(ctx *iris.Context) {
|
||||
content := `<h1>Hello From Iris web framework</h1> <br/><br/> <span style="color:blue"> This is the rich message body </span>`
|
||||
|
||||
err := mailService.Send("iris e-mail just t3st subject", content, to...)
|
||||
|
||||
if err != nil {
|
||||
ctx.HTML(200, "<b> Problem while sending the e-mail: "+err.Error())
|
||||
} else {
|
||||
ctx.HTML(200, "<h1> SUCCESS </h1>")
|
||||
}
|
||||
})
|
||||
|
||||
// send a body by template
|
||||
app.Get("/send/template", func(ctx *iris.Context) {
|
||||
// we will not use ctx.Render
|
||||
// because we don't want to render to the client
|
||||
// we need the templates' parsed result as raw bytes
|
||||
// so we make use of the bytes.Buffer which is an io.Writer
|
||||
// which being expected on app.Render parameter first.
|
||||
//
|
||||
// the rest of the parameters are the same and the behavior is the same as ctx.Render,
|
||||
// except the 'where to render'
|
||||
buff := &bytes.Buffer{}
|
||||
|
||||
app.Render(buff, "body.html", iris.Map{
|
||||
"Message": " his is the rich message body sent by a template!!",
|
||||
"Footer": "The footer of this e-mail!",
|
||||
})
|
||||
content := buff.String()
|
||||
|
||||
err := mailService.Send("iris e-mail just t3st subject", content, to...)
|
||||
|
||||
if err != nil {
|
||||
ctx.HTML(iris.StatusOK, "<b> Problem while sending the e-mail: "+err.Error())
|
||||
} else {
|
||||
ctx.HTML(iris.StatusOK, "<h1> SUCCESS </h1>")
|
||||
}
|
||||
})
|
||||
app.Listen(":8080")
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<h1>Hello From Iris web framework</h1>
|
||||
<br />
|
||||
<br />
|
||||
<span style="color: red"> {{.Message}}</span>
|
||||
<hr />
|
||||
|
||||
<b> {{.Footer}} </b>
|
||||
45
_examples/examples/intermediate/flash-messages/main.go
Normal file
45
_examples/examples/intermediate/flash-messages/main.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/sessions"
|
||||
)
|
||||
|
||||
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())
|
||||
sess := sessions.New(sessions.Config{Cookie: "myappsessionid"})
|
||||
app.Adapt(sess)
|
||||
|
||||
app.Get("/set", func(ctx *iris.Context) {
|
||||
ctx.Session().SetFlash("name", "iris")
|
||||
ctx.Writef("Message setted, is available for the next request")
|
||||
})
|
||||
|
||||
app.Get("/get", func(ctx *iris.Context) {
|
||||
name := ctx.Session().GetFlashString("name")
|
||||
if name != "" {
|
||||
ctx.Writef("Empty name!!")
|
||||
return
|
||||
}
|
||||
ctx.Writef("Hello %s", name)
|
||||
})
|
||||
|
||||
app.Get("/test", func(ctx *iris.Context) {
|
||||
name := ctx.Session().GetFlashString("name")
|
||||
if name != "" {
|
||||
ctx.Writef("Empty name!!")
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Writef("Ok you are comming from /set ,the value of the name is %s", name)
|
||||
ctx.Writef(", and again from the same context: %s", name)
|
||||
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
32
_examples/examples/intermediate/graceful-shutdown/main.go
Normal file
32
_examples/examples/intermediate/graceful-shutdown/main.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"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("/hi", func(ctx *iris.Context) {
|
||||
ctx.HTML(iris.StatusOK, " <h1>hi, I just exist in order to see if the server is closed</h1>")
|
||||
})
|
||||
|
||||
app.Adapt(iris.EventPolicy{
|
||||
// Interrupt Event means when control+C pressed on terminal.
|
||||
Interrupted: func(*iris.Framework) {
|
||||
// shut down gracefully, but wait 5 seconds the maximum before closed
|
||||
ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
app.Shutdown(ctx)
|
||||
},
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
hi = Γεια, %s
|
||||
@@ -0,0 +1 @@
|
||||
hi = hello, %s
|
||||
@@ -0,0 +1 @@
|
||||
hi = 您好,%s
|
||||
51
_examples/examples/intermediate/i18n/main.go
Normal file
51
_examples/examples/intermediate/i18n/main.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/middleware/i18n"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger()) // adapt a simple internal logger to print any errors
|
||||
app.Adapt(httprouter.New()) // adapt a router, you can use gorillamux too
|
||||
|
||||
app.Use(i18n.New(i18n.Config{
|
||||
Default: "en-US",
|
||||
URLParameter: "lang",
|
||||
Languages: map[string]string{
|
||||
"en-US": "./locales/locale_en-US.ini",
|
||||
"el-GR": "./locales/locale_el-GR.ini",
|
||||
"zh-CN": "./locales/locale_zh-CN.ini"}}))
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
|
||||
// it tries to find the language by:
|
||||
// ctx.Get("language") , that should be setted on other middleware before the i18n middleware*
|
||||
// if that was empty then
|
||||
// it tries to find from the URLParameter setted on the configuration
|
||||
// if not found then
|
||||
// it tries to find the language by the "lang" cookie
|
||||
// if didn't found then it it set to the Default setted on the configuration
|
||||
|
||||
// hi is the key, 'kataras' is the %s on the .ini file
|
||||
// the second parameter is optional
|
||||
|
||||
// hi := ctx.Translate("hi", "kataras")
|
||||
// or:
|
||||
hi := i18n.Translate(ctx, "hi", "kataras")
|
||||
|
||||
language := ctx.Get(iris.TranslateLanguageContextKey) // language is the language key, example 'en-US'
|
||||
|
||||
// The first succeed language found saved at the cookie with name ("language"),
|
||||
// you can change that by changing the value of the: iris.TranslateLanguageContextKey
|
||||
ctx.Writef("From the language %s translated output: %s", language, hi)
|
||||
})
|
||||
|
||||
// go to http://localhost:8080/?lang=el-GR
|
||||
// or http://localhost:8080
|
||||
// or http://localhost:8080/?lang=zh-CN
|
||||
app.Listen(":8080")
|
||||
|
||||
}
|
||||
28
_examples/examples/intermediate/password-hashing/main.go
Normal file
28
_examples/examples/intermediate/password-hashing/main.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func HashPassword(password string) (string, error) {
|
||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
func CheckPasswordHash(password, hash string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
password := "secret"
|
||||
hash, _ := HashPassword(password) // ignore error for the sake of simplicity
|
||||
|
||||
fmt.Println("Password:", password)
|
||||
fmt.Println("Hash: ", hash)
|
||||
|
||||
match := CheckPasswordHash(password, hash)
|
||||
fmt.Println("Match: ", match)
|
||||
}
|
||||
24
_examples/examples/intermediate/pprof/main.go
Normal file
24
_examples/examples/intermediate/pprof/main.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/middleware/pprof"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger())
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
ctx.HTML(iris.StatusOK, "<h1> Please click <a href='/debug/pprof'>here</a>")
|
||||
})
|
||||
|
||||
app.Get("/debug/pprof/*action", pprof.New())
|
||||
// ___________
|
||||
// Note:
|
||||
// if you prefer gorillamux adaptor, then
|
||||
// the wildcard for gorilla mux (as you already know) is '{action:.*}' instead of '*action'.
|
||||
app.Listen(":8080")
|
||||
}
|
||||
34
_examples/examples/intermediate/recover/main.go
Normal file
34
_examples/examples/intermediate/recover/main.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/middleware/recover"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
// fast way to enable non-fatal messages to be printed to the user
|
||||
// (yes in iris even recover's errors are not fatal because it's restarting,
|
||||
// ProdMode messages are only for things that Iris cannot continue at all,
|
||||
// these are logged by-default but you can change that behavior too by passing a different LoggerPolicy to the .Adapt)
|
||||
app.Adapt(iris.DevLogger())
|
||||
// adapt a router, you can use gorillamux too
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
// use this recover(y) middleware
|
||||
app.Use(recover.New())
|
||||
|
||||
i := 0
|
||||
// let's simmilate a panic every next request
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
i++
|
||||
if i%2 == 0 {
|
||||
panic("a panic here")
|
||||
}
|
||||
ctx.Writef("Hello, refresh one time more to get panic!")
|
||||
})
|
||||
|
||||
// http://localhost:8080
|
||||
app.Listen(":8080")
|
||||
}
|
||||
53
_examples/examples/intermediate/request-logger/main.go
Normal file
53
_examples/examples/intermediate/request-logger/main.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/middleware/logger"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
app.Adapt(iris.DevLogger()) // it just enables the print of the iris.DevMode logs. Enable it to view the middleware's messages.
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
customLogger := logger.New(logger.Config{
|
||||
// Status displays status code
|
||||
Status: true,
|
||||
// IP displays request's remote address
|
||||
IP: true,
|
||||
// Method displays the http method
|
||||
Method: true,
|
||||
// Path displays the request path
|
||||
Path: true,
|
||||
})
|
||||
|
||||
app.Use(customLogger)
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
ctx.Writef("hello")
|
||||
})
|
||||
|
||||
app.Get("/1", func(ctx *iris.Context) {
|
||||
ctx.Writef("hello")
|
||||
})
|
||||
|
||||
app.Get("/2", func(ctx *iris.Context) {
|
||||
ctx.Writef("hello")
|
||||
})
|
||||
|
||||
// log http errors
|
||||
errorLogger := logger.New()
|
||||
|
||||
app.OnError(iris.StatusNotFound, func(ctx *iris.Context) {
|
||||
errorLogger.Serve(ctx)
|
||||
ctx.Writef("My Custom 404 error page ")
|
||||
})
|
||||
|
||||
// http://localhost:8080
|
||||
// http://localhost:8080/1
|
||||
// http://localhost:8080/2
|
||||
app.Listen(":8080")
|
||||
|
||||
}
|
||||
73
_examples/examples/intermediate/sessions/database/main.go
Normal file
73
_examples/examples/intermediate/sessions/database/main.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/sessions"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/sessions/sessiondb/redis"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/sessions/sessiondb/redis/service"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// replace with your running redis' server settings:
|
||||
db := redis.New(service.Config{Network: service.DefaultRedisNetwork,
|
||||
Addr: service.DefaultRedisAddr,
|
||||
Password: "",
|
||||
Database: "",
|
||||
MaxIdle: 0,
|
||||
MaxActive: 0,
|
||||
IdleTimeout: service.DefaultRedisIdleTimeout,
|
||||
Prefix: "",
|
||||
MaxAgeSeconds: service.DefaultRedisMaxAgeSeconds}) // optionally configure the bridge between your redis server
|
||||
|
||||
mySessions := sessions.New(sessions.Config{Cookie: "mysessionid"})
|
||||
|
||||
//
|
||||
// IMPORTANT:
|
||||
//
|
||||
mySessions.UseDatabase(db)
|
||||
|
||||
// the rest of the code stays the same.
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger()) // enable all (error) logs
|
||||
app.Adapt(httprouter.New()) // select the httprouter as the servemux
|
||||
|
||||
// Adapt the session manager we just created
|
||||
app.Adapt(mySessions)
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead")
|
||||
})
|
||||
app.Get("/set", func(ctx *iris.Context) {
|
||||
|
||||
//set session values
|
||||
ctx.Session().Set("name", "iris")
|
||||
|
||||
//test if setted here
|
||||
ctx.Writef("All ok session setted to: %s", ctx.Session().GetString("name"))
|
||||
})
|
||||
|
||||
app.Get("/get", func(ctx *iris.Context) {
|
||||
// get a specific key, as string, if no found returns just an empty string
|
||||
name := ctx.Session().GetString("name")
|
||||
|
||||
ctx.Writef("The name on the /set was: %s", name)
|
||||
})
|
||||
|
||||
app.Get("/delete", func(ctx *iris.Context) {
|
||||
// delete a specific key
|
||||
ctx.Session().Delete("name")
|
||||
})
|
||||
|
||||
app.Get("/clear", func(ctx *iris.Context) {
|
||||
// removes all entries
|
||||
ctx.Session().Clear()
|
||||
})
|
||||
|
||||
app.Get("/destroy", func(ctx *iris.Context) {
|
||||
//destroy, removes the entire session data and cookie
|
||||
ctx.SessionDestroy()
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
55
_examples/examples/intermediate/sessions/overview/main.go
Normal file
55
_examples/examples/intermediate/sessions/overview/main.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/sessions"
|
||||
)
|
||||
|
||||
var (
|
||||
key = "my_sessionid"
|
||||
)
|
||||
|
||||
func secret(ctx *iris.Context) {
|
||||
|
||||
// Check if user is authenticated
|
||||
if auth, _ := ctx.Session().GetBoolean("authenticated"); !auth {
|
||||
ctx.EmitError(iris.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
// Print secret message
|
||||
ctx.WriteString("The cake is a lie!")
|
||||
}
|
||||
|
||||
func login(ctx *iris.Context) {
|
||||
session := ctx.Session()
|
||||
|
||||
// Authentication goes here
|
||||
// ...
|
||||
|
||||
// Set user as authenticated
|
||||
session.Set("authenticated", true)
|
||||
}
|
||||
|
||||
func logout(ctx *iris.Context) {
|
||||
session := ctx.Session()
|
||||
|
||||
// Revoke users authentication
|
||||
session.Set("authenticated", false)
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(httprouter.New())
|
||||
// Look https://github.com/kataras/iris/tree/v6/adaptors/sessions/_examples for more features,
|
||||
// i.e encode/decode and lifetime.
|
||||
sess := sessions.New(sessions.Config{Cookie: key})
|
||||
app.Adapt(sess)
|
||||
|
||||
app.Get("/secret", secret)
|
||||
app.Get("/login", login)
|
||||
app.Get("/logout", logout)
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
// developers can use any library to add a custom cookie encoder/decoder.
|
||||
// At this example we use the gorilla's securecookie library:
|
||||
"github.com/gorilla/securecookie"
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/sessions"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger()) // enable all (error) logs
|
||||
app.Adapt(httprouter.New()) // select the httprouter as the servemux
|
||||
|
||||
cookieName := "mycustomsessionid"
|
||||
// AES only supports key sizes of 16, 24 or 32 bytes.
|
||||
// You either need to provide exactly that amount or you derive the key from what you type in.
|
||||
hashKey := []byte("the-big-and-secret-fash-key-here")
|
||||
blockKey := []byte("lot-secret-of-characters-big-too")
|
||||
secureCookie := securecookie.New(hashKey, blockKey)
|
||||
|
||||
mySessions := sessions.New(sessions.Config{
|
||||
Cookie: cookieName,
|
||||
Encode: secureCookie.Encode,
|
||||
Decode: secureCookie.Decode,
|
||||
})
|
||||
|
||||
app.Adapt(mySessions)
|
||||
|
||||
// OPTIONALLY:
|
||||
// import "gopkg.in/kataras/iris.v6/adaptors/sessions/sessiondb/redis"
|
||||
// or import "github.com/kataras/go-sessions/sessiondb/$any_available_community_database"
|
||||
// mySessions.UseDatabase(redis.New(...))
|
||||
|
||||
app.Adapt(mySessions) // Adapt the session manager we just created.
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead")
|
||||
})
|
||||
app.Get("/set", func(ctx *iris.Context) {
|
||||
|
||||
//set session values
|
||||
ctx.Session().Set("name", "iris")
|
||||
|
||||
//test if setted here
|
||||
ctx.Writef("All ok session setted to: %s", ctx.Session().GetString("name"))
|
||||
})
|
||||
|
||||
app.Get("/get", func(ctx *iris.Context) {
|
||||
// get a specific key, as string, if no found returns just an empty string
|
||||
name := ctx.Session().GetString("name")
|
||||
|
||||
ctx.Writef("The name on the /set was: %s", name)
|
||||
})
|
||||
|
||||
app.Get("/delete", func(ctx *iris.Context) {
|
||||
// delete a specific key
|
||||
ctx.Session().Delete("name")
|
||||
})
|
||||
|
||||
app.Get("/clear", func(ctx *iris.Context) {
|
||||
// removes all entries
|
||||
ctx.Session().Clear()
|
||||
})
|
||||
|
||||
app.Get("/destroy", func(ctx *iris.Context) {
|
||||
//destroy, removes the entire session data and cookie
|
||||
ctx.SessionDestroy()
|
||||
}) // Note about destroy:
|
||||
//
|
||||
// You can destroy a session outside of a handler too, using the:
|
||||
// mySessions.DestroyByID
|
||||
// mySessions.DestroyAll
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
82
_examples/examples/intermediate/sessions/standalone/main.go
Normal file
82
_examples/examples/intermediate/sessions/standalone/main.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/sessions"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger()) // enable all (error) logs
|
||||
app.Adapt(httprouter.New()) // select the httprouter as the servemux
|
||||
|
||||
mySessions := sessions.New(sessions.Config{
|
||||
// Cookie string, the session's client cookie name, for example: "mysessionid"
|
||||
//
|
||||
// Defaults to "irissessionid"
|
||||
Cookie: "mysessionid",
|
||||
// it's time.Duration, from the time cookie is created, how long it can be alive?
|
||||
// 0 means no expire.
|
||||
// -1 means expire when browser closes
|
||||
// or set a value, like 2 hours:
|
||||
Expires: time.Hour * 2,
|
||||
// the length of the sessionid's cookie's value
|
||||
CookieLength: 32,
|
||||
// if you want to invalid cookies on different subdomains
|
||||
// of the same host, then enable it
|
||||
DisableSubdomainPersistence: false,
|
||||
// want to be crazy safe? Take a look at the "securecookie" example folder.
|
||||
})
|
||||
|
||||
// OPTIONALLY:
|
||||
// import "gopkg.in/kataras/iris.v6/adaptors/sessions/sessiondb/redis"
|
||||
// or import "github.com/kataras/go-sessions/sessiondb/$any_available_community_database"
|
||||
// mySessions.UseDatabase(redis.New(...))
|
||||
|
||||
app.Adapt(mySessions) // Adapt the session manager we just created.
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead")
|
||||
})
|
||||
app.Get("/set", func(ctx *iris.Context) {
|
||||
|
||||
//set session values
|
||||
ctx.Session().Set("name", "iris")
|
||||
|
||||
//test if setted here
|
||||
ctx.Writef("All ok session setted to: %s", ctx.Session().GetString("name"))
|
||||
})
|
||||
|
||||
app.Get("/get", func(ctx *iris.Context) {
|
||||
// get a specific key, as string, if no found returns just an empty string
|
||||
name := ctx.Session().GetString("name")
|
||||
|
||||
ctx.Writef("The name on the /set was: %s", name)
|
||||
})
|
||||
|
||||
app.Get("/delete", func(ctx *iris.Context) {
|
||||
// delete a specific key
|
||||
ctx.Session().Delete("name")
|
||||
})
|
||||
|
||||
app.Get("/clear", func(ctx *iris.Context) {
|
||||
// removes all entries
|
||||
ctx.Session().Clear()
|
||||
})
|
||||
|
||||
app.Get("/destroy", func(ctx *iris.Context) {
|
||||
|
||||
//destroy, removes the entire session data and cookie
|
||||
ctx.SessionDestroy()
|
||||
})
|
||||
// Note about Destroy:
|
||||
//
|
||||
// You can destroy a session outside of a handler too, using the:
|
||||
// mySessions.DestroyByID
|
||||
// mySessions.DestroyAll
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
69
_examples/examples/intermediate/upload-files/main.go
Normal file
69
_examples/examples/intermediate/upload-files/main.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger())
|
||||
app.Adapt(httprouter.New())
|
||||
app.Adapt(view.HTML("./templates", ".html"))
|
||||
|
||||
// Serve the form.html to the user
|
||||
app.Get("/upload", func(ctx *iris.Context) {
|
||||
//create a token (optionally)
|
||||
|
||||
now := time.Now().Unix()
|
||||
h := md5.New()
|
||||
io.WriteString(h, strconv.FormatInt(now, 10))
|
||||
token := fmt.Sprintf("%x", h.Sum(nil))
|
||||
//render the form with the token for any use you like
|
||||
ctx.Render("upload_form.html", token)
|
||||
})
|
||||
|
||||
// Handle the post request from the upload_form.html to the server
|
||||
app.Post("/upload", iris.LimitRequestBodySize(10<<20),
|
||||
func(ctx *iris.Context) {
|
||||
// or use ctx.SetMaxRequestBodySize(10 << 20)
|
||||
//to limit the uploaded file(s) size.
|
||||
|
||||
// Get the file from the request
|
||||
file, info, err := ctx.FormFile("uploadfile")
|
||||
|
||||
if err != nil {
|
||||
ctx.HTML(iris.StatusInternalServerError,
|
||||
"Error while uploading: <b>"+err.Error()+"</b>")
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
fname := info.Filename
|
||||
|
||||
// Create a file with the same name
|
||||
// assuming that you have a folder named 'uploads'
|
||||
out, err := os.OpenFile("./uploads/"+fname,
|
||||
os.O_WRONLY|os.O_CREATE, 0666)
|
||||
|
||||
if err != nil {
|
||||
ctx.HTML(iris.StatusInternalServerError,
|
||||
"Error while uploading: <b>"+err.Error()+"</b>")
|
||||
return
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
io.Copy(out, file)
|
||||
})
|
||||
|
||||
// start the server at 127.0.0.1:8080
|
||||
app.Listen(":8080")
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Upload file</title>
|
||||
</head>
|
||||
<body>
|
||||
<form enctype="multipart/form-data"
|
||||
action="http://127.0.0.1:8080/upload" method="post">
|
||||
<input type="file" name="uploadfile" /> <input type="hidden"
|
||||
name="token" value="{{.}}" /> <input type="submit" value="upload" />
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
48
_examples/examples/intermediate/view/custom-renderer/main.go
Normal file
48
_examples/examples/intermediate/view/custom-renderer/main.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"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())
|
||||
|
||||
// Custom Render Policy to override or create new content-type render
|
||||
// i,e: "text/html" with a prefix,
|
||||
// we will just write to the writer and return false
|
||||
// to continue to the next contentType-matched renderer if any.
|
||||
app.Adapt(iris.RenderPolicy(func(out io.Writer, contentType string, binding interface{}, options ...map[string]interface{}) (bool, error) {
|
||||
|
||||
if contentType == "text/html" {
|
||||
if content, ok := binding.(string); ok {
|
||||
out.Write([]byte("<pre>My Custom prefix</pre><br/>" + content))
|
||||
}
|
||||
|
||||
}
|
||||
// continue to the next, no error
|
||||
// note: if we wanted to stop here we would return true instead of false.
|
||||
return false, nil
|
||||
}))
|
||||
|
||||
app.Get("", func(ctx *iris.Context) {
|
||||
|
||||
// These content-types are not managed by our RenderPolicy:
|
||||
// text, binary and html content-types are
|
||||
// not rendered via serializers, you have to
|
||||
// use the ctx.Render functions instead.
|
||||
// so something like this:
|
||||
// ctx.Text(iris.StatusOK, "my text content body here!")
|
||||
// will NOT work with out custom render policy.
|
||||
ctx.Render("text/html",
|
||||
"my text content body here!")
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
// Code generated by go-bindata.
|
||||
// sources:
|
||||
// templates/hi.html
|
||||
// DO NOT EDIT!
|
||||
|
||||
// NOTE: execute your own look main.go
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func bindataRead(data []byte, name string) ([]byte, error) {
|
||||
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
_, err = io.Copy(&buf, gz)
|
||||
clErr := gz.Close()
|
||||
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||
}
|
||||
if clErr != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
type asset struct {
|
||||
bytes []byte
|
||||
info os.FileInfo
|
||||
}
|
||||
|
||||
type bindataFileInfo struct {
|
||||
name string
|
||||
size int64
|
||||
mode os.FileMode
|
||||
modTime time.Time
|
||||
}
|
||||
|
||||
func (fi bindataFileInfo) Name() string {
|
||||
return fi.name
|
||||
}
|
||||
func (fi bindataFileInfo) Size() int64 {
|
||||
return fi.size
|
||||
}
|
||||
func (fi bindataFileInfo) Mode() os.FileMode {
|
||||
return fi.mode
|
||||
}
|
||||
func (fi bindataFileInfo) ModTime() time.Time {
|
||||
return fi.modTime
|
||||
}
|
||||
func (fi bindataFileInfo) IsDir() bool {
|
||||
return false
|
||||
}
|
||||
func (fi bindataFileInfo) Sys() interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
var _templatesHiHtml = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xb2\xc9\x28\xc9\xcd\xb1\xe3\xe5\xb2\xc9\x48\x4d\x4c\x01\xd1\x25\x99\x25\x39\xa9\x76\x1e\x99\x0a\x9e\x45\x99\xc5\x0a\xd1\x21\x1e\xae\x0a\x21\x9e\x21\x3e\xae\xb1\x36\xfa\x10\x29\xa0\x1a\x7d\x98\xe2\xa4\xfc\x94\x4a\x20\xcd\x69\x93\x61\x08\xd2\x52\x5d\xad\xe7\x97\x98\x9b\x5a\x5b\x0b\x52\x03\x95\x03\x2a\x86\xd8\x00\x08\x00\x00\xff\xff\xed\x0e\xad\x42\x6a\x00\x00\x00")
|
||||
|
||||
func templatesHiHtmlBytes() ([]byte, error) {
|
||||
return bindataRead(
|
||||
_templatesHiHtml,
|
||||
"templates/hi.html",
|
||||
)
|
||||
}
|
||||
|
||||
func templatesHiHtml() (*asset, error) {
|
||||
bytes, err := templatesHiHtmlBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "templates/hi.html", size: 106, mode: os.FileMode(438), modTime: time.Unix(1487682349, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// Asset loads and returns the asset for the given name.
|
||||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func Asset(name string) ([]byte, error) {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[cannonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
|
||||
}
|
||||
return a.bytes, nil
|
||||
}
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
|
||||
// MustAsset is like Asset but panics when Asset would return an error.
|
||||
// It simplifies safe initialization of global variables.
|
||||
func MustAsset(name string) []byte {
|
||||
a, err := Asset(name)
|
||||
if err != nil {
|
||||
panic("asset: Asset(" + name + "): " + err.Error())
|
||||
}
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
// AssetInfo loads and returns the asset info for the given name.
|
||||
// It returns an error if the asset could not be found or
|
||||
// could not be loaded.
|
||||
func AssetInfo(name string) (os.FileInfo, error) {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
if f, ok := _bindata[cannonicalName]; ok {
|
||||
a, err := f()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
|
||||
}
|
||||
return a.info, nil
|
||||
}
|
||||
return nil, fmt.Errorf("AssetInfo %s not found", name)
|
||||
}
|
||||
|
||||
// AssetNames returns the names of the assets.
|
||||
func AssetNames() []string {
|
||||
names := make([]string, 0, len(_bindata))
|
||||
for name := range _bindata {
|
||||
names = append(names, name)
|
||||
}
|
||||
return names
|
||||
}
|
||||
|
||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||
var _bindata = map[string]func() (*asset, error){
|
||||
"templates/hi.html": templatesHiHtml,
|
||||
}
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
// directory embedded in the file by go-bindata.
|
||||
// For example if you run go-bindata on data/... and data contains the
|
||||
// following hierarchy:
|
||||
// data/
|
||||
// foo.txt
|
||||
// img/
|
||||
// a.png
|
||||
// b.png
|
||||
// then AssetDir("data") would return []string{"foo.txt", "img"}
|
||||
// AssetDir("data/img") would return []string{"a.png", "b.png"}
|
||||
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
|
||||
// AssetDir("") will return []string{"data"}.
|
||||
func AssetDir(name string) ([]string, error) {
|
||||
node := _bintree
|
||||
if len(name) != 0 {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
pathList := strings.Split(cannonicalName, "/")
|
||||
for _, p := range pathList {
|
||||
node = node.Children[p]
|
||||
if node == nil {
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
if node.Func != nil {
|
||||
return nil, fmt.Errorf("Asset %s not found", name)
|
||||
}
|
||||
rv := make([]string, 0, len(node.Children))
|
||||
for childName := range node.Children {
|
||||
rv = append(rv, childName)
|
||||
}
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
type bintree struct {
|
||||
Func func() (*asset, error)
|
||||
Children map[string]*bintree
|
||||
}
|
||||
|
||||
var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"templates": &bintree{nil, map[string]*bintree{
|
||||
"hi.html": &bintree{templatesHiHtml, map[string]*bintree{}},
|
||||
}},
|
||||
}}
|
||||
|
||||
// RestoreAsset restores an asset under the given directory
|
||||
func RestoreAsset(dir, name string) error {
|
||||
data, err := Asset(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
info, err := AssetInfo(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RestoreAssets restores an asset under the given directory recursively
|
||||
func RestoreAssets(dir, name string) error {
|
||||
children, err := AssetDir(name)
|
||||
// File
|
||||
if err != nil {
|
||||
return RestoreAsset(dir, name)
|
||||
}
|
||||
// Dir
|
||||
for _, child := range children {
|
||||
err = RestoreAssets(dir, filepath.Join(name, child))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func _filePath(dir, name string) string {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger())
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
// $ go-bindata ./templates/...
|
||||
// $ go build
|
||||
// $ ./template_binary
|
||||
// templates are not used, you can delete the folder and run the example
|
||||
app.Adapt(view.HTML("./templates", ".html").Binary(Asset, AssetNames))
|
||||
app.Get("/hi", hi)
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
func hi(ctx *iris.Context) {
|
||||
ctx.MustRender("hi.html", struct{ Name string }{Name: "iris"})
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Hi Iris [THE TITLE]</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hi {{.Name}}
|
||||
</body>
|
||||
</html>
|
||||
59
_examples/examples/intermediate/view/overview/main.go
Normal file
59
_examples/examples/intermediate/view/overview/main.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/gorillamux"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
)
|
||||
|
||||
// ExampleXML just a test struct to view represents xml content-type
|
||||
type ExampleXML struct {
|
||||
XMLName xml.Name `xml:"example"`
|
||||
One string `xml:"one,attr"`
|
||||
Two string `xml:"two,attr"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger())
|
||||
app.Adapt(gorillamux.New())
|
||||
|
||||
app.Get("/data", func(ctx *iris.Context) {
|
||||
ctx.Data(iris.StatusOK, []byte("Some binary data here."))
|
||||
})
|
||||
|
||||
app.Get("/text", func(ctx *iris.Context) {
|
||||
ctx.Text(iris.StatusOK, "Plain text here")
|
||||
})
|
||||
|
||||
app.Get("/json", func(ctx *iris.Context) {
|
||||
ctx.JSON(iris.StatusOK, map[string]string{"hello": "json"}) // or myjsonStruct{hello:"json}
|
||||
})
|
||||
|
||||
app.Get("/jsonp", func(ctx *iris.Context) {
|
||||
ctx.JSONP(iris.StatusOK, "callbackName", map[string]string{"hello": "jsonp"})
|
||||
})
|
||||
|
||||
app.Get("/xml", func(ctx *iris.Context) {
|
||||
ctx.XML(iris.StatusOK, ExampleXML{One: "hello", Two: "xml"}) // or iris.Map{"One":"hello"...}
|
||||
})
|
||||
|
||||
app.Get("/markdown", func(ctx *iris.Context) {
|
||||
ctx.Markdown(iris.StatusOK, "# Hello Dynamic Markdown Iris")
|
||||
})
|
||||
|
||||
app.Adapt(view.HTML("./templates", ".html"))
|
||||
app.Get("/template", func(ctx *iris.Context) {
|
||||
|
||||
ctx.MustRender(
|
||||
"hi.html", // the file name of the template relative to the './templates'
|
||||
iris.Map{"Name": "Iris"}, // the .Name inside the ./templates/hi.html
|
||||
iris.Map{"gzip": false}, // enable gzip for big files
|
||||
)
|
||||
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Hi Iris</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hi {{.Name}} </h1>
|
||||
</body>
|
||||
</html>
|
||||
23
_examples/examples/intermediate/view/template_html_0/main.go
Normal file
23
_examples/examples/intermediate/view/template_html_0/main.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New(iris.Configuration{Gzip: false, Charset: "UTF-8"}) // defaults to these
|
||||
|
||||
app.Adapt(iris.DevLogger())
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
app.Adapt(view.HTML("./templates", ".html"))
|
||||
|
||||
app.Get("/hi", hi)
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
func hi(ctx *iris.Context) {
|
||||
ctx.MustRender("hi.html", struct{ Name string }{Name: "iris"})
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Hi Iris</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hi {{.Name}} </h1>
|
||||
</body>
|
||||
</html>
|
||||
32
_examples/examples/intermediate/view/template_html_1/main.go
Normal file
32
_examples/examples/intermediate/view/template_html_1/main.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
)
|
||||
|
||||
type mypage struct {
|
||||
Title string
|
||||
Message string
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger())
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
tmpl := view.HTML("./templates", ".html")
|
||||
tmpl.Layout("layout.html")
|
||||
|
||||
app.Adapt(tmpl)
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
ctx.Render("mypage.html", mypage{"My Page title", "Hello world!"}, iris.Map{"gzip": true})
|
||||
// Note that: you can pass "layout" : "otherLayout.html" to bypass the config's Layout property
|
||||
// or iris.NoLayout to disable layout on this render action.
|
||||
// third is an optional parameter
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>My Layout</title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<h1>Body is:</h1>
|
||||
<!-- Render the current template here -->
|
||||
{{ yield }}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,4 @@
|
||||
<h1>
|
||||
Title: {{.Title}}
|
||||
</h1>
|
||||
<h3>Message: {{.Message}} </h3>
|
||||
@@ -0,0 +1,3 @@
|
||||
## Info
|
||||
|
||||
This folder examines the {{render "dir/templatefilename"}} functionality to manually render any template inside any template
|
||||
49
_examples/examples/intermediate/view/template_html_2/main.go
Normal file
49
_examples/examples/intermediate/view/template_html_2/main.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger())
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
tmpl := view.HTML("./templates", ".html")
|
||||
tmpl.Layout("layouts/layout.html")
|
||||
tmpl.Funcs(map[string]interface{}{
|
||||
"greet": func(s string) string {
|
||||
return "Greetings " + s + "!"
|
||||
},
|
||||
})
|
||||
|
||||
app.Adapt(tmpl)
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
if err := ctx.Render("page1.html", nil); err != nil {
|
||||
println(err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
// remove the layout for a specific route
|
||||
app.Get("/nolayout", func(ctx *iris.Context) {
|
||||
if err := ctx.Render("page1.html", nil, iris.RenderOptions{"layout": iris.NoLayout}); err != nil {
|
||||
println(err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
// set a layout for a party, .Layout should be BEFORE any Get or other Handle party's method
|
||||
my := app.Party("/my").Layout("layouts/mylayout.html")
|
||||
{
|
||||
my.Get("/", func(ctx *iris.Context) {
|
||||
ctx.MustRender("page1.html", nil)
|
||||
})
|
||||
my.Get("/other", func(ctx *iris.Context) {
|
||||
ctx.MustRender("page1.html", nil)
|
||||
})
|
||||
}
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Layout</title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<h1>This is the global layout</h1>
|
||||
<br />
|
||||
<!-- Render the current template here -->
|
||||
{{ yield }}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>my Layout</title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<h1>This is the layout for the /my/ and /my/other routes only</h1>
|
||||
<br />
|
||||
<!-- Render the current template here -->
|
||||
{{ yield }}
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,7 @@
|
||||
<div style="background-color: black; color: blue">
|
||||
|
||||
<h1>Page 1 {{ greet "iris developer"}}</h1>
|
||||
|
||||
{{ render "partials/page1_partial1.html"}}
|
||||
|
||||
</div>
|
||||
@@ -0,0 +1,3 @@
|
||||
<div style="background-color: white; color: red">
|
||||
<h1>Page 1's Partial 1</h1>
|
||||
</div>
|
||||
103
_examples/examples/intermediate/view/template_html_3/main.go
Normal file
103
_examples/examples/intermediate/view/template_html_3/main.go
Normal file
@@ -0,0 +1,103 @@
|
||||
// Package main an example on how to naming your routes & use the custom 'url' HTML Template Engine, same for other template engines.
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/gorillamux"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger())
|
||||
app.Adapt(view.HTML("./templates", ".html").Reload(true))
|
||||
|
||||
startWithHTTPRouter(app)
|
||||
// or uncomment
|
||||
// startWithGorillamux()
|
||||
|
||||
app.Listen("localhost:8080")
|
||||
|
||||
}
|
||||
|
||||
func writePathHandler(ctx *iris.Context) {
|
||||
ctx.Writef("Hello from %s.", ctx.Path())
|
||||
}
|
||||
|
||||
func startWithHTTPRouter(app *iris.Framework) {
|
||||
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
app.Get("/mypath", writePathHandler).ChangeName("my-page1")
|
||||
app.Get("/mypath2/:param1/:param2", writePathHandler).ChangeName("my-page2")
|
||||
app.Get("/mypath3/:param1/statichere/:param2", writePathHandler).ChangeName("my-page3")
|
||||
app.Get("/mypath4/:param1/statichere/:param2/:otherparam/*something", writePathHandler).ChangeName("my-page4")
|
||||
|
||||
// same with Handle/Func
|
||||
app.HandleFunc("GET", "/mypath5/:param1/statichere/:param2/:otherparam/anything/*something", writePathHandler).ChangeName("my-page5")
|
||||
|
||||
app.Get("/mypath6/:param1/:param2/staticParam/:param3AfterStatic", writePathHandler).ChangeName("my-page6")
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
// for /mypath6...
|
||||
paramsAsArray := []string{"param1", "theParam1",
|
||||
"param2", "theParam2",
|
||||
"param3AfterStatic", "theParam3"}
|
||||
|
||||
if err := ctx.Render("page.html", iris.Map{"ParamsAsArray": paramsAsArray}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
})
|
||||
|
||||
app.Get("/redirect/:namedRoute", func(ctx *iris.Context) {
|
||||
routeName := ctx.Param("namedRoute")
|
||||
|
||||
println("The full uri of " + routeName + "is: " + app.URL(routeName))
|
||||
// if routeName == "my-page1"
|
||||
// prints: The full uri of my-page1 is: http://127.0.0.1:8080/mypath
|
||||
ctx.RedirectTo(routeName)
|
||||
// http://127.0.0.1:8080/redirect/my-page1 will redirect to -> http://127.0.0.1:8080/mypath
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
// for gorillamux adaptor is the same thing, the path syntax is the only thing changed ofc.
|
||||
// Note: Here, we could use app.RouteParam("param1") without even care what router is being used,
|
||||
// but I have two examples of the same thing in order to be more understable for you.
|
||||
func startWithGorillamux(app *iris.Framework) {
|
||||
app.Adapt(gorillamux.New())
|
||||
|
||||
app.Get("/mypath", writePathHandler).ChangeName("my-page1")
|
||||
app.Get("/mypath2/{param1}/{param2}", writePathHandler).ChangeName("my-page2")
|
||||
app.Get("/mypath3/{param1}/statichere/{param2}", writePathHandler).ChangeName("my-page3")
|
||||
app.Get("/mypath4/{param1}/statichere/{param2}/{otherparam}/{something:.*}", writePathHandler).ChangeName("my-page4")
|
||||
|
||||
// same with Handle/Func
|
||||
app.HandleFunc("GET", "/mypath5/{param1}/statichere/{param2}/{otherparam}/anything/{something:.*}", writePathHandler).ChangeName("my-page5")
|
||||
|
||||
app.Get("/mypath6/{param1}/{param2}/staticParam/{param3AfterStatic}", writePathHandler).ChangeName("my-page6")
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
// for /mypath6...
|
||||
paramsAsArray := []string{"param1", "theParam1",
|
||||
"param2", "theParam2",
|
||||
"param3AfterStatic", "theParam3"}
|
||||
|
||||
if err := ctx.Render("page.html", iris.Map{"ParamsAsArray": paramsAsArray}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
})
|
||||
|
||||
app.Get("/redirect/{namedRoute}", func(ctx *iris.Context) {
|
||||
routeName := ctx.Param("namedRoute")
|
||||
|
||||
println("The full uri of " + routeName + "is: " + app.URL(routeName))
|
||||
// if routeName == "my-page1"
|
||||
// prints: The full uri of my-page1 is: http://127.0.0.1:8080/mypath
|
||||
ctx.RedirectTo(routeName)
|
||||
// http://127.0.0.1:8080/redirect/my-page1 will redirect to -> http://127.0.0.1:8080/mypath
|
||||
})
|
||||
|
||||
app.Listen("localhost:8080")
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<a href="{{url "my-page1"}}">http://127.0.0.1:8080/mypath</a>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<a href="{{url "my-page2" "param1" "theParam1" "param2" "theParam2"}}">http://localhost:8080/mypath2/:param1/:param2</a>
|
||||
or path only:
|
||||
<a href="{{urlpath "my-page2" "param1" "theParam1" "param2" "theParam2"}}">/mypath2/:param1/:param2</a>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<a href="{{url "my-page3" "param1" "theParam1" "param2" "theParam2AfterStatic"}}">
|
||||
http://localhost:8080/mypath3/:param1/statichere/:param2</a>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<a href="{{url "my-page4" "param1" "theParam1" "param2" "theparam2AfterStatic" "otherparam" "otherParam" "something" "matchAnything"}}">http://localhost/mypath4/:param1/statichere/:param2/:otherparam/*something</a>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<a href="{{url "my-page5" "param1" "theParam1" "param2" "theParam2AfterStatic" "otherparam" "otherParam" "something" "matchAnythingAfterStatic"}}">
|
||||
http://localhost:8080/mypath5/:param1/statichere/:param2/:otherparam/anything/*anything</a>
|
||||
|
||||
<br />
|
||||
<br />
|
||||
|
||||
<a href={{url "my-page6" .ParamsAsArray }}>http://localhost:8080/mypath6/{param1}/{param2}/staticParam/{param3AfterStatic}</a>
|
||||
32
_examples/examples/intermediate/view/template_html_4/hosts
Normal file
32
_examples/examples/intermediate/view/template_html_4/hosts
Normal file
@@ -0,0 +1,32 @@
|
||||
# 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 username1.127.0.0.1
|
||||
127.0.0.1 username2.127.0.0.1
|
||||
127.0.0.1 username3.127.0.0.1
|
||||
127.0.0.1 username4.127.0.0.1
|
||||
127.0.0.1 username5.127.0.0.1
|
||||
# note that you can always use custom subdomains
|
||||
#-END IRIS-
|
||||
|
||||
# Windows: Drive:/Windows/system32/drivers/etc/hosts, on Linux: /etc/hosts
|
||||
53
_examples/examples/intermediate/view/template_html_4/main.go
Normal file
53
_examples/examples/intermediate/view/template_html_4/main.go
Normal file
@@ -0,0 +1,53 @@
|
||||
// Package main an example on how to naming your routes & use the custom 'url' HTML Template Engine, same for other template engines.
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/gorillamux"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger())
|
||||
app.Adapt(gorillamux.New())
|
||||
|
||||
app.Adapt(view.HTML("./templates", ".html"))
|
||||
|
||||
app.Get("/mypath", emptyHandler).ChangeName("my-page1")
|
||||
app.Get("/mypath2/{param1}/{param2}", emptyHandler).ChangeName("my-page2")
|
||||
app.Get("/mypath3/{param1}/statichere/{param2}", emptyHandler).ChangeName("my-page3")
|
||||
app.Get("/mypath4/{param1}/statichere/{param2}/{otherparam}/{something:.*}", emptyHandler).ChangeName("my-page4")
|
||||
|
||||
// same with Handle/Func
|
||||
app.HandleFunc("GET", "/mypath5/{param1}/statichere/{param2}/{otherparam}/anything/{something:.*}", emptyHandler).ChangeName("my-page5")
|
||||
|
||||
app.Get("/mypath6/{param1}/{param2}/staticParam/{param3AfterStatic}", emptyHandler).ChangeName("my-page6")
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
// for /mypath6...
|
||||
paramsAsArray := []string{"param1", "theParam1",
|
||||
"param2", "theParam2",
|
||||
"param3AfterStatic", "theParam3"}
|
||||
|
||||
if err := ctx.Render("page.html", iris.Map{"ParamsAsArray": paramsAsArray}); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
})
|
||||
|
||||
app.Get("/redirect/{namedRoute}", func(ctx *iris.Context) {
|
||||
routeName := ctx.Param("namedRoute")
|
||||
|
||||
println("The full uri of " + routeName + "is: " + app.URL(routeName))
|
||||
// if routeName == "my-page1"
|
||||
// prints: The full uri of my-page1 is: http://127.0.0.1:8080/mypath
|
||||
ctx.RedirectTo(routeName)
|
||||
// http://127.0.0.1:8080/redirect/my-page1 will redirect to -> http://127.0.0.1:8080/mypath
|
||||
})
|
||||
|
||||
app.Listen("localhost:8080")
|
||||
}
|
||||
|
||||
func emptyHandler(ctx *iris.Context) {
|
||||
ctx.Writef("Hello from %s.", ctx.Path())
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
<!-- the only difference between normal named routes and dynamic subdomains named routes is that the first argument of url
|
||||
is the subdomain part instead of named parameter-->
|
||||
|
||||
<a href="{{url "dynamic-subdomain1" "username1"}}">username1.127.0.0.1:8080/mypath</a>
|
||||
<br />
|
||||
<br />
|
||||
<a href="{{url "dynamic-subdomain2" "username2" "theParam1" "theParam2"}}">username2.127.0.0.1:8080/mypath2/{param1}/{param2}</a>
|
||||
<br />
|
||||
<br />
|
||||
<a href="{{url "dynamic-subdomain3" "username3" "theParam1" "theParam2AfterStatic"}}">username3.127.0.0.1:8080/mypath3/{param1}/statichere/{param2}</a>
|
||||
<br />
|
||||
<br />
|
||||
<a href="{{url "dynamic-subdomain4" "username4" "theParam1" "theparam2AfterStatic" "otherParam" "matchAnything"}}">username4.127.0.0.1:8080/mypath4/{param1}/statichere/{param2}/{otherParam}/{something:.*}</a>
|
||||
<br />
|
||||
<br />
|
||||
<a href="{{url "dynamic-subdomain5" .ParamsAsArray }}" >username5.127.0.0.1:8080/mypath6/{param1}/{param2}/staticParam/{param3}AfterStatic</a>
|
||||
@@ -0,0 +1,113 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/websocket"
|
||||
)
|
||||
|
||||
type clientPage struct {
|
||||
Title string
|
||||
Host string
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger()) // enable all (error) logs
|
||||
app.Adapt(httprouter.New()) // select the httprouter as the servemux
|
||||
app.Adapt(view.HTML("./templates", ".html")) // select the html engine to serve templates
|
||||
|
||||
ws := websocket.New(websocket.Config{
|
||||
// the path which the websocket client should listen/registered to,
|
||||
Endpoint: "/my_endpoint",
|
||||
// the client-side javascript static file path
|
||||
// which will be served by Iris.
|
||||
// default is /iris-ws.js
|
||||
// if you change that you have to change the bottom of templates/client.html
|
||||
// script tag:
|
||||
ClientSourcePath: "/iris-ws.js",
|
||||
//
|
||||
// Set the timeouts, 0 means no timeout
|
||||
// websocket has more configuration, go to ../../config.go for more:
|
||||
// WriteTimeout: 0,
|
||||
// ReadTimeout: 0,
|
||||
// by-default all origins are accepted, you can change this behavior by setting:
|
||||
// CheckOrigin: (r *http.Request ) bool {},
|
||||
//
|
||||
//
|
||||
// IDGenerator used to create (and later on, set)
|
||||
// an ID for each incoming websocket connections (clients).
|
||||
// The request is an argument which you can use to generate the ID (from headers for example).
|
||||
// If empty then the ID is generated by DefaultIDGenerator: randomString(64):
|
||||
// IDGenerator func(ctx *iris.Context) string {},
|
||||
})
|
||||
|
||||
app.Adapt(ws) // adapt the websocket server, you can adapt more than one with different Endpoint
|
||||
|
||||
app.StaticWeb("/js", "./static/js") // serve our custom javascript code
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
ctx.Render("client.html", clientPage{"Client Page", ctx.ServerHost()})
|
||||
})
|
||||
|
||||
Conn := make(map[websocket.Connection]bool)
|
||||
var myChatRoom = "room1"
|
||||
var mutex = new(sync.Mutex)
|
||||
|
||||
ws.OnConnection(func(c websocket.Connection) {
|
||||
c.Join(myChatRoom)
|
||||
mutex.Lock()
|
||||
Conn[c] = true
|
||||
mutex.Unlock()
|
||||
c.On("chat", func(message string) {
|
||||
if message == "leave" {
|
||||
c.Leave(myChatRoom)
|
||||
c.To(myChatRoom).Emit("chat", "Client with ID: "+c.ID()+" left from the room and cannot send or receive message to/from this room.")
|
||||
c.Emit("chat", "You have left from the room: "+myChatRoom+" you cannot send or receive any messages from others inside that room.")
|
||||
return
|
||||
}
|
||||
})
|
||||
c.OnDisconnect(func() {
|
||||
mutex.Lock()
|
||||
delete(Conn, c)
|
||||
mutex.Unlock()
|
||||
fmt.Printf("\nConnection with ID: %s has been disconnected!\n", c.ID())
|
||||
})
|
||||
})
|
||||
|
||||
var delay = 1 * time.Second
|
||||
go func() {
|
||||
i := 0
|
||||
for {
|
||||
mutex.Lock()
|
||||
broadcast(Conn, fmt.Sprintf("aaaa %d\n", i))
|
||||
mutex.Unlock()
|
||||
time.Sleep(delay)
|
||||
i++
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
i := 0
|
||||
for {
|
||||
mutex.Lock()
|
||||
broadcast(Conn, fmt.Sprintf("aaaa2 %d\n", i))
|
||||
mutex.Unlock()
|
||||
time.Sleep(delay)
|
||||
i++
|
||||
}
|
||||
}()
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
func broadcast(Conn map[websocket.Connection]bool, message string) {
|
||||
for k := range Conn {
|
||||
k.To("room1").Emit("chat", message)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
var messageTxt;
|
||||
var messages;
|
||||
|
||||
$(function () {
|
||||
|
||||
messageTxt = $("#messageTxt");
|
||||
messages = $("#messages");
|
||||
|
||||
|
||||
w = new Ws("ws://" + HOST + "/my_endpoint");
|
||||
w.OnConnect(function () {
|
||||
console.log("Websocket connection established");
|
||||
});
|
||||
|
||||
w.OnDisconnect(function () {
|
||||
appendMessage($("<div><center><h3>Disconnected</h3></center></div>"));
|
||||
});
|
||||
|
||||
w.On("chat", function (message) {
|
||||
appendMessage($("<div>" + message + "</div>"));
|
||||
});
|
||||
|
||||
$("#sendBtn").click(function () {
|
||||
w.Emit("chat", messageTxt.val().toString());
|
||||
messageTxt.val("");
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
|
||||
function appendMessage(messageDiv) {
|
||||
var theDiv = messages[0];
|
||||
var doScroll = theDiv.scrollTop == theDiv.scrollHeight - theDiv.clientHeight;
|
||||
messageDiv.appendTo(messages);
|
||||
if (doScroll) {
|
||||
theDiv.scrollTop = theDiv.scrollHeight - theDiv.clientHeight;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{{ .Title}}</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="messages"
|
||||
style="border-width: 1px; border-style: solid; height: 400px; width: 375px;">
|
||||
|
||||
</div>
|
||||
<input type="text" id="messageTxt" />
|
||||
<button type="button" id="sendBtn">Send</button>
|
||||
<script type="text/javascript">
|
||||
var HOST = {{.Host}}
|
||||
</script>
|
||||
<script src="js/vendor/jquery-2.2.3.min.js" type="text/javascript"></script>
|
||||
<!-- This is auto-serving by the Iris, you don't need to have this file in your disk-->
|
||||
<script src="/iris-ws.js" type="text/javascript"></script>
|
||||
<!-- -->
|
||||
<script src="js/chat.js" type="text/javascript"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,179 @@
|
||||
package main
|
||||
|
||||
// Run first `go run main.go server`
|
||||
// and `go run main.go client` as many times as you want.
|
||||
// Originally written by: github.com/antlaw to describe an old kataras/go-websocket's issue
|
||||
// which you can find here: https://github.com/kataras/go-websocket/issues/24
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/websocket"
|
||||
|
||||
xwebsocket "golang.org/x/net/websocket"
|
||||
)
|
||||
|
||||
// WS is the current websocket connection
|
||||
var WS *xwebsocket.Conn
|
||||
|
||||
func main() {
|
||||
if len(os.Args) == 2 && strings.ToLower(os.Args[1]) == "server" {
|
||||
ServerLoop()
|
||||
} else if len(os.Args) == 2 && strings.ToLower(os.Args[1]) == "client" {
|
||||
ClientLoop()
|
||||
} else {
|
||||
fmt.Println("wsserver [server|client]")
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// client side
|
||||
func sendUntilErr(sendInterval int) {
|
||||
i := 1
|
||||
for {
|
||||
time.Sleep(time.Duration(sendInterval) * time.Second)
|
||||
err := SendMessage("2", "all", "objectupdate", "2.UsrSchedule_v1_1")
|
||||
if err != nil {
|
||||
fmt.Println("failed to send join message", err.Error())
|
||||
return
|
||||
}
|
||||
fmt.Println("objectupdate", i)
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
func recvUntilErr() {
|
||||
var msg = make([]byte, 2048)
|
||||
var n int
|
||||
var err error
|
||||
i := 1
|
||||
for {
|
||||
if n, err = WS.Read(msg); err != nil {
|
||||
fmt.Println(err.Error())
|
||||
return
|
||||
}
|
||||
fmt.Printf("%v Received: %s.%v\n", time.Now(), string(msg[:n]), i)
|
||||
i++
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//ConnectWebSocket connect a websocket to host
|
||||
func ConnectWebSocket() error {
|
||||
var origin = "http://localhost/"
|
||||
var url = "ws://localhost:9090/socket"
|
||||
var err error
|
||||
WS, err = xwebsocket.Dial(url, "", origin)
|
||||
return err
|
||||
}
|
||||
|
||||
// CloseWebSocket closes the current websocket connection
|
||||
func CloseWebSocket() error {
|
||||
if WS != nil {
|
||||
return WS.Close()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SendMessage broadcast a message to server
|
||||
func SendMessage(serverID, to, method, message string) error {
|
||||
buffer := []byte(message)
|
||||
return SendtBytes(serverID, to, method, buffer)
|
||||
}
|
||||
|
||||
// SendtBytes broadcast a message to server
|
||||
func SendtBytes(serverID, to, method string, message []byte) error {
|
||||
// look https://github.com/kataras/iris/tree/master/adaptors/websocket/message.go , client.go and client.js
|
||||
// to understand the buffer line:
|
||||
buffer := []byte(fmt.Sprintf("iris-websocket-message:%v;0;%v;%v;", method, serverID, to))
|
||||
buffer = append(buffer, message...)
|
||||
_, err := WS.Write(buffer)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ClientLoop connects to websocket server, the keep send and recv dataS
|
||||
func ClientLoop() {
|
||||
for {
|
||||
time.Sleep(time.Second)
|
||||
err := ConnectWebSocket()
|
||||
if err != nil {
|
||||
fmt.Println("failed to connect websocket", err.Error())
|
||||
continue
|
||||
}
|
||||
// time.Sleep(time.Second)
|
||||
err = SendMessage("2", "all", "join", "dummy2")
|
||||
go sendUntilErr(1)
|
||||
recvUntilErr()
|
||||
err = CloseWebSocket()
|
||||
if err != nil {
|
||||
fmt.Println("failed to close websocket", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// server side
|
||||
|
||||
// OnConnect handles incoming websocket connection
|
||||
func OnConnect(c websocket.Connection) {
|
||||
fmt.Println("socket.OnConnect()")
|
||||
c.On("join", func(message string) { OnJoin(message, c) })
|
||||
c.On("objectupdate", func(message string) { OnObjectUpdated(message, c) })
|
||||
// ok works too c.EmitMessage([]byte("dsadsa"))
|
||||
c.OnDisconnect(func() { OnDisconnect(c) })
|
||||
|
||||
}
|
||||
|
||||
// ServerLoop listen and serve websocket requests
|
||||
func ServerLoop() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger()) // enable all (error) logs
|
||||
app.Adapt(httprouter.New()) // select the httprouter as the servemux
|
||||
|
||||
ws := websocket.New(websocket.Config{Endpoint: "/socket"})
|
||||
app.Adapt(ws)
|
||||
|
||||
ws.OnConnection(OnConnect)
|
||||
app.Listen("0.0.0.0:9090")
|
||||
|
||||
}
|
||||
|
||||
// OnJoin handles Join broadcast group request
|
||||
func OnJoin(message string, c websocket.Connection) {
|
||||
t := time.Now()
|
||||
c.Join("server2")
|
||||
fmt.Println("OnJoin() time taken:", time.Since(t))
|
||||
}
|
||||
|
||||
// OnObjectUpdated broadcasts to all client an incoming message
|
||||
func OnObjectUpdated(message string, c websocket.Connection) {
|
||||
t := time.Now()
|
||||
s := strings.Split(message, ";")
|
||||
if len(s) != 3 {
|
||||
fmt.Println("OnObjectUpdated() invalid message format:" + message)
|
||||
return
|
||||
}
|
||||
serverID, _, objectID := s[0], s[1], s[2]
|
||||
err := c.To("server"+serverID).Emit("objectupdate", objectID)
|
||||
if err != nil {
|
||||
fmt.Println(err, "failed to broacast object")
|
||||
return
|
||||
}
|
||||
fmt.Println(fmt.Sprintf("OnObjectUpdated() message:%v, time taken: %v", message, time.Since(t)))
|
||||
}
|
||||
|
||||
// OnDisconnect clean up things when a client is disconnected
|
||||
func OnDisconnect(c websocket.Connection) {
|
||||
c.Leave("server2")
|
||||
fmt.Println("OnDisconnect(): client disconnected!")
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/websocket"
|
||||
)
|
||||
|
||||
/* Native messages no need to import the iris-ws.js to the ./templates.client.html
|
||||
Use of: OnMessage and EmitMessage.
|
||||
|
||||
|
||||
NOTICE: IF YOU HAVE RAN THE PREVIOUS EXAMPLES YOU HAVE TO CLEAR YOUR BROWSER's CACHE
|
||||
BECAUSE chat.js is different than the CACHED. OTHERWISE YOU WILL GET Ws is undefined from the browser's console, becuase it will use the cached.
|
||||
*/
|
||||
|
||||
type clientPage struct {
|
||||
Title string
|
||||
Host string
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger()) // enable all (error) logs
|
||||
app.Adapt(httprouter.New()) // select the httprouter as the servemux
|
||||
app.Adapt(view.HTML("./templates", ".html")) // select the html engine to serve templates
|
||||
|
||||
ws := websocket.New(websocket.Config{
|
||||
// the path which the websocket client should listen/registered to,
|
||||
Endpoint: "/my_endpoint",
|
||||
// to enable binary messages (useful for protobuf):
|
||||
// BinaryMessages: true,
|
||||
})
|
||||
|
||||
app.Adapt(ws) // adapt the websocket server, you can adapt more than one with different Endpoint
|
||||
|
||||
app.StaticWeb("/js", "./static/js") // serve our custom javascript code
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
ctx.Render("client.html", clientPage{"Client Page", ctx.Host()})
|
||||
})
|
||||
|
||||
ws.OnConnection(func(c websocket.Connection) {
|
||||
|
||||
c.OnMessage(func(data []byte) {
|
||||
message := string(data)
|
||||
c.To(websocket.Broadcast).EmitMessage([]byte("Message from: " + c.ID() + "-> " + message)) // broadcast to all clients except this
|
||||
c.EmitMessage([]byte("Me: " + message)) // writes to itself
|
||||
})
|
||||
|
||||
c.OnDisconnect(func() {
|
||||
fmt.Printf("\nConnection with ID: %s has been disconnected!", c.ID())
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
var messageTxt;
|
||||
var messages;
|
||||
|
||||
$(function () {
|
||||
|
||||
messageTxt = $("#messageTxt");
|
||||
messages = $("#messages");
|
||||
|
||||
|
||||
w = new WebSocket("ws://" + HOST + "/my_endpoint");
|
||||
w.onopen = function () {
|
||||
console.log("Websocket connection enstablished");
|
||||
};
|
||||
|
||||
w.onclose = function () {
|
||||
appendMessage($("<div><center><h3>Disconnected</h3></center></div>"));
|
||||
};
|
||||
w.onmessage = function(message){
|
||||
appendMessage($("<div>" + message.data + "</div>"));
|
||||
};
|
||||
|
||||
|
||||
$("#sendBtn").click(function () {
|
||||
w.send(messageTxt.val().toString());
|
||||
messageTxt.val("");
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
|
||||
function appendMessage(messageDiv) {
|
||||
var theDiv = messages[0];
|
||||
var doScroll = theDiv.scrollTop == theDiv.scrollHeight - theDiv.clientHeight;
|
||||
messageDiv.appendTo(messages);
|
||||
if (doScroll) {
|
||||
theDiv.scrollTop = theDiv.scrollHeight - theDiv.clientHeight;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{{ .Title}}</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="messages"
|
||||
style="border-width: 1px; border-style: solid; height: 400px; width: 375px;">
|
||||
|
||||
</div>
|
||||
<input type="text" id="messageTxt" />
|
||||
<button type="button" id="sendBtn">Send</button>
|
||||
<script type="text/javascript">
|
||||
var HOST = {{.Host}}
|
||||
</script>
|
||||
<script src="js/vendor/jquery-2.2.3.min.js" type="text/javascript"></script>
|
||||
<script src="js/chat.js" type="text/javascript"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
99
_examples/examples/intermediate/websockets/overview/main.go
Normal file
99
_examples/examples/intermediate/websockets/overview/main.go
Normal file
@@ -0,0 +1,99 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt" // optional
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/websocket"
|
||||
)
|
||||
|
||||
type clientPage struct {
|
||||
Title string
|
||||
Host string
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger()) // enable all (error) logs
|
||||
app.Adapt(httprouter.New()) // select the httprouter as the servemux
|
||||
app.Adapt(view.HTML("./templates", ".html")) // select the html engine to serve templates
|
||||
|
||||
ws := websocket.New(websocket.Config{
|
||||
// the path which the websocket client should listen/registered to,
|
||||
Endpoint: "/my_endpoint",
|
||||
// the client-side javascript static file path
|
||||
// which will be served by Iris.
|
||||
// default is /iris-ws.js
|
||||
// if you change that you have to change the bottom of templates/client.html
|
||||
// script tag:
|
||||
ClientSourcePath: "/iris-ws.js",
|
||||
//
|
||||
// Set the timeouts, 0 means no timeout
|
||||
// websocket has more configuration, go to ../../config.go for more:
|
||||
// WriteTimeout: 0,
|
||||
// ReadTimeout: 0,
|
||||
// by-default all origins are accepted, you can change this behavior by setting:
|
||||
// CheckOrigin: (r *http.Request ) bool {},
|
||||
//
|
||||
//
|
||||
// IDGenerator used to create (and later on, set)
|
||||
// an ID for each incoming websocket connections (clients).
|
||||
// The request is an argument which you can use to generate the ID (from headers for example).
|
||||
// If empty then the ID is generated by DefaultIDGenerator: randomString(64):
|
||||
// IDGenerator func(ctx *iris.Context) string {},
|
||||
})
|
||||
|
||||
app.Adapt(ws) // adapt the websocket server, you can adapt more than one with different Endpoint
|
||||
|
||||
app.StaticWeb("/js", "./static/js") // serve our custom javascript code
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
ctx.Render("client.html", clientPage{"Client Page", ctx.Host()})
|
||||
})
|
||||
|
||||
var myChatRoom = "room1"
|
||||
|
||||
ws.OnConnection(func(c websocket.Connection) {
|
||||
// Context returns the (upgraded) *iris.Context of this connection
|
||||
// avoid using it, you normally don't need it,
|
||||
// websocket has everything you need to authenticate the user BUT if it's necessary
|
||||
// then you use it to receive user information, for example: from headers.
|
||||
|
||||
// ctx := c.Context()
|
||||
|
||||
// join to a room (optional)
|
||||
c.Join(myChatRoom)
|
||||
|
||||
c.On("chat", func(message string) {
|
||||
if message == "leave" {
|
||||
c.Leave(myChatRoom)
|
||||
c.To(myChatRoom).Emit("chat", "Client with ID: "+c.ID()+" left from the room and cannot send or receive message to/from this room.")
|
||||
c.Emit("chat", "You have left from the room: "+myChatRoom+" you cannot send or receive any messages from others inside that room.")
|
||||
return
|
||||
}
|
||||
// to all except this connection ->
|
||||
// c.To(websocket.Broadcast).Emit("chat", "Message from: "+c.ID()+"-> "+message)
|
||||
// to all connected clients: c.To(websocket.All)
|
||||
|
||||
// to the client itself ->
|
||||
//c.Emit("chat", "Message from myself: "+message)
|
||||
|
||||
//send the message to the whole room,
|
||||
//all connections are inside this room will receive this message
|
||||
c.To(myChatRoom).Emit("chat", "From: "+c.ID()+": "+message)
|
||||
})
|
||||
|
||||
// or create a new leave event
|
||||
// c.On("leave", func() {
|
||||
// c.Leave(myChatRoom)
|
||||
// })
|
||||
|
||||
c.OnDisconnect(func() {
|
||||
fmt.Printf("Connection with ID: %s has been disconnected!\n", c.ID())
|
||||
})
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
var messageTxt;
|
||||
var messages;
|
||||
|
||||
$(function () {
|
||||
|
||||
messageTxt = $("#messageTxt");
|
||||
messages = $("#messages");
|
||||
|
||||
|
||||
w = new Ws("ws://" + HOST + "/my_endpoint");
|
||||
w.OnConnect(function () {
|
||||
console.log("Websocket connection established");
|
||||
});
|
||||
|
||||
w.OnDisconnect(function () {
|
||||
appendMessage($("<div><center><h3>Disconnected</h3></center></div>"));
|
||||
});
|
||||
|
||||
w.On("chat", function (message) {
|
||||
appendMessage($("<div>" + message + "</div>"));
|
||||
});
|
||||
|
||||
$("#sendBtn").click(function () {
|
||||
w.Emit("chat", messageTxt.val().toString());
|
||||
messageTxt.val("");
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
|
||||
function appendMessage(messageDiv) {
|
||||
var theDiv = messages[0];
|
||||
var doScroll = theDiv.scrollTop == theDiv.scrollHeight - theDiv.clientHeight;
|
||||
messageDiv.appendTo(messages);
|
||||
if (doScroll) {
|
||||
theDiv.scrollTop = theDiv.scrollHeight - theDiv.clientHeight;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{{ .Title}}</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="messages"
|
||||
style="border-width: 1px; border-style: solid; height: 400px; width: 375px;">
|
||||
|
||||
</div>
|
||||
<input type="text" id="messageTxt" />
|
||||
<button type="button" id="sendBtn">Send</button>
|
||||
<script type="text/javascript">
|
||||
var HOST = {{.Host}}
|
||||
</script>
|
||||
<script src="js/vendor/jquery-2.2.3.min.js" type="text/javascript"></script>
|
||||
<!-- This is auto-serving by the Iris, you don't need to have this file in your disk-->
|
||||
<script src="/iris-ws.js" type="text/javascript"></script>
|
||||
<!-- -->
|
||||
<script src="js/chat.js" type="text/javascript"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/websocket"
|
||||
)
|
||||
|
||||
func handleConnection(c websocket.Connection) {
|
||||
|
||||
// Read events from browser
|
||||
c.On("chat", func(msg string) {
|
||||
|
||||
// Print the message to the console
|
||||
fmt.Printf("%s sent: %s\n", c.Context().RemoteAddr(), msg)
|
||||
|
||||
// Write message back to browser
|
||||
c.Emit("chat", msg)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger())
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
// create our echo websocket server
|
||||
ws := websocket.New(websocket.Config{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
Endpoint: "/echo",
|
||||
})
|
||||
|
||||
ws.OnConnection(handleConnection)
|
||||
|
||||
// Adapt the websocket server.
|
||||
// you can adapt more than one of course.
|
||||
app.Adapt(ws)
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
ctx.ServeFile("websockets.html", false) // second parameter: enable gzip?
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<input id="input" type="text" />
|
||||
<button onclick="send()">Send</button>
|
||||
<pre id="output"></pre>
|
||||
<script src="/iris-ws.js"></script>
|
||||
<script>
|
||||
var input = document.getElementById("input");
|
||||
var output = document.getElementById("output");
|
||||
|
||||
// Ws comes from the auto-served '/iris-ws.js'
|
||||
var socket = new Ws("ws://localhost:8080/echo");
|
||||
socket.OnConnect(function () {
|
||||
output.innerHTML += "Status: Connected\n";
|
||||
});
|
||||
|
||||
socket.OnDisconnect(function () {
|
||||
output.innerHTML += "Status: Disconnected\n";
|
||||
});
|
||||
|
||||
// read events from the server
|
||||
socket.On("chat", function (msg) {
|
||||
output.innerHTML += "Server: " + msg + "\n";
|
||||
});
|
||||
|
||||
function send() {
|
||||
// send chat event data to the server
|
||||
socket.Emit("chat", input.value);
|
||||
input.value = "";
|
||||
}
|
||||
</script>
|
||||
197
_examples/examples/intermediate/websockets/secure/main.go
Normal file
197
_examples/examples/intermediate/websockets/secure/main.go
Normal file
@@ -0,0 +1,197 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt" // optional
|
||||
"io/ioutil" // optional
|
||||
"os" // optional
|
||||
"time" // optional
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/websocket"
|
||||
)
|
||||
|
||||
type clientPage struct {
|
||||
Title string
|
||||
Host string
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger()) // enable all (error) logs
|
||||
app.Adapt(httprouter.New()) // select the httprouter as the servemux
|
||||
app.Adapt(view.HTML("./templates", ".html")) // select the html engine to serve templates
|
||||
|
||||
ws := websocket.New(websocket.Config{
|
||||
// the path which the websocket client should listen/registered to,
|
||||
Endpoint: "/my_endpoint",
|
||||
// the client-side javascript static file path
|
||||
// which will be served by Iris.
|
||||
// default is /iris-ws.js
|
||||
// if you change that you have to change the bottom of templates/client.html
|
||||
// script tag:
|
||||
ClientSourcePath: "/iris-ws.js",
|
||||
//
|
||||
// Set the timeouts, 0 means no timeout
|
||||
// websocket has more configuration, go to ../../config.go for more:
|
||||
// WriteTimeout: 0,
|
||||
// ReadTimeout: 0,
|
||||
// by-default all origins are accepted, you can change this behavior by setting:
|
||||
// CheckOrigin: (r *http.Request ) bool {},
|
||||
//
|
||||
//
|
||||
// IDGenerator used to create (and later on, set)
|
||||
// an ID for each incoming websocket connections (clients).
|
||||
// The request is an argument which you can use to generate the ID (from headers for example).
|
||||
// If empty then the ID is generated by DefaultIDGenerator: randomString(64):
|
||||
// IDGenerator func(ctx *iris.Context) string {},
|
||||
})
|
||||
|
||||
app.Adapt(ws) // adapt the websocket server, you can adapt more than one with different Endpoint
|
||||
|
||||
app.StaticWeb("/js", "./static/js") // static route to serve our javascript files
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
// send our custom javascript source file before client really asks for that
|
||||
// using the new go v1.8's HTTP/2 Push.
|
||||
// Note that you have to listen using ListenTLS in order this to work.
|
||||
if err := ctx.Push("/js/chat.js", nil); err != nil {
|
||||
app.Log(iris.DevMode, err.Error())
|
||||
}
|
||||
ctx.Render("client.html", clientPage{"Client Page", ctx.Host()})
|
||||
})
|
||||
|
||||
var myChatRoom = "room1"
|
||||
|
||||
ws.OnConnection(func(c websocket.Connection) {
|
||||
// Context returns the (upgraded) *iris.Context of this connection
|
||||
// avoid using it, you normally don't need it,
|
||||
// websocket has everything you need to authenticate the user BUT if it's necessary
|
||||
// then you use it to receive user information, for example: from headers.
|
||||
|
||||
// ctx := c.Context()
|
||||
|
||||
// join to a room (optional)
|
||||
c.Join(myChatRoom)
|
||||
|
||||
c.On("chat", func(message string) {
|
||||
if message == "leave" {
|
||||
c.Leave(myChatRoom)
|
||||
c.To(myChatRoom).Emit("chat", "Client with ID: "+c.ID()+" left from the room and cannot send or receive message to/from this room.")
|
||||
c.Emit("chat", "You have left from the room: "+myChatRoom+" you cannot send or receive any messages from others inside that room.")
|
||||
return
|
||||
}
|
||||
// to all except this connection ->
|
||||
// c.To(websocket.Broadcast).Emit("chat", "Message from: "+c.ID()+"-> "+message)
|
||||
// to all connected clients: c.To(websocket.All)
|
||||
|
||||
// to the client itself ->
|
||||
//c.Emit("chat", "Message from myself: "+message)
|
||||
|
||||
//send the message to the whole room,
|
||||
//all connections are inside this room will receive this message
|
||||
c.To(myChatRoom).Emit("chat", "From: "+c.ID()+": "+message)
|
||||
})
|
||||
|
||||
// or create a new leave event
|
||||
// c.On("leave", func() {
|
||||
// c.Leave(myChatRoom)
|
||||
// })
|
||||
|
||||
c.OnDisconnect(func() {
|
||||
fmt.Printf("Connection with ID: %s has been disconnected!\n", c.ID())
|
||||
})
|
||||
})
|
||||
|
||||
listenTLS(app)
|
||||
|
||||
}
|
||||
|
||||
// a test listenTLS for our localhost
|
||||
func listenTLS(app *iris.Framework) {
|
||||
|
||||
const (
|
||||
testTLSCert = `-----BEGIN CERTIFICATE-----
|
||||
MIIDBTCCAe2gAwIBAgIJAOYzROngkH6NMA0GCSqGSIb3DQEBBQUAMBkxFzAVBgNV
|
||||
BAMMDmxvY2FsaG9zdDo4MDgwMB4XDTE3MDIxNzAzNDM1NFoXDTI3MDIxNTAzNDM1
|
||||
NFowGTEXMBUGA1UEAwwObG9jYWxob3N0OjgwODAwggEiMA0GCSqGSIb3DQEBAQUA
|
||||
A4IBDwAwggEKAoIBAQCfsiVHO14FpKsi0pvBv68oApQm2MO+dCvq87sDU4E0QJhG
|
||||
KV1RCUmQVypChEqdLlUQsopcXSyKwbWoyg1/KNHYO3DHMfePb4bC1UD2HENq7Ph2
|
||||
8QJTEi/CJvUB9hqke/YCoWYdjFiI3h3Hw8q5whGO5XR3R23z69vr5XxoNlcF2R+O
|
||||
TdkzArd0CWTZS27vbgdnyi9v3Waydh/rl+QRtPUgEoCEqOOkMSMldXO6Z9GlUk9b
|
||||
FQHwIuEnlSoVFB5ot5cqebEjJnWMLLP83KOCQekJeHZOyjeTe8W0Fy1DGu5fvFNh
|
||||
xde9e/7XlFE//00vT7nBmJAUV/2CXC8U5lsjLEqdAgMBAAGjUDBOMB0GA1UdDgQW
|
||||
BBQOfENuLn/t0Z4ZY1+RPWaz7RBH+TAfBgNVHSMEGDAWgBQOfENuLn/t0Z4ZY1+R
|
||||
PWaz7RBH+TAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBG7AEEuIq6
|
||||
rWCE5I2t4IXz0jN7MilqEhUWDbUajl1paYf6Ikx5QhMsFx21p6WEWYIYcnWAKZe2
|
||||
chAgnnGojuxdx0qjiaH4N4xWGHsWhaesnIF1xJepLlX3kJZQURvRxM4wlljlQPIb
|
||||
9tqzKP131K1HDqplAtp7nWQ72m3J0ZfzH0mYIUxuaS/uQIVtgKqdilwy/VE5dRZ9
|
||||
QFIb4G9TnNThXMqgTLjfNr33jVbTuv6fzKHYNbCkP3L10ydEs/ddlREmtsn9nE8Q
|
||||
XCTIYXzA2kr5kWk7d3LkUiSvu3g2S1Ol1YaIKaOQyRveseCGwR4xohLT+dPUW9dL
|
||||
3hDVLlwE3mB3
|
||||
-----END CERTIFICATE-----
|
||||
|
||||
`
|
||||
testTLSKey = `-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEogIBAAKCAQEAn7IlRzteBaSrItKbwb+vKAKUJtjDvnQr6vO7A1OBNECYRild
|
||||
UQlJkFcqQoRKnS5VELKKXF0sisG1qMoNfyjR2DtwxzH3j2+GwtVA9hxDauz4dvEC
|
||||
UxIvwib1AfYapHv2AqFmHYxYiN4dx8PKucIRjuV0d0dt8+vb6+V8aDZXBdkfjk3Z
|
||||
MwK3dAlk2Utu724HZ8ovb91msnYf65fkEbT1IBKAhKjjpDEjJXVzumfRpVJPWxUB
|
||||
8CLhJ5UqFRQeaLeXKnmxIyZ1jCyz/NyjgkHpCXh2Tso3k3vFtBctQxruX7xTYcXX
|
||||
vXv+15RRP/9NL0+5wZiQFFf9glwvFOZbIyxKnQIDAQABAoIBAEzBx4ExW8PCni8i
|
||||
o5LAm2PTuXniflMwa1uGwsCahmOjGI3AnAWzPRSPkNRf2a0q8+AOsMosTphy+umi
|
||||
FFKmQBZ6m35i2earaE6FSbABbbYbKGGi/ccH2sSrDOBgdfXRTzF8eiSBrJw8hnvZ
|
||||
87rNOLtCNnSOdJ7lItODfgRo+fLo4uQenJ8VONYwtwm1ejn8qLXq8O5zF66IYUD6
|
||||
gAzqOiAWumgZL0tEmndeQ+noe4STpJZlOjiCsA12NiJaKDDeDIn5A/pXce+bYNfJ
|
||||
k4yoroyq/JXBkhyuZDvX9vYp5AA+Q68h8/KmsKkifUgSGSHun5/80lYyT/f60TLX
|
||||
PxT9GYECgYEA0s8qck7L29nBBTQ6IPF3GHGmqiRdfH+qhP/Jn4NtoW3XuVe4A15i
|
||||
REq1L8WAiOUIBnBaD8HzbeioqJJYx1pu7x9h/GCNDhdBfwhTjnBe+JjfLqvJKnc0
|
||||
HUT5wj4DVqattxKzUW8kTRBSWtVremzeffDo+EL6dnR7Bc02Ibs4WpUCgYEAwe34
|
||||
Uqhie+/EFr4HjYRUNZSNgYNAJkKHVxk4qGzG5VhvjPafnHUbo+Kk/0QW7eIB+kvR
|
||||
FDO8oKh9wTBrWZEcLJP4jDIKh4y8hZTo9B8EjxFONXVxZlOSYuGjheL8AiLzE7L9
|
||||
C1spaKMM/MyxAXDRHpG/NeEgXM7Kn6kUGwJdNekCgYAshLNiEGHcu8+XWcAs1NFh
|
||||
yB56L9PORuerzpi1pvuv65JzAaNKktQNt/krbXoHbtaTBYb/bOYLf+aeMsmsz9w9
|
||||
g1MeCQXAxAiA2zFKE1D7Ds2S/ZQt8559z+MusgnicrCcyMY1nFL+M0QxCoD4CaWy
|
||||
0v1f8EUUXuTcBMo5tV/hQQKBgDoBBW8jsiFDu7DZscSgOde00QZVzZAkAfsJLisi
|
||||
LfNXGjZdZawUUuoX1iYLpZgNK25D0wtp1hdvjf2Ej/dAMd8bexHjvcaBT7ncqjiq
|
||||
NmDcWjofIIXspTIyLwjStXGmJnJT7N/CqoYDjtTmHGND7Shpi3mAFn/r0isjFUJm
|
||||
2J5RAoGALuGXxzmSRWmkIp11F/Qr3PBFWBWkrRWaH2TRLMhrU/wO8kCsSyo4PmAZ
|
||||
ltOfD7InpDiCu43hcDPQ/29FUbDnmAhvMnmIQuHXGgPF/LhqEhbKPA/o/eZdQVCK
|
||||
QG+tmveBBIYMed5YbWstZu/95lIHF+u8Hl+Z6xgveozfE5yqiUA=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
|
||||
`
|
||||
)
|
||||
|
||||
// create the key and cert files on the fly, and delete them when this test finished
|
||||
certFile, ferr := ioutil.TempFile("", "cert")
|
||||
|
||||
if ferr != nil {
|
||||
panic(ferr)
|
||||
}
|
||||
|
||||
keyFile, ferr := ioutil.TempFile("", "key")
|
||||
if ferr != nil {
|
||||
panic(ferr)
|
||||
}
|
||||
|
||||
certFile.WriteString(testTLSCert)
|
||||
keyFile.WriteString(testTLSKey)
|
||||
|
||||
// add an event when control+C pressed, to remove the temp cert and key files.
|
||||
app.Adapt(iris.EventPolicy{
|
||||
Interrupted: func(*iris.Framework) {
|
||||
certFile.Close()
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
os.Remove(certFile.Name())
|
||||
|
||||
keyFile.Close()
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
os.Remove(keyFile.Name())
|
||||
},
|
||||
})
|
||||
|
||||
// https://localhost
|
||||
app.ListenTLS("localhost:443", certFile.Name(), keyFile.Name())
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
var messageTxt;
|
||||
var messages;
|
||||
|
||||
$(function () {
|
||||
|
||||
messageTxt = $("#messageTxt");
|
||||
messages = $("#messages");
|
||||
|
||||
/* secure wss because we ListenTLS */
|
||||
w = new Ws("wss://" + HOST + "/my_endpoint");
|
||||
w.OnConnect(function () {
|
||||
console.log("Websocket connection established");
|
||||
});
|
||||
|
||||
w.OnDisconnect(function () {
|
||||
appendMessage($("<div><center><h3>Disconnected</h3></center></div>"));
|
||||
});
|
||||
|
||||
w.On("chat", function (message) {
|
||||
appendMessage($("<div>" + message + "</div>"));
|
||||
});
|
||||
|
||||
$("#sendBtn").click(function () {
|
||||
w.Emit("chat", messageTxt.val().toString());
|
||||
messageTxt.val("");
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
|
||||
function appendMessage(messageDiv) {
|
||||
var theDiv = messages[0];
|
||||
var doScroll = theDiv.scrollTop == theDiv.scrollHeight - theDiv.clientHeight;
|
||||
messageDiv.appendTo(messages);
|
||||
if (doScroll) {
|
||||
theDiv.scrollTop = theDiv.scrollHeight - theDiv.clientHeight;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>{{ .Title}}</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="messages"
|
||||
style="border-width: 1px; border-style: solid; height: 400px; width: 375px;">
|
||||
|
||||
</div>
|
||||
<input type="text" id="messageTxt" />
|
||||
<button type="button" id="sendBtn">Send</button>
|
||||
<script type="text/javascript">
|
||||
var HOST = {{.Host}}
|
||||
</script>
|
||||
<script src="/js/vendor/jquery-2.2.3.min.js"></script>
|
||||
<!-- This is auto-serving by the Iris, you don't need to have this file in your disk-->
|
||||
<script src="/iris-ws.js"></script>
|
||||
<!-- -->
|
||||
<script src="/js/chat.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user