Add notes for the new lead maintainer of the open-source iris project and align with @get-ion/ion by @hiveminded
Former-commit-id: da4f38eb9034daa49446df3ee529423b98f9b331
@@ -1,110 +1,164 @@
|
||||
# Examples
|
||||
|
||||
This folder provides easy to understand code snippets on how to get started with web development with the Go programming language using the [Iris](https://github.com/kataras/iris) web framework.
|
||||
Please do learn how [net/http](https://golang.org/pkg/net/http/) std package works, first.
|
||||
|
||||
It doesn't contains "best ways" neither explains all its features. It's just a simple, practical cookbook for young Gophers!
|
||||
This folder provides easy to understand code snippets on how to get started with [iris](https://github.com/kataras/iris) micro web framework.
|
||||
|
||||
## Table of contents
|
||||
It doesn't always contain the "best ways" but it does cover each important feature that will make you so excited to GO with iris!
|
||||
|
||||
* [Level: Beginner](beginner)
|
||||
* [Hello world](beginner/hello-world/main.go)
|
||||
* [Overview](beginner/overview/main.go)
|
||||
* [Listening](beginner/listening)
|
||||
* [Common, with address](beginner/listening/listen-addr/main.go)
|
||||
* [UNIX socket file](beginner/listening/listen-unix/main.go)
|
||||
* [TLS](beginner/listening/listen-tls/main.go)
|
||||
* [Letsencrypt (Automatic Certifications)](beginner/listening/listen-letsencrypt/main.go)
|
||||
* [Custom TCP Listener](beginner/listening/custom-listener/main.go)
|
||||
* [Configuration](beginner/configuration)
|
||||
* [Basic way](beginner/configuration/basic/main.go)
|
||||
* [Functional way](beginner/configuration/functional/main.go)
|
||||
* [Import from YAML file](beginner/configuration/from-yaml-file/main.go)
|
||||
* [Import from TOML file](beginner/configuration/from-toml-file/main.go)
|
||||
* [Routing](beginner/routing)
|
||||
* [Overview](beginner/routing/overview/main.go)
|
||||
* [Basic](beginner/routing/basic/main.go)
|
||||
* [Dynamic Path](beginner/routing/dynamic-path/main.go)
|
||||
* [Reverse routing](beginner/routing/reverse/main.go)
|
||||
* [Custom wrapper](beginner/routing/custom-wrapper/main.go)
|
||||
* [Transform any third-party handler to iris-compatible handler](beginner/convert-handlers)
|
||||
* [From func(http.ResponseWriter, *http.Request, http.HandlerFunc)](beginner/convert-handlers/negroni-like/main.go)
|
||||
* [From http.Handler or http.HandlerFunc](beginner/convert-handlers/nethttp/main.go)
|
||||
* [Internal Application File Logger](beginner/file-logger/main.go)
|
||||
* [Custom HTTP Errors](beginner/http-errors/main.go)
|
||||
* [Write JSON](beginner/write-json/main.go)
|
||||
* [Read JSON](beginner/read-json/main.go)
|
||||
* [Read Form](beginner/read-form/main.go)
|
||||
* [Favicon](beginner/favicon/main.go)
|
||||
* [File Server](beginner/file-server)
|
||||
* [Basic](beginner/file-server/basic/main.go)
|
||||
* [Embedding Files Into App Executable File](beginner/file-server/embedding-files-into-app/main.go)
|
||||
* [Single Page Application](beginner/file-server/single-page-application/main.go)
|
||||
* [Embedding Single Page Application](beginner/file-server/embedding-single-page-application/main.go)
|
||||
* [Send Files](beginner/send-files/main.go)
|
||||
* [Stream Writer](beginner/stream-writer/main.go)
|
||||
* [Send An E-mail](beginner/e-mail/main.go)
|
||||
* [Upload/Read Files](beginner/upload-files/main.go)
|
||||
* [Recovery](beginner/recover/main.go)
|
||||
* [Profiling (pprof)](beginner/pprof/main.go)
|
||||
* [Request Logger](beginner/request-logger/main.go)
|
||||
* [Basic Authentication](beginner/basicauth/main.go)
|
||||
* [Level: Intermediate](intermediate)
|
||||
* [JWT](https://github.com/iris-contrib/middleware/blob/master/jwt/_example/main.go)
|
||||
* [OAUth2](intermediate/oauth2/main.go)
|
||||
* [CORS](https://github.com/iris-contrib/middleware/blob/master/cors/_example/main.go)
|
||||
* [Transactions](intermediate/transactions/main.go)
|
||||
* [HTTP Testing](intermediate/httptest/main_test.go)
|
||||
* [Watch & Compile Typescript source files](intermediate/typescript/main.go)
|
||||
* [Cloud Editor](intermediate/cloud-editor/main.go)
|
||||
* [HTTP Access Control](intermediate/cors/main.go)
|
||||
* [Cache Markdown](intermediate/cache-markdown/main.go)
|
||||
* [Localization and Internationalization](intermediate/i18n/main.go)
|
||||
* [Graceful Shutdown](intermediate/graceful-shutdown)
|
||||
* [Basic and simple](intermediate/graceful-shutdown/basic/main.go)
|
||||
* [Custom Host](intermediate/graceful-shutdown/custom-host/main.go)
|
||||
* [Custom notifier](intermediate/graceful-shutdown/custom-notifier/main.go)
|
||||
* [Custom HTTP Server](intermediate/custom-httpserver)
|
||||
* [Iris way](intermediate/custom-httpserver/iris-way/main.go)
|
||||
* [Standar way](intermediate/custom-httpserver/std-way/main.go)
|
||||
* [More than one server](intermediate/custom-httpserver/multi/main.go)
|
||||
* [Custom Context](intermediate/custom-context)
|
||||
* [Method Overriding](intermediate/custom-context/method-overriding/main.go)
|
||||
* [Route State](intermediate/route-state/main.go)
|
||||
* [View Engine](intermediate/view)
|
||||
* [Overview](intermediate/view/overview/main.go)
|
||||
* [Hi](intermediate/view/template_html_0/main.go)
|
||||
* [Showcase one simple Layout](intermediate/view/template_html_1/main.go)
|
||||
* [Layouts `yield` and `render` tmpl funcs](intermediate/view/template_html_2/main.go)
|
||||
* [Showcase of the `urlpath` tmpl func](intermediate/view/template_html_3/main.go)
|
||||
* [Showcase of the `url` tmpl func](intermediate/view/template_html_4/main.go)
|
||||
* [Inject Data Between Handlers](intermediate/view/context-view-data/main.go)
|
||||
* [Embedding Templates Into App Executable File](intermediate/view/embedding-templates-into-app/main.go)
|
||||
* [Sessions](intermediate/sessions)
|
||||
* [Overview](intermediate/sessions/overview/main.go)
|
||||
* [Encoding & Decoding the Session ID: Secure Cookie](intermediate/sessions/securecookie/main.go)
|
||||
* [Standalone](intermediate/sessions/standalone/main.go)
|
||||
* [Flash Messages](intermediate/sessions/flash-messages/main.go)
|
||||
* [With A Back-End Database](intermediate/sessions/database/main.go)
|
||||
* [Password Hashing](intermediate/sessions/password-hashing/main.go)
|
||||
* [Websockets](intermediate/websockets)
|
||||
* [Ridiculous Simple](intermediate/websockets/ridiculous-simple/main.go)
|
||||
* [Overview](intermediate/websockets/overview/main.go)
|
||||
* [Connection List](intermediate/websockets/connectionlist/main.go)
|
||||
* [Native Messages](intermediate/websockets/native-messages/main.go)
|
||||
* [Secure](intermediate/websockets/secure/main.go)
|
||||
* [Custom Go Client](intermediate/websockets/custom-go-client/main.go)
|
||||
* [Subdomains](intermediate/subdomains)
|
||||
* [Single](intermediate/subdomains/single/main.go)
|
||||
* [Multi](intermediate/subdomains/multi/main.go)
|
||||
* [Wildcard](intermediate/subdomains/wildcard/main.go)
|
||||
* [WWW](intermediate/subdomains/www/main.go)
|
||||
* [Level: Advanced](advanced)
|
||||
* [Online Visitors](advanced/online-visitors/main.go)
|
||||
* [URL Shortener using BoltDB](advanced/url-shortener/main.go)
|
||||
### Overview
|
||||
|
||||
- [Hello world!](hello-world/main.go)
|
||||
- [Glimpse](overview/main.go)
|
||||
- [Tutorial: Online Visitors](tutorial/online-visitors/main.go)
|
||||
- [Tutorial: URL Shortener using BoltDB](tutorial/url-shortener/main.go)
|
||||
|
||||
### HTTP Listening
|
||||
|
||||
- [Common, with address](http-listening/listen-addr/main.go)
|
||||
- [UNIX socket file](http-listening/listen-unix/main.go)
|
||||
- [TLS](http-listening/listen-tls/main.go)
|
||||
- [Letsencrypt (Automatic Certifications)](http-listening/listen-letsencrypt/main.go)
|
||||
- Custom TCP Listener
|
||||
* [common net.Listener](http-listening/custom-listener/main.go)
|
||||
* [SO_REUSEPORT for unix systems](http-listening/custom-listener/unix-reuseport/main.go)
|
||||
- Custom HTTP Server
|
||||
* [iris way](http-listening/custom-httpserver/iris-way/main.go)
|
||||
* [std way](http-listening/custom-httpserver/std-way/main.go)
|
||||
* [multi server instances](http-listening/custom-httpserver/multi/main.go)
|
||||
- Graceful Shutdown
|
||||
* [using the `RegisterOnInterrupt`](http-listening/graceful-shutdown/default-notifier/main.go)
|
||||
* [using a custom notifier](http-listening/graceful-shutdown/custom-notifier/main.go)
|
||||
|
||||
### Configuration
|
||||
|
||||
- [Functional](configuration/functional/main.go)
|
||||
- [From Configuration Struct](configuration/from-configuration-struct/main.go)
|
||||
- [Import from YAML file](configuration/from-yaml-file/main.go)
|
||||
- [Import from TOML file](configuration/from-toml-file/main.go)
|
||||
|
||||
|
||||
You may want to check out examples for jwt, cors and the rest of community-maden middleware by clicking [here](https://github.com/iris-contrib/middleware)
|
||||
### Routing, Grouping, Dynamic Path Parameters, "Macros" and Custom Context
|
||||
|
||||
- [Overview](routing/overview/main.go)
|
||||
- [Basic](routing/basic/main.go)
|
||||
- [Custom HTTP Errors](routing/http-errors/main.go)
|
||||
- [Dynamic Path](routing/dynamic-path/main.go)
|
||||
- [Reverse routing](routing/reverse/main.go)
|
||||
- [Custom wrapper](routing/custom-wrapper/main.go)
|
||||
- Custom Context
|
||||
* [Method Overriding](routing/custom-context/method-overriding/main.go)
|
||||
* [New Implementation](routing/custom-context/new-implementation/main.go)
|
||||
- [Route State](routing/route-state/main.go)
|
||||
|
||||
### Subdomains
|
||||
|
||||
- [Single](subdomains/single/main.go)
|
||||
- [Multi](subdomains/multi/main.go)
|
||||
- [Wildcard](subdomains/wildcard/main.go)
|
||||
- [WWW](subdomains/www/main.go)
|
||||
|
||||
### Convert `http.Handler/HandlerFunc`
|
||||
|
||||
- [From func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc)](convert-handlers/negroni-like/main.go)
|
||||
- [From http.Handler or http.HandlerFunc](convert-handlers/nethttp/main.go)
|
||||
|
||||
### View
|
||||
|
||||
| Engine | Declaration |
|
||||
| -----------|-------------|
|
||||
| template/html | `iris.HTML(...)` |
|
||||
| django | `iris.Django(...)` |
|
||||
| handlebars | `iris.Handlebars(...)` |
|
||||
| amber | `iris.Amber(...)` |
|
||||
| pug(jade) | `iris.Pug(...)` |
|
||||
|
||||
- [Overview](view/overview/main.go)
|
||||
- [Hi](view/template_html_0/main.go)
|
||||
- [A simple Layout](view/template_html_1/main.go)
|
||||
- [Layouts: `yield` and `render` tmpl funcs](view/template_html_2/main.go)
|
||||
- [The `urlpath` tmpl func](view/template_html_3/main.go)
|
||||
- [The `url` tmpl func](view/template_html_4/main.go)
|
||||
- [Inject Data Between Handlers](view/context-view-data/main.go)
|
||||
- [Embedding Templates Into App Executable File](view/embedding-templates-into-app/main.go)
|
||||
|
||||
### Authentication
|
||||
|
||||
- [Basic Authentication](authentication/basicauth/main.go)
|
||||
- [OAUth2](authentication/oauth2/main.go)
|
||||
- [JWT](https://github.com/iris-contrib/middleware/blob/master/jwt/_example/main.go)
|
||||
- [Sessions](#sessions)
|
||||
|
||||
### File Server
|
||||
|
||||
- [Favicon](file-server/favicon/main.go)
|
||||
- [Basic](file-server/basic/main.go)
|
||||
- [Embedding Files Into App Executable File](file-server/embedding-files-into-app/main.go)
|
||||
- [Send/Force-Download Files](file-server/send-files/main.go)
|
||||
- Single Page Applications
|
||||
* [Single Page Application](file-server/single-page-application/basic/main.go)
|
||||
* [Embedded Single Page Application](file-server/single-page-application/embedded-single-page-application/main.go)
|
||||
|
||||
### How to Read from `context.Request() *http.Request`
|
||||
|
||||
- [Bind JSON](http_request/read-json/main.go)
|
||||
- [Bind Form](http_request/read-form/main.go)
|
||||
- [Upload/Read Files](http_request/upload-files/main.go)
|
||||
|
||||
> The `context.Request()` returns the same *http.Request you already know, these examples show some places where the Context uses this object. Besides that you can use it as you did before iris.
|
||||
|
||||
### How to Write to `context.ResponseWriter() http.ResponseWriter`
|
||||
|
||||
- [Text, Markdown, HTML, JSON, JSONP, XML, Binary](http_responsewriter/write-rest/main.go)
|
||||
- [Stream Writer](http_responsewriter/stream-writer/main.go)
|
||||
- [Transactions](http_responsewriter/transactions/main.go)
|
||||
|
||||
> The `context.ResponseWriter()` returns an enchament version of a http.ResponseWriter, these examples show some places where the Context uses this object. Besides that you can use it as you did before iris.
|
||||
|
||||
### Miscellaneous
|
||||
|
||||
- [Request Logger](http_request/request-logger/main.go)
|
||||
- [Localization and Internationalization](miscellaneous/i18n/main.go)
|
||||
- [Recovery](miscellaneous/recover/main.go)
|
||||
- [Profiling (pprof)](miscellaneous/pprof/main.go)
|
||||
- [Internal Application File Logger](miscellaneous/file-logger/main.go)
|
||||
|
||||
#### More
|
||||
|
||||
https://github.com/kataras/iris/tree/master/middleware#third-party-handlers
|
||||
|
||||
### Testing
|
||||
|
||||
The `httptest` package is your way for end-to-end HTTP testing, it uses the httpexpect library created by our friend, [gavv](https://github.com/gavv).
|
||||
|
||||
[Example](testing/httptest/main_test.go)
|
||||
|
||||
### Caching
|
||||
|
||||
iris cache library lives on its own package: [https://github.com/kataras/iris/tree/master/cache](https://github.com/kataras/iris/tree/master/cache) **it contains examples**
|
||||
|
||||
### Sessions
|
||||
|
||||
iris session manager lives on its own package: [https://github.com/kataras/iris/tree/master/sessions](https://github.com/kataras/iris/tree/master/sessions) **it contains examples**
|
||||
|
||||
> You're free to use your own favourite sessions package if you'd like so.
|
||||
|
||||
### Websockets
|
||||
|
||||
iris websocket library lives on its own package: [https://github.com/kataras/iris/tree/master/websocket](https://github.com/kataras/iris/tree/master/websocket) **it contains examples**
|
||||
|
||||
> You're free to use your own favourite websockets package if you'd like so.
|
||||
|
||||
### Typescript Automation Tools
|
||||
|
||||
typescript automation tools have their own repository: [https://github.com/kataras/iris/tree/master/typescript](https://github.com/kataras/iris/tree/master/typescript) **it contains examples**
|
||||
|
||||
> I'd like to tell you that you can use your favourite but I don't think you will find such a thing anywhere else.
|
||||
|
||||
### Hey, You!
|
||||
|
||||
Developers should read the [godocs](https://godoc.org/github.com/kataras/iris) for a better understanding.
|
||||
|
||||
Psst, I almost forgot; do not forget to [star or watch](https://github.com/kataras/iris/stargazers) the project in order to stay updated with the latest tech trends, it never takes more than a second!
|
||||
|
||||
> Do not forget to [star or watch the project](https://github.com/kataras/iris/stargazers) in order to stay updated with the latest tech trends, it takes some seconds for the sake of go!
|
||||
|
||||
> Developers should read the official [documentation](https://godoc.org/github.com/kataras/iris) in depth, for deep understanding.
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
package main
|
||||
|
||||
// Version is the current version of the url-shortener package.
|
||||
const Version = "0.0.1"
|
||||
6
_examples/authentication/README.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# Authentication
|
||||
|
||||
- [Basic Authentication](basicauth/main.go)
|
||||
- [OAUth2](oauth2/main.go)
|
||||
- [JWT](https://github.com/iris-contrib/middleware/blob/master/jwt/_example/main.go)
|
||||
- [Sessions](https://github.com/kataras/iris/tree/master/_examples/#sessions)
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/kataras/iris/middleware/basicauth"
|
||||
)
|
||||
|
||||
func main() {
|
||||
func newApp() *iris.Application {
|
||||
app := iris.New()
|
||||
|
||||
authConfig := basicauth.Config{
|
||||
@@ -40,6 +40,11 @@ func main() {
|
||||
needAuth.Get("/settings", h)
|
||||
}
|
||||
|
||||
return app
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := newApp()
|
||||
// open http://localhost:8080/admin
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
29
_examples/authentication/basicauth/main_test.go
Normal file
@@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/kataras/iris/httptest"
|
||||
)
|
||||
|
||||
func TestBasicAuth(t *testing.T) {
|
||||
app := newApp()
|
||||
e := httptest.New(t, app)
|
||||
|
||||
// redirects to /admin without basic auth
|
||||
e.GET("/").Expect().Status(httptest.StatusUnauthorized)
|
||||
// without basic auth
|
||||
e.GET("/admin").Expect().Status(httptest.StatusUnauthorized)
|
||||
|
||||
// with valid basic auth
|
||||
e.GET("/admin").WithBasicAuth("myusername", "mypassword").Expect().
|
||||
Status(httptest.StatusOK).Body().Equal("/admin myusername:mypassword")
|
||||
e.GET("/admin/profile").WithBasicAuth("myusername", "mypassword").Expect().
|
||||
Status(httptest.StatusOK).Body().Equal("/admin/profile myusername:mypassword")
|
||||
e.GET("/admin/settings").WithBasicAuth("myusername", "mypassword").Expect().
|
||||
Status(httptest.StatusOK).Body().Equal("/admin/settings myusername:mypassword")
|
||||
|
||||
// with invalid basic auth
|
||||
e.GET("/admin/settings").WithBasicAuth("invalidusername", "invalidpassword").
|
||||
Expect().Status(httptest.StatusUnauthorized)
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package main
|
||||
|
||||
// Any OAuth2 (even the pure golang/x/net/oauth2) package
|
||||
// can be used with Iris but at this example we will see the markbates' goth:
|
||||
// can be used with iris but at this example we will see the markbates' goth:
|
||||
//
|
||||
// $ go get github.com/markbates/goth/...
|
||||
//
|
||||
@@ -26,8 +26,8 @@ import (
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
|
||||
"github.com/kataras/iris/sessions"
|
||||
"github.com/kataras/iris/view"
|
||||
|
||||
"github.com/gorilla/securecookie" // optionally, used for session's encoder/decoder
|
||||
|
||||
@@ -70,6 +70,24 @@ import (
|
||||
"github.com/markbates/goth/providers/yammer"
|
||||
)
|
||||
|
||||
var sessionsManager *sessions.Sessions
|
||||
|
||||
func init() {
|
||||
// attach a session manager
|
||||
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)
|
||||
|
||||
sessionsManager = sessions.New(sessions.Config{
|
||||
Cookie: cookieName,
|
||||
Encode: secureCookie.Encode,
|
||||
Decode: secureCookie.Decode,
|
||||
})
|
||||
}
|
||||
|
||||
// These are some function helpers that you may use if you want
|
||||
|
||||
// GetProviderName is a function used to get the name of a provider
|
||||
@@ -97,7 +115,7 @@ var GetProviderName = func(ctx context.Context) (string, error) {
|
||||
}
|
||||
|
||||
/*
|
||||
BeginAuthHandler is a convienence handler for starting the authentication process.
|
||||
BeginAuthHandler is a convenience handler for starting the authentication process.
|
||||
It expects to be able to get the name of the provider from the query parameters
|
||||
as either "provider" or ":provider".
|
||||
|
||||
@@ -146,8 +164,8 @@ func GetAuthURL(ctx context.Context) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
ctx.Session().Set(providerName, sess.Marshal())
|
||||
session := sessionsManager.Start(ctx)
|
||||
session.Set(providerName, sess.Marshal())
|
||||
return url, nil
|
||||
}
|
||||
|
||||
@@ -191,8 +209,8 @@ var CompleteUserAuth = func(ctx context.Context) (goth.User, error) {
|
||||
if err != nil {
|
||||
return goth.User{}, err
|
||||
}
|
||||
|
||||
value := ctx.Session().GetString(providerName)
|
||||
session := sessionsManager.Start(ctx)
|
||||
value := session.GetString(providerName)
|
||||
if value == "" {
|
||||
return goth.User{}, errors.New("session value for " + providerName + " not found")
|
||||
}
|
||||
@@ -214,7 +232,7 @@ var CompleteUserAuth = func(ctx context.Context) (goth.User, error) {
|
||||
return goth.User{}, err
|
||||
}
|
||||
|
||||
ctx.Session().Set(providerName, sess.Marshal())
|
||||
session.Set(providerName, sess.Marshal())
|
||||
return provider.FetchUser(sess)
|
||||
}
|
||||
|
||||
@@ -224,8 +242,8 @@ func Logout(ctx context.Context) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx.Session().Delete(providerName)
|
||||
session := sessionsManager.Start(ctx)
|
||||
session.Delete(providerName)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -341,21 +359,7 @@ func main() {
|
||||
app := iris.New()
|
||||
|
||||
// attach and build our templates
|
||||
app.AttachView(view.HTML("./templates", ".html"))
|
||||
|
||||
// attach a session manager
|
||||
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)
|
||||
sessManager := sessions.New(sessions.Config{
|
||||
Cookie: cookieName,
|
||||
Encode: secureCookie.Encode,
|
||||
Decode: secureCookie.Decode,
|
||||
})
|
||||
app.AttachSessionManager(sessManager)
|
||||
app.RegisterView(iris.HTML("./templates", ".html"))
|
||||
|
||||
// start of the router
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
||||
"github.com/kataras/go-mailer"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
"github.com/kataras/iris/view"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
app := iris.New()
|
||||
app.AttachView(view.HTML("./templates", ".html"))
|
||||
|
||||
// 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 context.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("<b> Problem while sending the e-mail: " + err.Error())
|
||||
} else {
|
||||
ctx.HTML("<h1> SUCCESS </h1>")
|
||||
}
|
||||
})
|
||||
|
||||
// send a body by template
|
||||
app.Get("/send/template", func(ctx context.Context) {
|
||||
// we will not use ctx.View
|
||||
// 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.View parameter first.
|
||||
//
|
||||
// the rest of the parameters are the same and the behavior is the same as ctx.View,
|
||||
// except the 'where to render'
|
||||
buff := &bytes.Buffer{}
|
||||
|
||||
// View executes and writes the result of a template file to the writer.
|
||||
//
|
||||
// First parameter is the writer to write the parsed template.
|
||||
// Second parameter is the relative, to templates directory, template filename, including extension.
|
||||
// Third parameter is the layout, can be empty string.
|
||||
// Forth parameter is the bindable data to the template, can be nil.
|
||||
//
|
||||
// Use context.View to render templates to the client instead.
|
||||
// Returns an error on failure, otherwise nil.
|
||||
app.View(buff, "body.html", "", context.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.StatusCode(iris.StatusBadRequest)
|
||||
ctx.HTML("<b> Sent failed with error: " + err.Error())
|
||||
} else {
|
||||
ctx.HTML("<h1> SUCCESS </h1>")
|
||||
}
|
||||
})
|
||||
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
<h1>Hello From Iris web framework</h1>
|
||||
<br />
|
||||
<br />
|
||||
<span style="color: red"> {{.Message}}</span>
|
||||
<hr />
|
||||
|
||||
<b> {{.Footer}} </b>
|
||||
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 15 KiB |
@@ -1,14 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Handle("GET", "/", func(ctx context.Context) {
|
||||
ctx.HTML("<b> Hello world! </b>")
|
||||
})
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/core/nettools"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
l, err := nettools.UNIX("/tmpl/srv.sock", 0666) // see its code to see how you can manually create a new file listener, it's easy.
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
app.Run(iris.Listener(l))
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
)
|
||||
|
||||
// User bind struct
|
||||
type User struct {
|
||||
Firstname string `json:"firstname"`
|
||||
Lastname string `json:"lastname"`
|
||||
City string `json:"city"`
|
||||
Age int `json:"age"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
app.Post("/decode", func(ctx context.Context) {
|
||||
var user User
|
||||
ctx.ReadJSON(&user)
|
||||
|
||||
ctx.Writef("%s %s is %d years old and comes from %s!", user.Firstname, user.Lastname, user.Age, user.City)
|
||||
})
|
||||
|
||||
app.Get("/encode", func(ctx context.Context) {
|
||||
peter := User{
|
||||
Firstname: "John",
|
||||
Lastname: "Doe",
|
||||
City: "Neither FBI knows!!!",
|
||||
Age: 25,
|
||||
}
|
||||
|
||||
ctx.StatusCode(iris.StatusOK)
|
||||
ctx.JSON(peter)
|
||||
})
|
||||
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
@@ -2,16 +2,19 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.HTML("<b>Hello!</b>")
|
||||
})
|
||||
// [...]
|
||||
|
||||
// Good when you want to modify the whole configuration.
|
||||
app.Run(iris.Addr(":8080"), iris.WithConfiguration(iris.Configuration{ // default configuration:
|
||||
DisableBanner: false,
|
||||
DisableStartupLog: false,
|
||||
DisableInterruptHandler: false,
|
||||
DisablePathCorrection: false,
|
||||
EnablePathEscape: false,
|
||||
@@ -22,7 +25,6 @@ func main() {
|
||||
Charset: "UTF-8",
|
||||
}))
|
||||
|
||||
// or before run:
|
||||
// app.Configure(iris.WithConfiguration(...))
|
||||
// app.Run(iris.Addr(":8080"))
|
||||
// or before Run:
|
||||
// app.Configure(iris.WithConfiguration(iris.Configuration{...}))
|
||||
}
|
||||
@@ -6,4 +6,4 @@ TimeFormat = "Mon, 01 Jan 2006 15:04:05 GMT"
|
||||
Charset = "UTF-8"
|
||||
|
||||
[Other]
|
||||
MyServerName = "Iris"
|
||||
MyServerName = "iris"
|
||||
@@ -2,11 +2,15 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.HTML("<b>Hello!</b>")
|
||||
})
|
||||
// [...]
|
||||
|
||||
// Good when you have two configurations, one for development and a different one for production use.
|
||||
@@ -2,11 +2,14 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.HTML("<b>Hello!</b>")
|
||||
})
|
||||
// [...]
|
||||
|
||||
// Good when you have two configurations, one for development and a different one for production use.
|
||||
@@ -2,15 +2,20 @@ package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.HTML("<b>Hello!</b>")
|
||||
})
|
||||
// [...]
|
||||
|
||||
// Good when you want to change some of the configuration's field.
|
||||
// I use that method :)
|
||||
// Prefix: "With", code editors will help you navigate through all
|
||||
// configuration options without even a glitch to the documentation.
|
||||
|
||||
app.Run(iris.Addr(":8080"), iris.WithoutBanner, iris.WithCharset("UTF-8"))
|
||||
|
||||
// or before run:
|
||||
@@ -5,13 +5,12 @@ import (
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
"github.com/kataras/iris/core/handlerconv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
irisMiddleware := handlerconv.FromStdWithNext(negronilikeTestMiddleware)
|
||||
app.Use(irisMiddleware)
|
||||
ionMiddleware := iris.FromStd(negronilikeTestMiddleware)
|
||||
app.Use(ionMiddleware)
|
||||
|
||||
// Method GET: http://localhost:8080/
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
@@ -41,3 +40,6 @@ func negronilikeTestMiddleware(w http.ResponseWriter, r *http.Request, next http
|
||||
w.WriteHeader(iris.StatusBadRequest)
|
||||
w.Write([]byte("Bad request"))
|
||||
}
|
||||
|
||||
// Look "routing/custom-context" if you want to convert a custom handler with a custom Context
|
||||
// to a context.Handler.
|
||||
@@ -5,13 +5,12 @@ import (
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
"github.com/kataras/iris/core/handlerconv"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
irisMiddleware := handlerconv.FromStd(nativeTestMiddleware)
|
||||
app.Use(irisMiddleware)
|
||||
ionMiddleware := iris.FromStd(nativeTestMiddleware)
|
||||
app.Use(ionMiddleware)
|
||||
|
||||
// Method GET: http://localhost:8080/
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
@@ -31,3 +30,6 @@ func main() {
|
||||
func nativeTestMiddleware(w http.ResponseWriter, r *http.Request) {
|
||||
println("Request path: " + r.URL.Path)
|
||||
}
|
||||
|
||||
// Look "routing/custom-context" if you want to convert a custom handler with a custom Context
|
||||
// to a context.Handler.
|
||||
BIN
_examples/file-server/basic/assets/favicon.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
@@ -3,10 +3,10 @@ package main
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/httptest"
|
||||
)
|
||||
|
||||
@@ -33,7 +33,11 @@ func (r resource) loadFromBase(dir string) string {
|
||||
panic(fullpath + " failed with error: " + err.Error())
|
||||
}
|
||||
|
||||
return string(b)
|
||||
result := string(b)
|
||||
if runtime.GOOS != "windows" {
|
||||
result = strings.Replace(result, "\n", "\r\n", -1)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
var urls = []resource{
|
||||
@@ -49,12 +53,18 @@ func TestEmbeddingFilesIntoApp(t *testing.T) {
|
||||
app := newApp()
|
||||
e := httptest.New(t, app)
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
// remove the embedded static favicon for !windows,
|
||||
// it should be built for unix-specific in order to be work
|
||||
urls = urls[0 : len(urls)-1]
|
||||
}
|
||||
|
||||
for _, u := range urls {
|
||||
url := u.String()
|
||||
contents := u.loadFromBase("./assets")
|
||||
|
||||
e.GET(url).Expect().
|
||||
Status(iris.StatusOK).
|
||||
Status(httptest.StatusOK).
|
||||
Body().Equal(contents)
|
||||
}
|
||||
}
|
||||
@@ -8,17 +8,17 @@ import (
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
// This will serve the ./static/favicons/iris_favicon_48_48.ico to: localhost:8080/favicon.ico
|
||||
app.Favicon("./static/favicons/iris_favicon_48_48.ico")
|
||||
// This will serve the ./static/favicons/favicon.ico to: localhost:8080/favicon.ico
|
||||
app.Favicon("./static/favicons/favicon.ico.ico")
|
||||
|
||||
// app.Favicon("./static/favicons/iris_favicon_48_48.ico", "/favicon_48_48.ico")
|
||||
// This will serve the ./static/favicons/iris_favicon_48_48.ico to: localhost:8080/favicon_48_48.ico
|
||||
// app.Favicon("./static/favicons/favicon.ico.ico", "/favicon_16_16.ico")
|
||||
// This will serve the ./static/favicons/favicon.ico.ico to: localhost:8080/favicon_16_16.ico
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.HTML(`<a href="/favicon.ico"> press here to see the favicon.ico</a>.
|
||||
At some browsers like chrome, it should be visible at the top-left side of the browser's window,
|
||||
because some browsers make requests to the /favicon.ico automatically,
|
||||
so Iris serves your favicon in that path too (you can change it).`)
|
||||
so iris serves your favicon in that path too (you can change it).`)
|
||||
}) // if favicon doesn't show to you, try to clear your browser's cache.
|
||||
|
||||
app.Run(iris.Addr(":8080"))
|
||||
BIN
_examples/file-server/favicon/static/favicons/favicon.ico
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
@@ -6,7 +6,7 @@ import (
|
||||
"github.com/kataras/iris/view"
|
||||
)
|
||||
|
||||
// same as embedding-single-page-application but without go-bindata, the files are "physical" stored in the
|
||||
// same as embedded-single-page-application but without go-bindata, the files are "physical" stored in the
|
||||
// current system directory.
|
||||
|
||||
var page = struct {
|
||||
@@ -15,7 +15,7 @@ var page = struct {
|
||||
|
||||
func newApp() *iris.Application {
|
||||
app := iris.New()
|
||||
app.AttachView(view.HTML("./public", ".html"))
|
||||
app.RegisterView(view.HTML("./public", ".html"))
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.ViewData("Page", page)
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/httptest"
|
||||
)
|
||||
|
||||
@@ -35,7 +34,8 @@ func (r resource) loadFromBase(dir string) string {
|
||||
panic(fullpath + " failed with error: " + err.Error())
|
||||
}
|
||||
|
||||
return string(b)
|
||||
result := string(b)
|
||||
return result
|
||||
}
|
||||
|
||||
var urls = []resource{
|
||||
@@ -47,7 +47,7 @@ var urls = []resource{
|
||||
|
||||
func TestSPA(t *testing.T) {
|
||||
app := newApp()
|
||||
e := httptest.New(t, app)
|
||||
e := httptest.New(t, app, httptest.Debug(true))
|
||||
|
||||
for _, u := range urls {
|
||||
url := u.String()
|
||||
@@ -55,7 +55,7 @@ func TestSPA(t *testing.T) {
|
||||
contents = strings.Replace(contents, "{{ .Page.Title }}", page.Title, 1)
|
||||
|
||||
e.GET(url).Expect().
|
||||
Status(iris.StatusOK).
|
||||
Status(httptest.StatusOK).
|
||||
Body().Equal(contents)
|
||||
}
|
||||
}
|
||||
@@ -182,9 +182,9 @@ func AssetNames() []string {
|
||||
|
||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||
var _bindata = map[string]func() (*asset, error){
|
||||
"public/app.js": publicAppJs,
|
||||
"public/app.js": publicAppJs,
|
||||
"public/css/main.css": publicCssMainCss,
|
||||
"public/index.html": publicIndexHtml,
|
||||
"public/index.html": publicIndexHtml,
|
||||
}
|
||||
|
||||
// AssetDir returns the file names below a certain
|
||||
@@ -226,13 +226,14 @@ type bintree struct {
|
||||
Func func() (*asset, error)
|
||||
Children map[string]*bintree
|
||||
}
|
||||
|
||||
var _bintree = &bintree{nil, map[string]*bintree{
|
||||
"public": &bintree{nil, map[string]*bintree{
|
||||
"app.js": &bintree{publicAppJs, map[string]*bintree{}},
|
||||
"css": &bintree{nil, map[string]*bintree{
|
||||
"main.css": &bintree{publicCssMainCss, map[string]*bintree{}},
|
||||
"public": {nil, map[string]*bintree{
|
||||
"app.js": {publicAppJs, map[string]*bintree{}},
|
||||
"css": {nil, map[string]*bintree{
|
||||
"main.css": {publicCssMainCss, map[string]*bintree{}},
|
||||
}},
|
||||
"index.html": &bintree{publicIndexHtml, map[string]*bintree{}},
|
||||
"index.html": {publicIndexHtml, map[string]*bintree{}},
|
||||
}},
|
||||
}}
|
||||
|
||||
@@ -282,4 +283,3 @@ func _filePath(dir, name string) string {
|
||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
// $ go get -u github.com/jteeuwen/go-bindata/...
|
||||
// $ go-bindata ./public/...
|
||||
// $ go build
|
||||
// $ ./embedding-single-page-application
|
||||
// $ ./embedded-single-page-application
|
||||
|
||||
var page = struct {
|
||||
Title string
|
||||
@@ -17,7 +17,7 @@ var page = struct {
|
||||
|
||||
func newApp() *iris.Application {
|
||||
app := iris.New()
|
||||
app.AttachView(view.HTML("./public", ".html").Binary(Asset, AssetNames))
|
||||
app.RegisterView(view.HTML("./public", ".html").Binary(Asset, AssetNames))
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.ViewData("Page", page)
|
||||
@@ -3,10 +3,10 @@ package main
|
||||
import (
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/httptest"
|
||||
)
|
||||
|
||||
@@ -34,8 +34,11 @@ func (r resource) loadFromBase(dir string) string {
|
||||
if err != nil {
|
||||
panic(fullpath + " failed with error: " + err.Error())
|
||||
}
|
||||
|
||||
return string(b)
|
||||
result := string(b)
|
||||
if runtime.GOOS != "windows" {
|
||||
result = strings.Replace(result, "\n", "\r\n", -1)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
var urls = []resource{
|
||||
@@ -55,7 +58,7 @@ func TestSPAEmbedded(t *testing.T) {
|
||||
contents = strings.Replace(contents, "{{ .Page.Title }}", page.Title, 1)
|
||||
|
||||
e.GET(url).Expect().
|
||||
Status(iris.StatusOK).
|
||||
Status(httptest.StatusOK).
|
||||
Body().Equal(contents)
|
||||
}
|
||||
}
|
||||
36
_examples/hello-world/main.go
Normal file
@@ -0,0 +1,36 @@
|
||||
// +build go.1.8
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.Default()
|
||||
|
||||
// Method: GET
|
||||
// Resource: http://localhost:8080/
|
||||
app.Handle("GET", "/", func(ctx context.Context) {
|
||||
ctx.HTML("<b>Hello world!</b>")
|
||||
})
|
||||
|
||||
// same as app.Handle("GET", "/ping", [...])
|
||||
// Method: GET
|
||||
// Resource: http://context:8080/ping
|
||||
app.Get("/ping", func(ctx iris.Context) {
|
||||
ctx.WriteString("pong")
|
||||
})
|
||||
|
||||
// Method: GET
|
||||
// Resource: http://localhost:8080/hello
|
||||
app.Get("/hello", func(ctx context.Context) {
|
||||
ctx.JSON(iris.Map{"message": "Hello iris web framework."})
|
||||
})
|
||||
|
||||
// http://localhost:8080
|
||||
// http://localhost:8080/ping
|
||||
// http://localhost:8080/hello
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
35
_examples/hello-world/main_go19.go
Normal file
@@ -0,0 +1,35 @@
|
||||
// +build go1.9
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.Default()
|
||||
|
||||
// Method: GET
|
||||
// Resource: http://localhost:8080/
|
||||
app.Handle("GET", "/", func(ctx iris.Context) {
|
||||
ctx.HTML("<b>Hello world!</b>")
|
||||
})
|
||||
|
||||
// same as app.Handle("GET", "/ping", [...])
|
||||
// Method: GET
|
||||
// Resource: http://localhost:8080/ping
|
||||
app.Get("/ping", func(ctx iris.Context) {
|
||||
ctx.WriteString("pong")
|
||||
})
|
||||
|
||||
// Method: GET
|
||||
// Resource: http://localhost:8080/hello
|
||||
app.Get("/hello", func(ctx iris.Context) {
|
||||
ctx.JSON(iris.Map{"message": "Hello iris web framework."})
|
||||
})
|
||||
|
||||
// http://localhost:8080
|
||||
// http://localhost:8080/ping
|
||||
// http://localhost:8080/hello
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
@@ -18,7 +18,9 @@ func main() {
|
||||
ctx.Writef("Hello from %s", ctx.Path())
|
||||
})
|
||||
|
||||
srv := &http.Server{Addr: ":8080" /* Any custom fields here: Handler and ErrorLog are setted to the server automatically */}
|
||||
// Any custom fields here. Handler and ErrorLog are setted to the server automatically
|
||||
srv := &http.Server{Addr: ":8080"}
|
||||
|
||||
// http://localhost:8080/
|
||||
// http://localhost:8080/mypath
|
||||
app.Run(iris.Server(srv)) // same as app.Run(iris.Addr(":8080"))
|
||||
@@ -18,10 +18,8 @@ func main() {
|
||||
ctx.Writef("Hello from %s", ctx.Path())
|
||||
})
|
||||
|
||||
// call .Build before use the 'app' as an http.Handler on a custom http.Server
|
||||
if err := app.Build(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// call .Build before use the 'app' as a http.Handler on a custom http.Server
|
||||
app.Build()
|
||||
|
||||
// create our custom server and assign the Handler/Router
|
||||
srv := &http.Server{Handler: app, Addr: ":8080"} // you have to set Handler:app and Addr, see "iris-way" which does this automatically.
|
||||
@@ -0,0 +1,45 @@
|
||||
// +build linux darwin dragonfly freebsd netbsd openbsd rumprun
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
// Package tcplisten provides customizable TCP net.Listener with various
|
||||
// performance-related options:
|
||||
//
|
||||
// - SO_REUSEPORT. This option allows linear scaling server performance
|
||||
// on multi-CPU servers.
|
||||
// See https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/ for details.
|
||||
//
|
||||
// - TCP_DEFER_ACCEPT. This option expects the server reads from the accepted
|
||||
// connection before writing to them.
|
||||
//
|
||||
// - TCP_FASTOPEN. See https://lwn.net/Articles/508865/ for details.
|
||||
"github.com/valyala/tcplisten"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
)
|
||||
|
||||
// $ go get github.com/valyala/tcplisten
|
||||
// $ go run main.go
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.HTML("<b>Hello World!</b>")
|
||||
})
|
||||
|
||||
listenerCfg := tcplisten.Config{
|
||||
ReusePort: true,
|
||||
DeferAccept: true,
|
||||
FastOpen: true,
|
||||
}
|
||||
|
||||
l, err := listenerCfg.NewListener("tcp", ":8080")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
app.Run(iris.Listener(l))
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
// +build windows
|
||||
|
||||
package main
|
||||
|
||||
func main() {
|
||||
panic("windows operating system does not support this feature")
|
||||
}
|
||||
@@ -13,10 +13,9 @@ import (
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
// output startup banner and error logs on os.Stdout
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.HTML(" <h1>hi, I just exist in order to see if the server is closed</h1>")
|
||||
ctx.HTML("<h1>hi, I just exist in order to see if the server is closed</h1>")
|
||||
})
|
||||
|
||||
go func() {
|
||||
@@ -33,16 +32,16 @@ func main() {
|
||||
)
|
||||
select {
|
||||
case <-ch:
|
||||
println("Shutdown the server gracefully...")
|
||||
println("shutdown...")
|
||||
|
||||
timeout := 5 * time.Second // give the server 5 seconds to wait for idle connections.
|
||||
timeout := 5 * time.Second
|
||||
ctx, cancel := stdContext.WithTimeout(stdContext.Background(), timeout)
|
||||
defer cancel()
|
||||
app.Shutdown(ctx)
|
||||
}
|
||||
}()
|
||||
|
||||
// Start the server and disable the default interrupt handler in order to handle it clear and simple by our own, without
|
||||
// any issues.
|
||||
// Start the server and disable the default interrupt handler in order to
|
||||
// handle it clear and simple by our own, without any issues.
|
||||
app.Run(iris.Addr(":8080"), iris.WithoutInterruptHandler)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
stdContext "context"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
)
|
||||
|
||||
// Before continue:
|
||||
//
|
||||
// Gracefully Shutdown on control+C/command+C or when kill command sent is ENABLED BY-DEFAULT.
|
||||
//
|
||||
// In order to manually manage what to do when app is interrupted,
|
||||
// We have to disable the default behavior with the option `WithoutInterruptHandler`
|
||||
// and register a new interrupt handler (globally, across all possible hosts).
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
iris.RegisterOnInterrupt(func() {
|
||||
timeout := 5 * time.Second
|
||||
ctx, cancel := stdContext.WithTimeout(stdContext.Background(), timeout)
|
||||
defer cancel()
|
||||
// close all hosts
|
||||
app.Shutdown(ctx)
|
||||
})
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.HTML(" <h1>hi, I just exist in order to see if the server is closed</h1>")
|
||||
})
|
||||
|
||||
// http://localhost:8080
|
||||
app.Run(iris.Addr(":8080"), iris.WithoutInterruptHandler)
|
||||
}
|
||||
@@ -9,7 +9,7 @@ func main() {
|
||||
app := iris.New()
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.HTML("<h1>Index /</h1>")
|
||||
ctx.HTML("<h1>Hello World!/</h1>")
|
||||
})
|
||||
|
||||
if err := app.Run(iris.Addr(":8080")); err != nil {
|
||||
@@ -22,7 +22,7 @@ func main() {
|
||||
})
|
||||
|
||||
// If http to https auto-redirect is one of your needs
|
||||
// please look the code inside iris_deprecateed.go.ListenLETSENCRYPT to do it manually.
|
||||
// please look the code inside ion_deprecateed.go.ListenLETSENCRYPT to do it manually.
|
||||
|
||||
// NOTE: This may not work on local addresses like this,
|
||||
// use it on a real domain, because
|
||||
19
_examples/http-listening/listen-unix/main.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/core/netutil"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
l, err := netutil.UNIX("/tmpl/srv.sock", 0666) // see its code to see how you can manually create a new file listener, it's easy.
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
app.Run(iris.Listener(l))
|
||||
}
|
||||
|
||||
// Look "custom-listener/unix-reuseport" too.
|
||||
1
_examples/http_request/README.md
Normal file
@@ -0,0 +1 @@
|
||||
The `context.Request()` returns the same *http.Request you already know, the examples show some places where the Context uses this object. Besides that you can use it as you did before iris.
|
||||
@@ -17,7 +17,7 @@ func main() {
|
||||
app := iris.New()
|
||||
|
||||
// set the view html template engine
|
||||
app.AttachView(view.HTML("./templates", ".html").Reload(true))
|
||||
app.RegisterView(view.HTML("./templates", ".html").Reload(true))
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
if err := ctx.View("form.html"); err != nil {
|
||||
@@ -31,7 +31,7 @@ func main() {
|
||||
// to the http://localhost:8080 with RAW BODY:
|
||||
/*
|
||||
{
|
||||
"Name": "Iris-Go",
|
||||
"Name": "iris-Go",
|
||||
"City": "New York",
|
||||
"Other": "Something here"
|
||||
}
|
||||
@@ -39,6 +39,6 @@ func main() {
|
||||
// and Content-Type to application/json
|
||||
//
|
||||
// The response should be:
|
||||
// Received: &main.Company{Name:"Iris-Go", City:"New York", Other:"Something here"}
|
||||
// Received: &main.Company{Name:"iris-Go", City:"New York", Other:"Something here"}
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
@@ -16,7 +16,7 @@ import (
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
app.AttachView(view.HTML("./templates", ".html"))
|
||||
app.RegisterView(view.HTML("./templates", ".html"))
|
||||
|
||||
// Serve the form.html to the user
|
||||
app.Get("/upload", func(ctx context.Context) {
|
||||
1
_examples/http_responsewriter/README.md
Normal file
@@ -0,0 +1 @@
|
||||
The `context.ResponseWriter()` returns an enchament version of a http.ResponseWriter, the examples show some places where the Context uses this object. Besides that you can use it as you did before iris.
|
||||
@@ -32,7 +32,7 @@ func main() {
|
||||
|
||||
// OPTIONAl STEP:
|
||||
// but useful if we want to post back an error message to the client if the transaction failed.
|
||||
// if the reason is empty then the transaction completed succesfuly,
|
||||
// if the reason is empty then the transaction completed successfully,
|
||||
// otherwise we rollback the whole response writer's body,
|
||||
// headers and cookies, status code and everything lives inside this transaction
|
||||
t.Complete(err)
|
||||
@@ -5,9 +5,16 @@ import (
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
"github.com/kataras/iris/view"
|
||||
)
|
||||
|
||||
// User bind struct
|
||||
type User struct {
|
||||
Firstname string `json:"firstname"`
|
||||
Lastname string `json:"lastname"`
|
||||
City string `json:"city"`
|
||||
Age int `json:"age"`
|
||||
}
|
||||
|
||||
// ExampleXML just a test struct to view represents xml content-type
|
||||
type ExampleXML struct {
|
||||
XMLName xml.Name `xml:"example"`
|
||||
@@ -18,8 +25,32 @@ type ExampleXML struct {
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
// Just some general restful render types, none of these has to do anything with templates.
|
||||
app.Get("/binary", func(ctx context.Context) { // useful when you want force-download of contents of raw bytes form.
|
||||
// Read
|
||||
app.Post("/decode", func(ctx context.Context) {
|
||||
var user User
|
||||
ctx.ReadJSON(&user)
|
||||
|
||||
ctx.Writef("%s %s is %d years old and comes from %s!", user.Firstname, user.Lastname, user.Age, user.City)
|
||||
})
|
||||
|
||||
// Write
|
||||
app.Get("/encode", func(ctx context.Context) {
|
||||
peter := User{
|
||||
Firstname: "John",
|
||||
Lastname: "Doe",
|
||||
City: "Neither FBI knows!!!",
|
||||
Age: 25,
|
||||
}
|
||||
|
||||
ctx.StatusCode(iris.StatusOK)
|
||||
// Manually setting a content type: ctx.ContentType("application/javascript")
|
||||
ctx.JSON(peter)
|
||||
})
|
||||
|
||||
// Other content types,
|
||||
|
||||
app.Get("/binary", func(ctx context.Context) {
|
||||
// useful when you want force-download of contents of raw bytes form.
|
||||
ctx.Binary([]byte("Some binary data here."))
|
||||
})
|
||||
|
||||
@@ -40,38 +71,17 @@ func main() {
|
||||
})
|
||||
|
||||
app.Get("/markdown", func(ctx context.Context) {
|
||||
ctx.Markdown([]byte("# Hello Dynamic Markdown -- Iris"))
|
||||
ctx.Markdown([]byte("# Hello Dynamic Markdown -- iris"))
|
||||
})
|
||||
|
||||
// http://localhost:8080/decode
|
||||
// http://localhost:8080/encode
|
||||
//
|
||||
|
||||
// - standard html | view.HTML(...)
|
||||
// - django | view.Django(...)
|
||||
// - pug(jade) | view.Pug(...)
|
||||
// - handlebars | view.Handlebars(...)
|
||||
// - amber | view.Amber(...)
|
||||
// with default template funcs:
|
||||
//
|
||||
// - {{ urlpath "mynamedroute" "pathParameter_ifneeded" }}
|
||||
// - {{ render "header.html" }}
|
||||
// - {{ render_r "header.html" }} // partial relative path to current page
|
||||
// - {{ yield }}
|
||||
// - {{ current }}
|
||||
app.AttachView(view.HTML("./templates", ".html"))
|
||||
app.Get("/template", func(ctx context.Context) {
|
||||
|
||||
ctx.ViewData("Name", "Iris") // the .Name inside the ./templates/hi.html
|
||||
ctx.Gzip(true) // enable gzip for big files
|
||||
ctx.View("hi.html") // render the template with the file name relative to the './templates'
|
||||
|
||||
})
|
||||
|
||||
// http://localhost:8080/binary
|
||||
// http://localhost:8080/text
|
||||
// http://localhost:8080/json
|
||||
// http://localhost:8080/jsonp
|
||||
// http://localhost:8080/xml
|
||||
// http://localhost:8080/markdown
|
||||
// http://localhost:8080/template
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
)
|
||||
|
||||
var markdownContents = []byte(`## 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.
|
||||
|
||||
* **Routine 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) `)
|
||||
|
||||
// Cache should not be used on handlers that contain dynamic data.
|
||||
// Cache is a good and a must-feature on static content, i.e "about page" or for a whole blog site.
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
app.Get("/", iris.Cache(10*time.Second), writeMarkdown)
|
||||
// saves its content on the first request and serves it instead of re-calculating the content.
|
||||
// After 10 seconds it will be cleared and resetted.
|
||||
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
|
||||
func writeMarkdown(ctx context.Context) {
|
||||
// tap multiple times the browser's refresh button and you will
|
||||
// see this println only once every 10 seconds.
|
||||
println("Handler executed. Content refreshed.")
|
||||
|
||||
ctx.Markdown(markdownContents)
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
|
||||
"github.com/kataras/iris/typescript" // optionally
|
||||
"github.com/kataras/iris/typescript/editor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.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/"
|
||||
ts.Attach(app) // attach the typescript compiler adaptor
|
||||
|
||||
editorConfig := editor.Config{
|
||||
Hostname: "localhost",
|
||||
Port: 4444,
|
||||
WorkingDir: "./www/scripts/", // "/path/to/the/client/side/directory/",
|
||||
Username: "myusername",
|
||||
Password: "mypassword",
|
||||
}
|
||||
e := editor.New(editorConfig)
|
||||
e.Attach(app) // attach the editor
|
||||
|
||||
app.StaticWeb("/", "./www") // serve the index.html
|
||||
|
||||
app.Run(iris.Addr(":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 (
|
||||
stdContext "context"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
"github.com/kataras/iris/core/host"
|
||||
)
|
||||
|
||||
// Before continue, please read the below notes:
|
||||
//
|
||||
// Current version of Iris is auto-graceful on control+C/command+C
|
||||
// or kill command sent or whenever app.Shutdown called.
|
||||
//
|
||||
// In order to add a custom interrupt handler(ctrl+c/cmd+c) or
|
||||
// shutdown manually you have to "schedule a host supervisor's task" or
|
||||
// use the core/host package manually or use a pure http.Server as we already seen at "custom-server" example.
|
||||
//
|
||||
// At this example, we will disable the interrupt handler and set our own interrupt handler.
|
||||
func main() {
|
||||
app := iris.New()
|
||||
// output startup banner and error logs on os.Stdout
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.HTML(" <h1>hi, I just exist in order to see if the server is closed</h1>")
|
||||
})
|
||||
|
||||
// tasks are always running in their go-routine by-default.
|
||||
//
|
||||
// register custom interrupt handler, fires when ctrl+C/cmd+C pressed or kill command sent.
|
||||
app.Scheduler.Schedule(host.OnInterrupt(func(proc host.TaskProcess) {
|
||||
println("Shutdown the server gracefully...")
|
||||
|
||||
timeout := 5 * time.Second // give the server 5 seconds to wait for idle connections.
|
||||
ctx, cancel := stdContext.WithTimeout(stdContext.Background(), timeout)
|
||||
defer cancel()
|
||||
proc.Host().Shutdown(ctx) // Shutdown the underline supervisor's server
|
||||
}))
|
||||
|
||||
// Start the server and disable the default interrupt handler in order to use our scheduled interrupt task.
|
||||
app.Run(iris.Addr(":8080"), iris.WithoutInterruptHandler)
|
||||
}
|
||||
|
||||
// Note:
|
||||
// You can just use an http.Handler with your own signal notify channel and do that as you did with the net/http
|
||||
// package. I will not show this way, but you can find many examples on the internet.
|
||||
@@ -1,72 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
stdContext "context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
"github.com/kataras/iris/core/host"
|
||||
)
|
||||
|
||||
// The difference from its parent main.go is that
|
||||
// with a custom host we're able to call the host's shutdown
|
||||
// and be notified about its .Shutdown call.
|
||||
// Almost the same as before.
|
||||
func main() {
|
||||
app := iris.New()
|
||||
// output startup banner and error logs on os.Stdout
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.HTML(" <h1>hi, I just exist in order to see if the server is closed</h1>")
|
||||
})
|
||||
|
||||
// build the framework when all routing-relative actions are declared.
|
||||
if err := app.Build(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// create our custom host supervisor by adapting
|
||||
// a custom http server
|
||||
srv := host.New(&http.Server{Addr: ":8080", Handler: app})
|
||||
|
||||
// tasks are always running in their go-routine by-default.
|
||||
//
|
||||
// register custom interrupt handler, fires when ctrl+C/cmd+C pressed or kill command sent, as we did before.
|
||||
srv.Schedule(host.OnInterrupt(func(proc host.TaskProcess) {
|
||||
println("Shutdown the server gracefully...")
|
||||
|
||||
timeout := 5 * time.Second // give the server 5 seconds to wait for idle connections.
|
||||
ctx, cancel := stdContext.WithTimeout(stdContext.Background(), timeout)
|
||||
defer cancel()
|
||||
proc.Host().DeferFlow() // defer the exit, in order to catch the event
|
||||
srv.Shutdown(ctx) // Shutdown the supervisor, only this way the proc.Host().Done will be notified
|
||||
// the proc.Host().Shutdown, closes the underline server but no the supervisor.
|
||||
// This behavior was choosen because is inneed for custom maintanance services
|
||||
// (i.e restart server every week without loosing connections) which you can easly adapt with Iris.
|
||||
}))
|
||||
|
||||
// schedule a task to be notify when the server was closed by our interrutp handler,
|
||||
// optionally ofcourse.
|
||||
srv.ScheduleFunc(func(proc host.TaskProcess) {
|
||||
select {
|
||||
case <-proc.Host().Done(): // when .Host.Shutdown(ctx) called.
|
||||
println("Server was closed.")
|
||||
proc.Host().RestoreFlow() // Restore the flow in order to exit(continue after the srv.ListenAndServe)
|
||||
}
|
||||
})
|
||||
|
||||
// Start our custom host
|
||||
println("Server is running at :8080")
|
||||
srv.ListenAndServe()
|
||||
// Go to the console and press ctrl+c(for windows and linux) or cmd+c for osx.
|
||||
// The output should be:
|
||||
// Server is running at:8080
|
||||
// Shutdown the server gracefully...
|
||||
// Server was closed.
|
||||
}
|
||||
|
||||
// Note:
|
||||
// You can just use an http.Handler with your own signal notify channel and do that as you did with the net/http
|
||||
// package. I will not show this way, but you can find many examples on the internet.
|
||||
@@ -1 +0,0 @@
|
||||
hi = Γεια, %s
|
||||
@@ -1,71 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
|
||||
"github.com/kataras/iris/sessions"
|
||||
"github.com/kataras/iris/sessions/sessiondb/redis"
|
||||
"github.com/kataras/iris/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()
|
||||
// Attach the session manager we just created
|
||||
app.AttachSessionManager(mySessions)
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead")
|
||||
})
|
||||
app.Get("/set", func(ctx context.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 context.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 context.Context) {
|
||||
// delete a specific key
|
||||
ctx.Session().Delete("name")
|
||||
})
|
||||
|
||||
app.Get("/clear", func(ctx context.Context) {
|
||||
// removes all entries
|
||||
ctx.Session().Clear()
|
||||
})
|
||||
|
||||
app.Get("/destroy", func(ctx context.Context) {
|
||||
//destroy, removes the entire session data and cookie
|
||||
ctx.SessionDestroy()
|
||||
})
|
||||
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
"github.com/kataras/iris/sessions"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
// output startup banner and error logs on os.Stdout
|
||||
|
||||
sess := sessions.New(sessions.Config{Cookie: "myappsessionid"})
|
||||
app.AttachSessionManager(sess)
|
||||
|
||||
app.Get("/set", func(ctx context.Context) {
|
||||
ctx.Session().SetFlash("name", "iris")
|
||||
ctx.Writef("Message setted, is available for the next request")
|
||||
})
|
||||
|
||||
app.Get("/get", func(ctx context.Context) {
|
||||
name := ctx.Session().GetFlashString("name")
|
||||
if name == "" {
|
||||
ctx.Writef("Empty name!!")
|
||||
return
|
||||
}
|
||||
ctx.Writef("Hello %s", name)
|
||||
})
|
||||
|
||||
app.Get("/test", func(ctx context.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.Run(iris.Addr(":8080"))
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
|
||||
"github.com/kataras/iris/sessions"
|
||||
)
|
||||
|
||||
var (
|
||||
key = "my_sessionid"
|
||||
)
|
||||
|
||||
func secret(ctx context.Context) {
|
||||
|
||||
// Check if user is authenticated
|
||||
if auth, _ := ctx.Session().GetBoolean("authenticated"); !auth {
|
||||
ctx.StatusCode(iris.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
// Print secret message
|
||||
ctx.WriteString("The cake is a lie!")
|
||||
}
|
||||
|
||||
func login(ctx context.Context) {
|
||||
session := ctx.Session()
|
||||
|
||||
// Authentication goes here
|
||||
// ...
|
||||
|
||||
// Set user as authenticated
|
||||
session.Set("authenticated", true)
|
||||
}
|
||||
|
||||
func logout(ctx context.Context) {
|
||||
session := ctx.Session()
|
||||
|
||||
// Revoke users authentication
|
||||
session.Set("authenticated", false)
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
// Look https://github.com/kataras/iris/tree/master/sessions/_examples for more features,
|
||||
// i.e encode/decode and lifetime.
|
||||
sess := sessions.New(sessions.Config{Cookie: key})
|
||||
app.AttachSessionManager(sess)
|
||||
|
||||
app.Get("/secret", secret)
|
||||
app.Get("/login", login)
|
||||
app.Get("/logout", logout)
|
||||
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
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)
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
package main
|
||||
|
||||
// developers can use any library to add a custom cookie encoder/decoder.
|
||||
// At this example we use the gorilla's securecookie package:
|
||||
// $ go get github.com/gorilla/securecookie
|
||||
// $ go run main.go
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
"github.com/kataras/iris/sessions"
|
||||
|
||||
"github.com/gorilla/securecookie"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
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,
|
||||
})
|
||||
|
||||
// OPTIONALLY:
|
||||
// import "github.com/kataras/iris/sessions/sessiondb/redis"
|
||||
// or import "github.com/kataras/go-sessions/sessiondb/$any_available_community_database"
|
||||
// mySessions.UseDatabase(redis.New(...))
|
||||
|
||||
app.AttachSessionManager(mySessions) // Attach the session manager we just created.
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead")
|
||||
})
|
||||
app.Get("/set", func(ctx context.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 context.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 context.Context) {
|
||||
// delete a specific key
|
||||
ctx.Session().Delete("name")
|
||||
})
|
||||
|
||||
app.Get("/clear", func(ctx context.Context) {
|
||||
// removes all entries
|
||||
ctx.Session().Clear()
|
||||
})
|
||||
|
||||
app.Get("/destroy", func(ctx context.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.Run(iris.Addr(":8080"))
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
"github.com/kataras/iris/sessions"
|
||||
)
|
||||
|
||||
type businessModel struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
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,
|
||||
// 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.
|
||||
})
|
||||
|
||||
app.AttachSessionManager(mySessions) // Attach the session manager we just created.
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.Writef("You should navigate to the /set, /get, /delete, /clear,/destroy instead")
|
||||
})
|
||||
app.Get("/set", func(ctx context.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"))
|
||||
|
||||
// Set will set the value as-it-is,
|
||||
// if it's a slice or map
|
||||
// you will be able to change it on .Get directly!
|
||||
// Keep note that I don't recommend saving big data neither slices or maps on a session
|
||||
// but if you really need it then use the `SetImmutable` instead of `Set`.
|
||||
// Use `SetImmutable` consistently, it's slower.
|
||||
// Read more about muttable and immutable go types: https://stackoverflow.com/a/8021081
|
||||
})
|
||||
|
||||
app.Get("/get", func(ctx context.Context) {
|
||||
// get a specific value, 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 context.Context) {
|
||||
// delete a specific key
|
||||
ctx.Session().Delete("name")
|
||||
})
|
||||
|
||||
app.Get("/clear", func(ctx context.Context) {
|
||||
// removes all entries
|
||||
ctx.Session().Clear()
|
||||
})
|
||||
|
||||
app.Get("/destroy", func(ctx context.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
|
||||
|
||||
// remember: slices and maps are muttable by-design
|
||||
// The `SetImmutable` makes sure that they will be stored and received
|
||||
// as immutable, so you can't change them directly by mistake.
|
||||
//
|
||||
// Use `SetImmutable` consistently, it's slower than `Set`.
|
||||
// Read more about muttable and immutable go types: https://stackoverflow.com/a/8021081
|
||||
app.Get("/set_immutable", func(ctx context.Context) {
|
||||
business := []businessModel{{Name: "Edward"}, {Name: "value 2"}}
|
||||
ctx.Session().SetImmutable("businessEdit", business)
|
||||
businessGet := ctx.Session().Get("businessEdit").([]businessModel)
|
||||
|
||||
// try to change it, if we used `Set` instead of `SetImmutable` this
|
||||
// change will affect the underline array of the session's value "businessEdit", but now it will not.
|
||||
businessGet[0].Name = "Gabriel"
|
||||
|
||||
})
|
||||
|
||||
app.Get("/get_immutable", func(ctx context.Context) {
|
||||
valSlice := ctx.Session().Get("businessEdit")
|
||||
if valSlice == nil {
|
||||
ctx.HTML("please navigate to the <a href='/set_immutable'>/set_immutable</a> first")
|
||||
return
|
||||
}
|
||||
|
||||
firstModel := valSlice.([]businessModel)[0]
|
||||
// businessGet[0].Name is equal to Edward initially
|
||||
if firstModel.Name != "Edward" {
|
||||
panic("Report this as a bug, immutable data cannot be changed from the caller without re-SetImmutable")
|
||||
}
|
||||
|
||||
ctx.Writef("[]businessModel[0].Name remains: %s", firstModel.Name)
|
||||
|
||||
// the name should remains "Edward"
|
||||
})
|
||||
|
||||
app.Run(iris.Addr(":8080"))
|
||||
}
|
||||
|
Before Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 7.2 KiB |
@@ -1,33 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/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()
|
||||
|
||||
ts := typescript.New()
|
||||
ts.Config.Dir = "./www/scripts"
|
||||
ts.Attach(app) // attach the application to the typescript compiler
|
||||
|
||||
app.StaticWeb("/", "./www") // serve the index.html
|
||||
app.Run(iris.Addr(":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,114 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
|
||||
"github.com/kataras/iris/view"
|
||||
"github.com/kataras/iris/websocket"
|
||||
)
|
||||
|
||||
type clientPage struct {
|
||||
Title string
|
||||
Host string
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.AttachView(view.HTML("./templates", ".html")) // select the html engine to serve templates
|
||||
|
||||
ws := websocket.New(websocket.Config{
|
||||
// the request path which the websocket client should listen/registered to the server,
|
||||
// the endpoint is like a route.
|
||||
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 context.Context) string {},
|
||||
})
|
||||
|
||||
ws.Attach(app) // adapt the application to the websocket server
|
||||
|
||||
app.StaticWeb("/js", "./static/js") // serve our custom javascript code
|
||||
|
||||
app.Get("/", func(ctx context.Context) {
|
||||
ctx.ViewData("", clientPage{"Client Page", "localhost:8080"})
|
||||
ctx.View("client.html")
|
||||
})
|
||||
|
||||
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.Run(iris.Addr(":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,175 +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 issue.
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
xwebsocket "golang.org/x/net/websocket"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/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:8080/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()
|
||||
|
||||
ws := websocket.New(websocket.Config{Endpoint: "/socket"})
|
||||
ws.Attach(app)
|
||||
|
||||
ws.OnConnection(OnConnect)
|
||||
app.Run(iris.Addr(":8080"))
|
||||
|
||||
}
|
||||
|
||||
// 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,63 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/context"
|
||||
|
||||
"github.com/kataras/iris/view"
|
||||
"github.com/kataras/iris/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.AttachView(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,
|
||||
})
|
||||
|
||||
ws.Attach(app) // 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 context.Context) {
|
||||
ctx.ViewData("", clientPage{"Client Page", "localhost:8080"})
|
||||
ctx.View("client.html")
|
||||
})
|
||||
|
||||
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.Run(iris.Addr(":8080"))
|
||||
|
||||
}
|
||||