mirror of
https://github.com/kataras/iris.git
synced 2026-03-14 04:09:37 +00:00
Add More Examples & Categorized in Folders & TOC
Former-commit-id: ce4d711a75a4ba08ffab075e6baa88724725885b
This commit is contained in:
@@ -1,43 +0,0 @@
|
||||
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")
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/gorillamux" // import the gorillamux adaptor
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger()) // writes both prod and dev logs to the os.Stdout
|
||||
app.Adapt(gorillamux.New()) // uses the gorillamux for routing and reverse routing
|
||||
|
||||
// set a custom 404 handler
|
||||
app.OnError(iris.StatusNotFound, func(ctx *iris.Context) {
|
||||
ctx.HTML(iris.StatusNotFound, "<h1> custom http error page </h1>")
|
||||
})
|
||||
|
||||
app.Get("/healthcheck", h)
|
||||
|
||||
gamesMiddleware := func(ctx *iris.Context) {
|
||||
println(ctx.Method() + ": " + ctx.Path())
|
||||
ctx.Next()
|
||||
}
|
||||
|
||||
games := app.Party("/games", gamesMiddleware)
|
||||
{ // braces are optional of course, it's just a style of code
|
||||
games.Get("/{gameID:[0-9]+}/clans", h)
|
||||
games.Get("/{gameID:[0-9]+}/clans/clan/{publicID:[0-9]+}", h)
|
||||
games.Get("/{gameID:[0-9]+}/clans/search", h)
|
||||
|
||||
games.Put("/{gameID:[0-9]+}/players/{publicID:[0-9]+}", h)
|
||||
games.Put("/{gameID:[0-9]+}/clans/clan/{publicID:[0-9]+}", h)
|
||||
|
||||
games.Post("/{gameID:[0-9]+}/clans", h)
|
||||
games.Post("/{gameID:[0-9]+}/players", h)
|
||||
games.Post("/{gameID:[0-9]+}/clans/{publicID:[0-9]+}/leave", h)
|
||||
games.Post("/{gameID:[0-9]+}/clans/{clanPublicID:[0-9]+}/memberships/application", h)
|
||||
games.Post("/{gameID:[0-9]+}/clans/{clanPublicID:[0-9]+}/memberships/application/:action", h)
|
||||
games.Post("/{gameID:[0-9]+}/clans/{clanPublicID:[0-9]+}/memberships/invitation", h)
|
||||
games.Post("/{gameID:[0-9]+}/clans/{clanPublicID:[0-9]+}/memberships/invitation/:action", h)
|
||||
games.Post("/{gameID:[0-9]+}/clans/{clanPublicID:[0-9]+}/memberships/delete", h)
|
||||
games.Post("/{gameID:[0-9]+}/clans/{clanPublicID:[0-9]+}/memberships/promote", h)
|
||||
games.Post("/{gameID:[0-9]+}/clans/{clanPublicID:[0-9]+}/memberships/demote", h)
|
||||
}
|
||||
|
||||
myroute := app.Get("/anything/{anythingparameter:.*}", func(ctx *iris.Context) {
|
||||
s := ctx.Param("anythingparameter")
|
||||
ctx.Writef("The path after /anything is: %s", s)
|
||||
}) // .ChangeName("myroute")
|
||||
|
||||
app.Get("/reverse_myroute", func(ctx *iris.Context) {
|
||||
// reverse routing snippet using templates:
|
||||
// https://github.com/kataras/iris/tree/v6/adaptors/view/_examples/template_html_3 (gorillamux)
|
||||
// https://github.com/kataras/iris/tree/v6/adaptors/view/_examples/template_html_4 (httprouter)
|
||||
|
||||
myrouteRequestPath := app.Path(myroute.Name(), "anythingparameter", "something/here")
|
||||
ctx.Writef("Should be '/anything/something/here': %s", myrouteRequestPath)
|
||||
})
|
||||
|
||||
p := app.Party("mysubdomain.")
|
||||
// http://mysubdomain.myhost.com/
|
||||
p.Get("/", h)
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
func h(ctx *iris.Context) {
|
||||
ctx.HTML(iris.StatusOK, "<h1>Path<h1/>"+ctx.Path())
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
)
|
||||
|
||||
func hello(ctx *iris.Context) {
|
||||
ctx.Writef("Hello from %s", ctx.Path())
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger())
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
app.OnError(iris.StatusNotFound, func(ctx *iris.Context) {
|
||||
ctx.HTML(iris.StatusNotFound, "<h1>Custom not found handler </h1>")
|
||||
})
|
||||
|
||||
app.Get("/", hello)
|
||||
app.Get("/users/:userid", func(ctx *iris.Context) {
|
||||
ctx.Writef("Hello user with id: %s", ctx.Param("userid"))
|
||||
})
|
||||
|
||||
app.Get("/myfiles/*file", func(ctx *iris.Context) {
|
||||
ctx.HTML(iris.StatusOK, "Hello, the dynamic path after /myfiles is:<br/> <b>"+ctx.Param("file")+"</b>")
|
||||
})
|
||||
|
||||
app.Get("/users/:userid/messages/:messageid", func(ctx *iris.Context) {
|
||||
ctx.HTML(iris.StatusOK, `Message from user with id:<br/> <b>`+ctx.Param("userid")+`</b>,
|
||||
message id: <b>`+ctx.Param("messageid")+`</b>`)
|
||||
})
|
||||
|
||||
// http://127.0.0.1:8080/users/42
|
||||
// http://127.0.0.1:8080/myfiles/mydirectory/myfile.zip
|
||||
// http://127.0.0.1:8080/users/42/messages/1
|
||||
app.Listen(":8080")
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
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")
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
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")
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
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")
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/typescript"
|
||||
)
|
||||
|
||||
// NOTE: Some machines don't allow to install typescript automatically, so if you don't have typescript installed
|
||||
// and the typescript adaptor doesn't works for you then follow the below steps:
|
||||
// 1. close the iris server
|
||||
// 2. open your terminal and execute: npm install -g typescript
|
||||
// 3. start your iris server, it should be work, as expected, now.
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger())
|
||||
app.Adapt(httprouter.New()) // adapt a router, order doesn't matters but before Listen.
|
||||
|
||||
ts := typescript.New()
|
||||
ts.Config.Dir = "./www/scripts"
|
||||
app.Adapt(ts) // adapt the typescript compiler adaptor
|
||||
|
||||
app.StaticWeb("/", "./www") // serve the index.html
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
// open http://localhost:8080
|
||||
// go to ./www/scripts/app.ts
|
||||
// make a change
|
||||
// reload the http://localhost:8080 and you should see the changes
|
||||
//
|
||||
// what it does?
|
||||
// - compiles the typescript files using default compiler options if not tsconfig found
|
||||
// - watches for changes on typescript files, if a change then it recompiles the .ts to .js
|
||||
//
|
||||
// same as you used to do with gulp-like tools, but here at Iris I do my bests to help GO developers.
|
||||
@@ -1,8 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Load my script (lawl)</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="scripts/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,16 +0,0 @@
|
||||
class User{
|
||||
private name: string;
|
||||
|
||||
constructor(fullname:string) {
|
||||
this.name = fullname;
|
||||
}
|
||||
|
||||
Hi(msg: string): string {
|
||||
return msg + " "+ this.name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var user = new User("kataras");
|
||||
var hi = user.Hi("Hello");
|
||||
window.alert(hi);
|
||||
@@ -1,35 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/typescript" // optinally
|
||||
"gopkg.in/kataras/iris.v6/adaptors/typescript/editor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger())
|
||||
app.Adapt(httprouter.New()) // adapt a router, order doesn't matters
|
||||
|
||||
// optionally but good to have, I didn't put inside editor or the editor in the typescript compiler adaptors
|
||||
// because you may use tools like gulp and you may use the editor without the typescript compiler adaptor.
|
||||
// but if you need auto-compilation on .ts, we have a solution:
|
||||
ts := typescript.New()
|
||||
ts.Config.Dir = "./www/scripts/"
|
||||
app.Adapt(ts) // adapt the typescript compiler adaptor
|
||||
|
||||
editorConfig := editor.Config{
|
||||
Hostname: "127.0.0.1",
|
||||
Port: 4444,
|
||||
WorkingDir: "./www/scripts/", // "/path/to/the/client/side/directory/",
|
||||
Username: "myusername",
|
||||
Password: "mypassword",
|
||||
}
|
||||
e := editor.New(editorConfig)
|
||||
app.Adapt(e) // adapt the editor
|
||||
|
||||
app.StaticWeb("/", "./www") // serve the index.html
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Load my script (lawl)</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="scripts/app.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,16 +0,0 @@
|
||||
class User{
|
||||
private name: string;
|
||||
|
||||
constructor(fullname:string) {
|
||||
this.name = fullname;
|
||||
}
|
||||
|
||||
Hi(msg: string): string {
|
||||
return msg + " " + this.name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var user = new User("kataras");
|
||||
var hi = user.Hi("Hello");
|
||||
window.alert(hi);
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"noImplicitAny": false,
|
||||
"removeComments": true,
|
||||
"preserveConstEnums": true,
|
||||
"sourceMap": false,
|
||||
"target": "ES5",
|
||||
"noEmit": false,
|
||||
"watch":true,
|
||||
"noEmitOnError": true,
|
||||
"experimentalDecorators": false,
|
||||
"outDir": "./",
|
||||
"charset": "UTF-8",
|
||||
"noLib": false,
|
||||
"diagnostics": true,
|
||||
"declaration": false
|
||||
},
|
||||
"files": [
|
||||
"./app.ts"
|
||||
]
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
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")
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
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")
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Hi Iris</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hi {{.Name}} </h1>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,238 +0,0 @@
|
||||
// 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, "/")...)...)
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
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"})
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Hi Iris [THE TITLE]</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hi {{.Name}}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,23 +0,0 @@
|
||||
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"})
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Hi Iris</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hi {{.Name}} </h1>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,32 +0,0 @@
|
||||
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")
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>My Layout</title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<h1>Body is:</h1>
|
||||
<!-- Render the current template here -->
|
||||
{{ yield }}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,4 +0,0 @@
|
||||
<h1>
|
||||
Title: {{.Title}}
|
||||
</h1>
|
||||
<h3>Message: {{.Message}} </h3>
|
||||
@@ -1,3 +0,0 @@
|
||||
## Info
|
||||
|
||||
This folder examines the {{render "dir/templatefilename"}} functionality to manually render any template inside any template
|
||||
@@ -1,49 +0,0 @@
|
||||
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")
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Layout</title>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<h1>This is the global layout</h1>
|
||||
<br />
|
||||
<!-- Render the current template here -->
|
||||
{{ yield }}
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,12 +0,0 @@
|
||||
<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>
|
||||
@@ -1,7 +0,0 @@
|
||||
<div style="background-color: black; color: blue">
|
||||
|
||||
<h1>Page 1 {{ greet "iris developer"}}</h1>
|
||||
|
||||
{{ render "partials/page1_partial1.html"}}
|
||||
|
||||
</div>
|
||||
@@ -1,3 +0,0 @@
|
||||
<div style="background-color: white; color: red">
|
||||
<h1>Page 1's Partial 1</h1>
|
||||
</div>
|
||||
@@ -1,103 +0,0 @@
|
||||
// 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")
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<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>
|
||||
@@ -1,32 +0,0 @@
|
||||
# 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
|
||||
@@ -1,53 +0,0 @@
|
||||
// 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())
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
<!-- 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>
|
||||
@@ -1,99 +0,0 @@
|
||||
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")
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<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>
|
||||
@@ -1,113 +0,0 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<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>
|
||||
@@ -1,179 +0,0 @@
|
||||
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!")
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
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")
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
<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>
|
||||
@@ -1,197 +0,0 @@
|
||||
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())
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<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