mirror of
https://github.com/kataras/iris.git
synced 2026-01-11 05:55:57 +00:00
Add some _examples in the main repository too.
Former-commit-id: 98895c34115ec2076b431332f0ffe9645adf7590
This commit is contained in:
33
_examples/README.md
Normal file
33
_examples/README.md
Normal file
@@ -0,0 +1,33 @@
|
||||
## 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.
|
||||
|
||||
|
||||
It doesn't contains "best ways" neither explains all its features. It's just a simple, practical cookbook for young Go developers!
|
||||
|
||||
Developers should read the official [documentation](https://godoc.org/gopkg.in/kataras/iris.v6) in depth.
|
||||
|
||||
|
||||
<a href ="https://github.com/kataras/iris"> <img src="http://iris-go.com/assets/book/cover_4.jpg" width="300" /> </a>
|
||||
|
||||
|
||||
## Table of Contents
|
||||
|
||||
* [Hello World](examples/hello-world/main.go)
|
||||
* [Routes (using httprouter)](examples/routes-using-httprouter/main.go)
|
||||
* [Routes (using gorillamux)](examples/routes-using-gorillamux/main.go)
|
||||
* [Templates](examples/templates/main.go)
|
||||
* [Forms](examples/forms/main.go)
|
||||
* [JSON](examples/json/main.go)
|
||||
* [Upload Files](examples/upload-files/main.go)
|
||||
* [Static Files](examples/static-files/main.go)
|
||||
* [Favicon](examples/favicon/main.go)
|
||||
* [Password Hashing](examples/password-hashing/main.go)
|
||||
* [Sessions](examples/sessions/main.go)
|
||||
* [Websockets](examples/websockets/main.go)
|
||||
* [Markdown and Cache](examples/cache-markdown/main.go)
|
||||
* [Online Visitors](examples/online-visitors/main.go)
|
||||
* [URL Shortener](examples/url-shortener/main.go)
|
||||
|
||||
|
||||
> Take look at the [community examples](https://github.com/iris-contrib/examples) too!
|
||||
82
_examples/examples/cache-markdown/main.go
Normal file
82
_examples/examples/cache-markdown/main.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
)
|
||||
|
||||
var testMarkdownContents = `## Hello Markdown
|
||||
|
||||
This is a sample of Markdown contents
|
||||
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
All features of Sundown are supported, including:
|
||||
|
||||
* **Compatibility**. The Markdown v1.0.3 test suite passes with
|
||||
the --tidy option. Without --tidy, the differences are
|
||||
mostly in whitespace and entity escaping, where blackfriday is
|
||||
more consistent and cleaner.
|
||||
|
||||
* **Common extensions**, including table support, fenced code
|
||||
blocks, autolinks, strikethroughs, non-strict emphasis, etc.
|
||||
|
||||
* **Safety**. Blackfriday is paranoid when parsing, making it safe
|
||||
to feed untrusted user input without fear of bad things
|
||||
happening. The test suite stress tests this and there are no
|
||||
known inputs that make it crash. If you find one, please let me
|
||||
know and send me the input that does it.
|
||||
|
||||
NOTE: "safety" in this context means *runtime safety only*. In order to
|
||||
protect yourself against JavaScript injection in untrusted content, see
|
||||
[this example](https://github.com/russross/blackfriday#sanitize-untrusted-content).
|
||||
|
||||
* **Fast processing**. It is fast enough to render on-demand in
|
||||
most web applications without having to cache the output.
|
||||
|
||||
* **Thread safety**. You can run multiple parsers in different
|
||||
goroutines without ill effect. There is no dependence on global
|
||||
shared state.
|
||||
|
||||
* **Minimal dependencies**. Blackfriday only depends on standard
|
||||
library packages in Go. The source code is pretty
|
||||
self-contained, so it is easy to add to any project, including
|
||||
Google App Engine projects.
|
||||
|
||||
* **Standards compliant**. Output successfully validates using the
|
||||
W3C validation tool for HTML 4.01 and XHTML 1.0 Transitional.
|
||||
|
||||
[this is a link](https://github.com/kataras/iris) `
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
// output startup banner and error logs on os.Stdout
|
||||
app.Adapt(iris.DevLogger())
|
||||
// set the router, you can choose gorillamux too
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
app.Get("/hi", app.Cache(func(c *iris.Context) {
|
||||
c.WriteString("Hi this is a big content, do not try cache on small content it will not make any significant difference!")
|
||||
}, time.Duration(10)*time.Second))
|
||||
|
||||
bodyHandler := func(ctx *iris.Context) {
|
||||
ctx.Markdown(iris.StatusOK, testMarkdownContents)
|
||||
}
|
||||
|
||||
expiration := time.Duration(5 * time.Second)
|
||||
|
||||
app.Get("/", app.Cache(bodyHandler, expiration))
|
||||
|
||||
// if expiration is <=time.Second then the cache tries to set the expiration from the "cache-control" maxage header's value(in seconds)
|
||||
// // if this header doesn't founds then the default is 5 minutes
|
||||
app.Get("/cache_control", app.Cache(func(ctx *iris.Context) {
|
||||
ctx.HTML(iris.StatusOK, "<h1>Hello!</h1>")
|
||||
}, -1))
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
23
_examples/examples/favicon/main.go
Normal file
23
_examples/examples/favicon/main.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(httprouter.New())
|
||||
// This will serve the ./static/favicons/iris_favicon_32_32.ico to: localhost:8080/favicon.ico
|
||||
app.Favicon("./static/favicons/iris_favicon_32_32.ico")
|
||||
|
||||
// app.Favicon("./static/favicons/iris_favicon_32_32.ico", "/favicon_32_32.ico")
|
||||
// This will serve the ./static/favicons/iris_favicon_32_32.ico to: localhost:8080/favicon_32_32.ico
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
ctx.HTML(iris.StatusOK, `You should see the favicon now at the side of your browser,
|
||||
if not, please refresh or clear the browser's cache.`)
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.2 KiB |
47
_examples/examples/forms/main.go
Normal file
47
_examples/examples/forms/main.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
)
|
||||
|
||||
// ContactDetails the information from user
|
||||
type ContactDetails struct {
|
||||
Email string `form:"email"`
|
||||
Subject string `form:"subject"`
|
||||
Message string `form:"message"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
// Parse all files inside `./mytemplates` directory ending with `.html`
|
||||
app.Adapt(view.HTML("./mytemplates", ".html"))
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
ctx.Render("forms.html", nil)
|
||||
})
|
||||
|
||||
// Equivalent with app.HandleFunc("POST", ...)
|
||||
app.Post("/", func(ctx *iris.Context) {
|
||||
|
||||
// details := ContactDetails{
|
||||
// Email: ctx.FormValue("email"),
|
||||
// Subject: ctx.FormValue("subject"),
|
||||
// Message: ctx.FormValue("message"),
|
||||
// }
|
||||
|
||||
// or simply:
|
||||
var details ContactDetails
|
||||
ctx.ReadForm(&details)
|
||||
|
||||
// do something with details
|
||||
_ = details
|
||||
|
||||
ctx.Render("forms.html", struct{ Success bool }{true})
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
14
_examples/examples/forms/mytemplates/forms.html
Normal file
14
_examples/examples/forms/mytemplates/forms.html
Normal file
@@ -0,0 +1,14 @@
|
||||
{{if .Success}}
|
||||
<h1>Thanks for your message!</h1>
|
||||
{{else}}
|
||||
<h1>Contact</h1>
|
||||
<form method="POST">
|
||||
<label>Email:</label><br />
|
||||
<input type="text" name="email"><br />
|
||||
<label>Subject:</label><br />
|
||||
<input type="text" name="subject"><br />
|
||||
<label>Message:</label><br />
|
||||
<textarea name="message"></textarea><br />
|
||||
<input type="submit">
|
||||
</form>
|
||||
{{end}}
|
||||
20
_examples/examples/hello-world/main.go
Normal file
20
_examples/examples/hello-world/main.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
// Adapt the "httprouter", faster,
|
||||
// but it has limits on named path parameters' validation,
|
||||
// you can adapt "gorillamux" if you need regexp path validation!
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
app.HandleFunc("GET", "/", func(ctx *iris.Context) {
|
||||
ctx.Writef("hello world\n")
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
37
_examples/examples/json/main.go
Normal file
37
_examples/examples/json/main.go
Normal file
@@ -0,0 +1,37 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
)
|
||||
|
||||
// User bind struct
|
||||
type User struct {
|
||||
Firstname string `json:"firstname"`
|
||||
Lastname string `json:"lastname"`
|
||||
Age int `json:"age"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
app.Post("/decode", func(ctx *iris.Context) {
|
||||
var user User
|
||||
ctx.ReadJSON(&user)
|
||||
|
||||
ctx.Writef("%s %s is %d years old!", user.Firstname, user.Lastname, user.Age)
|
||||
})
|
||||
|
||||
app.Get("/encode", func(ctx *iris.Context) {
|
||||
peter := User{
|
||||
Firstname: "John",
|
||||
Lastname: "Doe",
|
||||
Age: 25,
|
||||
}
|
||||
|
||||
ctx.JSON(iris.StatusOK, peter)
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
170
_examples/examples/online-visitors/main.go
Normal file
170
_examples/examples/online-visitors/main.go
Normal file
@@ -0,0 +1,170 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"sync/atomic"
|
||||
|
||||
"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"
|
||||
)
|
||||
|
||||
var (
|
||||
app *iris.Framework
|
||||
ws websocket.Server
|
||||
)
|
||||
|
||||
func init() {
|
||||
// init the server instance
|
||||
app = iris.New()
|
||||
// adapt a logger in dev mode
|
||||
app.Adapt(iris.DevLogger())
|
||||
// adapt router
|
||||
app.Adapt(httprouter.New())
|
||||
// adapt templaes
|
||||
app.Adapt(view.HTML("./templates", ".html").Reload(true))
|
||||
// adapt websocket
|
||||
ws = websocket.New(websocket.Config{Endpoint: "/my_endpoint"})
|
||||
ws.OnConnection(HandleWebsocketConnection)
|
||||
app.Adapt(ws)
|
||||
}
|
||||
|
||||
type page struct {
|
||||
PageID string
|
||||
}
|
||||
|
||||
func main() {
|
||||
app.StaticWeb("/js", "./static/assets/js")
|
||||
|
||||
h := func(ctx *iris.Context) {
|
||||
ctx.Render("index.html", page{PageID: "index page"})
|
||||
}
|
||||
|
||||
h2 := func(ctx *iris.Context) {
|
||||
ctx.Render("other.html", page{PageID: "other page"})
|
||||
}
|
||||
|
||||
// Open some browser tabs/or windows
|
||||
// and navigate to
|
||||
// http://localhost:8080/ and http://localhost:8080/other
|
||||
// Each page has its own online-visitors counter.
|
||||
app.Get("/", h)
|
||||
app.Get("/other", h2)
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
type pageView struct {
|
||||
source string
|
||||
count uint64
|
||||
}
|
||||
|
||||
func (v *pageView) increment() {
|
||||
atomic.AddUint64(&v.count, 1)
|
||||
}
|
||||
|
||||
func (v *pageView) decrement() {
|
||||
oldCount := v.count
|
||||
if oldCount > 0 {
|
||||
atomic.StoreUint64(&v.count, oldCount-1)
|
||||
}
|
||||
}
|
||||
|
||||
func (v *pageView) getCount() uint64 {
|
||||
val := atomic.LoadUint64(&v.count)
|
||||
return val
|
||||
}
|
||||
|
||||
type (
|
||||
pageViews []pageView
|
||||
)
|
||||
|
||||
func (v *pageViews) Add(source string) {
|
||||
args := *v
|
||||
n := len(args)
|
||||
for i := 0; i < n; i++ {
|
||||
kv := &args[i]
|
||||
if kv.source == source {
|
||||
kv.increment()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
c := cap(args)
|
||||
if c > n {
|
||||
args = args[:n+1]
|
||||
kv := &args[n]
|
||||
kv.source = source
|
||||
kv.count = 1
|
||||
*v = args
|
||||
return
|
||||
}
|
||||
|
||||
kv := pageView{}
|
||||
kv.source = source
|
||||
kv.count = 1
|
||||
*v = append(args, kv)
|
||||
}
|
||||
|
||||
func (v *pageViews) Get(source string) *pageView {
|
||||
args := *v
|
||||
n := len(args)
|
||||
for i := 0; i < n; i++ {
|
||||
kv := &args[i]
|
||||
if kv.source == source {
|
||||
return kv
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *pageViews) Reset() {
|
||||
*v = (*v)[:0]
|
||||
}
|
||||
|
||||
var v pageViews
|
||||
|
||||
// HandleWebsocketConnection handles the online viewers per example(gist source)
|
||||
func HandleWebsocketConnection(c websocket.Connection) {
|
||||
|
||||
c.On("watch", func(pageSource string) {
|
||||
v.Add(pageSource)
|
||||
// join the socket to a room linked with the page source
|
||||
c.Join(pageSource)
|
||||
|
||||
viewsCount := v.Get(pageSource).getCount()
|
||||
if viewsCount == 0 {
|
||||
viewsCount++ // count should be always > 0 here
|
||||
}
|
||||
c.To(pageSource).Emit("watch", viewsCount)
|
||||
})
|
||||
|
||||
c.OnLeave(func(roomName string) {
|
||||
if roomName != c.ID() { // if the roomName it's not the connection iself
|
||||
// the roomName here is the source, this is the only room(except the connection's ID room) which we join the users to.
|
||||
pageV := v.Get(roomName)
|
||||
if pageV == nil {
|
||||
return // for any case that this room is not a pageView source
|
||||
}
|
||||
// decrement -1 the specific counter for this page source.
|
||||
pageV.decrement()
|
||||
// 1. open 30 tabs.
|
||||
// 2. close the browser.
|
||||
// 3. re-open the browser
|
||||
// 4. should be v.getCount() = 1
|
||||
// in order to achieve the previous flow we should decrement exactly when the user disconnects
|
||||
// but emit the result a little after, on a goroutine
|
||||
// getting all connections within this room and emit the online views one by one.
|
||||
// note:
|
||||
// we can also add a time.Sleep(2-3 seconds) inside the goroutine at the future if we don't need 'real-time' updates.
|
||||
go func(currentConnID string) {
|
||||
for _, conn := range ws.GetConnectionsByRoom(roomName) {
|
||||
if conn.ID() != currentConnID {
|
||||
conn.Emit("watch", pageV.getCount())
|
||||
}
|
||||
|
||||
}
|
||||
}(c.ID())
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
(function() {
|
||||
var socket = new Ws("ws://localhost:8080/my_endpoint");
|
||||
|
||||
socket.OnConnect(function () {
|
||||
socket.Emit("watch", PAGE_SOURCE);
|
||||
});
|
||||
|
||||
|
||||
socket.On("watch", function (onlineViews) {
|
||||
var text = "1 online view";
|
||||
if (onlineViews > 1) {
|
||||
text = onlineViews + " online views";
|
||||
}
|
||||
document.getElementById("online_views").innerHTML = text;
|
||||
});
|
||||
|
||||
socket.OnDisconnect(function () {
|
||||
document.getElementById("online_views").innerHTML = "you've been disconnected";
|
||||
});
|
||||
|
||||
})();
|
||||
43
_examples/examples/online-visitors/templates/index.html
Normal file
43
_examples/examples/online-visitors/templates/index.html
Normal file
@@ -0,0 +1,43 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Online visitors example</title>
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, "San Francisco", "Helvetica Neue", "Noto", "Roboto", "Calibri Light", sans-serif;
|
||||
color: #212121;
|
||||
font-size: 1.0em;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 750px;
|
||||
margin: auto;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
#online_views {
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<span id="online_views">1 online view</span>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
/* take the page source from our passed struct on .Render */
|
||||
var PAGE_SOURCE = {{ .PageID }}
|
||||
</script>
|
||||
|
||||
<script src="/iris-ws.js"></script>
|
||||
|
||||
<script src="/js/visitors.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
29
_examples/examples/online-visitors/templates/other.html
Normal file
29
_examples/examples/online-visitors/templates/other.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Different page, different results</title>
|
||||
<style>
|
||||
#online_views {
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<span id="online_views">1 online view</span>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
/* take the page source from our passed struct on .Render */
|
||||
var PAGE_SOURCE = {{ .PageID }}
|
||||
</script>
|
||||
|
||||
<script src="/iris-ws.js"></script>
|
||||
|
||||
<script src="/js/visitors.js"></script>
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
28
_examples/examples/password-hashing/main.go
Normal file
28
_examples/examples/password-hashing/main.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
||||
func HashPassword(password string) (string, error) {
|
||||
bytes, err := bcrypt.GenerateFromPassword([]byte(password), 14)
|
||||
return string(bytes), err
|
||||
}
|
||||
|
||||
func CheckPasswordHash(password, hash string) bool {
|
||||
err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
password := "secret"
|
||||
hash, _ := HashPassword(password) // ignore error for the sake of simplicity
|
||||
|
||||
fmt.Println("Password:", password)
|
||||
fmt.Println("Hash: ", hash)
|
||||
|
||||
match := CheckPasswordHash(password, hash)
|
||||
fmt.Println("Match: ", match)
|
||||
}
|
||||
28
_examples/examples/routes-using-gorillamux/main.go
Normal file
28
_examples/examples/routes-using-gorillamux/main.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/gorillamux"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
// Adapt the "httprouter", you can use "gorillamux" too.
|
||||
app.Adapt(gorillamux.New())
|
||||
|
||||
userAges := map[string]int{
|
||||
"Alice": 25,
|
||||
"Bob": 30,
|
||||
"Claire": 29,
|
||||
}
|
||||
|
||||
// Equivalent with app.HandleFunc("GET", ...)
|
||||
app.Get("/users/{name}", func(ctx *iris.Context) {
|
||||
name := ctx.Param("name")
|
||||
age := userAges[name]
|
||||
|
||||
ctx.Writef("%s is %d years old!", name, age)
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
27
_examples/examples/routes-using-httprouter/main.go
Normal file
27
_examples/examples/routes-using-httprouter/main.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
userAges := map[string]int{
|
||||
"Alice": 25,
|
||||
"Bob": 30,
|
||||
"Claire": 29,
|
||||
}
|
||||
|
||||
// Equivalent with app.HandleFunc("GET", ...)
|
||||
app.Get("/users/:name", func(ctx *iris.Context) {
|
||||
name := ctx.Param("name")
|
||||
age := userAges[name]
|
||||
|
||||
ctx.Writef("%s is %d years old!", name, age)
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
54
_examples/examples/sessions/main.go
Normal file
54
_examples/examples/sessions/main.go
Normal file
@@ -0,0 +1,54 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/sessions"
|
||||
)
|
||||
|
||||
var (
|
||||
key = "my_sessionid"
|
||||
)
|
||||
|
||||
func secret(ctx *iris.Context) {
|
||||
|
||||
// Check if user is authenticated
|
||||
if auth, _ := ctx.Session().GetBoolean("authenticated"); !auth {
|
||||
ctx.EmitError(iris.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
||||
// Print secret message
|
||||
ctx.WriteString("The cake is a lie!")
|
||||
}
|
||||
|
||||
func login(ctx *iris.Context) {
|
||||
session := ctx.Session()
|
||||
|
||||
// Authentication goes here
|
||||
// ...
|
||||
|
||||
// Set user as authenticated
|
||||
session.Set("authenticated", true)
|
||||
}
|
||||
|
||||
func logout(ctx *iris.Context) {
|
||||
session := ctx.Session()
|
||||
|
||||
// Revoke users authentication
|
||||
session.Set("authenticated", false)
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
sess := sessions.New(sessions.Config{Cookie: key})
|
||||
app.Adapt(sess)
|
||||
|
||||
app.Get("/secret", secret)
|
||||
app.Get("/login", login)
|
||||
app.Get("/logout", logout)
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
3
_examples/examples/static-files/assets/css/styles.css
Normal file
3
_examples/examples/static-files/assets/css/styles.css
Normal file
@@ -0,0 +1,3 @@
|
||||
body {
|
||||
background-color: black;
|
||||
}
|
||||
16
_examples/examples/static-files/main.go
Normal file
16
_examples/examples/static-files/main.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(httprouter.New())
|
||||
// first parameter is the request path
|
||||
// second is the operating system directory
|
||||
app.StaticWeb("/static", "./assets")
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
39
_examples/examples/templates/main.go
Normal file
39
_examples/examples/templates/main.go
Normal file
@@ -0,0 +1,39 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
)
|
||||
|
||||
// Todo bind struct
|
||||
type Todo struct {
|
||||
Task string
|
||||
Done bool
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Configuration is optional
|
||||
app := iris.New(iris.Configuration{Gzip: false, Charset: "UTF-8"})
|
||||
|
||||
// Adapt a logger which will print all errors to os.Stdout
|
||||
app.Adapt(iris.DevLogger())
|
||||
|
||||
// Adapt the httprouter (we will use that on all examples)
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
// Parse all files inside `./mytemplates` directory ending with `.html`
|
||||
app.Adapt(view.HTML("./mytemplates", ".html"))
|
||||
|
||||
todos := []Todo{
|
||||
{"Learn Go", true},
|
||||
{"Read GopherBOOk", true},
|
||||
{"Create a web app in Go", false},
|
||||
}
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
ctx.Render("todos.html", struct{ Todos []Todo }{todos})
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
10
_examples/examples/templates/mytemplates/todos.html
Normal file
10
_examples/examples/templates/mytemplates/todos.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<h1>Todos</h1>
|
||||
<ul>
|
||||
{{range .Todos}}
|
||||
{{if .Done}}
|
||||
<li><s>{{.Task}}</s></li>
|
||||
{{else}}
|
||||
<li>{{.Task}}</li>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</ul>
|
||||
69
_examples/examples/upload-files/main.go
Normal file
69
_examples/examples/upload-files/main.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger())
|
||||
app.Adapt(httprouter.New())
|
||||
app.Adapt(view.HTML("./templates", ".html"))
|
||||
|
||||
// Serve the form.html to the user
|
||||
app.Get("/upload", func(ctx *iris.Context) {
|
||||
//create a token (optionally)
|
||||
|
||||
now := time.Now().Unix()
|
||||
h := md5.New()
|
||||
io.WriteString(h, strconv.FormatInt(now, 10))
|
||||
token := fmt.Sprintf("%x", h.Sum(nil))
|
||||
//render the form with the token for any use you like
|
||||
ctx.Render("upload_form.html", token)
|
||||
})
|
||||
|
||||
// Handle the post request from the upload_form.html to the server
|
||||
app.Post("/upload", iris.LimitRequestBodySize(10<<20),
|
||||
func(ctx *iris.Context) {
|
||||
// or use ctx.SetMaxRequestBodySize(10 << 20)
|
||||
//to limit the uploaded file(s) size.
|
||||
|
||||
// Get the file from the request
|
||||
file, info, err := ctx.FormFile("uploadfile")
|
||||
|
||||
if err != nil {
|
||||
ctx.HTML(iris.StatusInternalServerError,
|
||||
"Error while uploading: <b>"+err.Error()+"</b>")
|
||||
return
|
||||
}
|
||||
|
||||
defer file.Close()
|
||||
fname := info.Filename
|
||||
|
||||
// Create a file with the same name
|
||||
// assuming that you have a folder named 'uploads'
|
||||
out, err := os.OpenFile("./uploads/"+fname,
|
||||
os.O_WRONLY|os.O_CREATE, 0666)
|
||||
|
||||
if err != nil {
|
||||
ctx.HTML(iris.StatusInternalServerError,
|
||||
"Error while uploading: <b>"+err.Error()+"</b>")
|
||||
return
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
io.Copy(out, file)
|
||||
})
|
||||
|
||||
// start the server at 127.0.0.1:8080
|
||||
app.Listen(":8080")
|
||||
}
|
||||
12
_examples/examples/upload-files/templates/upload_form.html
Normal file
12
_examples/examples/upload-files/templates/upload_form.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>Upload file</title>
|
||||
</head>
|
||||
<body>
|
||||
<form enctype="multipart/form-data"
|
||||
action="http://127.0.0.1:8080/upload" method="post">
|
||||
<input type="file" name="uploadfile" /> <input type="hidden"
|
||||
name="token" value="{{.}}" /> <input type="submit" value="upload" />
|
||||
</form>
|
||||
</body>
|
||||
</html>
|
||||
132
_examples/examples/url-shortener/main.go
Normal file
132
_examples/examples/url-shortener/main.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"html/template"
|
||||
"math/rand"
|
||||
"net/url"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/view"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(
|
||||
iris.DevLogger(),
|
||||
httprouter.New(),
|
||||
view.HTML("./templates", ".html").Reload(true),
|
||||
)
|
||||
|
||||
// Serve static files (css)
|
||||
app.StaticWeb("/static", "./static_files")
|
||||
|
||||
var mu sync.Mutex
|
||||
var urls = map[string]string{
|
||||
"iris": "http://support.iris-go.com",
|
||||
}
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
ctx.Render("index.html", iris.Map{"url_count": len(urls)})
|
||||
})
|
||||
|
||||
// find and execute a short url by its key
|
||||
// used on http://localhost:8080/url/dsaoj41u321dsa
|
||||
execShortURL := func(ctx *iris.Context, key string) {
|
||||
if key == "" {
|
||||
ctx.EmitError(iris.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
value, found := urls[key]
|
||||
if !found {
|
||||
ctx.SetStatusCode(iris.StatusNotFound)
|
||||
ctx.Writef("Short URL for key: '%s' not found", key)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Redirect(value, iris.StatusTemporaryRedirect)
|
||||
}
|
||||
app.Get("/url/:shortkey", func(ctx *iris.Context) {
|
||||
execShortURL(ctx, ctx.Param("shortkey"))
|
||||
})
|
||||
|
||||
// for wildcard subdomain (yeah.. cool) http://dsaoj41u321dsa.localhost:8080
|
||||
// Note:
|
||||
// if you want subdomains (chrome doesn't works on localhost, so you have to define other hostname on app.Listen)
|
||||
// app.Party("*.", func(ctx *iris.Context) {
|
||||
// execShortURL(ctx, ctx.Subdomain())
|
||||
// })
|
||||
|
||||
app.Post("/url/shorten", func(ctx *iris.Context) {
|
||||
data := make(map[string]interface{}, 0)
|
||||
data["url_count"] = len(urls)
|
||||
value := ctx.FormValue("url")
|
||||
if value == "" {
|
||||
data["form_result"] = "You need to a enter a URL."
|
||||
} else {
|
||||
urlValue, err := url.ParseRequestURI(value)
|
||||
if err != nil {
|
||||
// ctx.JSON(iris.StatusInternalServerError,
|
||||
// iris.Map{"status": iris.StatusInternalServerError,
|
||||
// "error": err.Error(),
|
||||
// "reason": "Invalid URL",
|
||||
// })
|
||||
data["form_result"] = "Invalid URL."
|
||||
} else {
|
||||
key := randomString(12)
|
||||
// Make sure that the key is unique
|
||||
for {
|
||||
if _, exists := urls[key]; !exists {
|
||||
break
|
||||
}
|
||||
key = randomString(8)
|
||||
}
|
||||
mu.Lock()
|
||||
urls[key] = urlValue.String()
|
||||
mu.Unlock()
|
||||
ctx.SetStatusCode(iris.StatusOK)
|
||||
shortenURL := "http://" + app.Config.VHost + "/url/" + key
|
||||
data["form_result"] = template.HTML("<pre>Here is your short URL: <a href='" + shortenURL + "'>" + shortenURL + " </a></pre>")
|
||||
}
|
||||
|
||||
}
|
||||
ctx.Render("index.html", data)
|
||||
})
|
||||
|
||||
app.Listen("localhost:8080")
|
||||
}
|
||||
|
||||
// +------------------------------------------------------------+
|
||||
// | |
|
||||
// | Random String |
|
||||
// | |
|
||||
// +------------------------------------------------------------+
|
||||
|
||||
const (
|
||||
letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
letterIdxBits = 6 // 6 bits to represent a letter index
|
||||
letterIdxMask = 1<<letterIdxBits - 1 // All 1-bits, as many as letterIdxBits
|
||||
letterIdxMax = 63 / letterIdxBits // # of letter indices fitting in 63 bits
|
||||
)
|
||||
|
||||
func randomString(n int) string {
|
||||
src := rand.NewSource(time.Now().UnixNano())
|
||||
b := make([]byte, n)
|
||||
// A src.Int63() generates 63 random bits, enough for letterIdxMax characters!
|
||||
for i, cache, remain := n-1, src.Int63(), letterIdxMax; i >= 0; {
|
||||
if remain == 0 {
|
||||
cache, remain = src.Int63(), letterIdxMax
|
||||
}
|
||||
if idx := int(cache & letterIdxMask); idx < len(letterBytes) {
|
||||
b[i] = letterBytes[idx]
|
||||
i--
|
||||
}
|
||||
cache >>= letterIdxBits
|
||||
remain--
|
||||
}
|
||||
|
||||
return string(b)
|
||||
}
|
||||
3
_examples/examples/url-shortener/static_files/style.css
Normal file
3
_examples/examples/url-shortener/static_files/style.css
Normal file
@@ -0,0 +1,3 @@
|
||||
body{
|
||||
background-color:silver;
|
||||
}
|
||||
20
_examples/examples/url-shortener/templates/index.html
Normal file
20
_examples/examples/url-shortener/templates/index.html
Normal file
@@ -0,0 +1,20 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Golang URL Shortener</title>
|
||||
<link rel="stylesheet" href="/static/css/style.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>Golang URL Shortener</h2>
|
||||
<h3>{{ .form_result}}</h3>
|
||||
<form action="/url/shorten" method="POST">
|
||||
<input type="text" name="url" style="width: 35em;" />
|
||||
<input type="submit" value="Shorten!" />
|
||||
</form>
|
||||
|
||||
<p>{{ .url_count }} URLs shortened</p>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
48
_examples/examples/websockets/main.go
Normal file
48
_examples/examples/websockets/main.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gopkg.in/kataras/iris.v6"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/httprouter"
|
||||
"gopkg.in/kataras/iris.v6/adaptors/websocket"
|
||||
)
|
||||
|
||||
func handleConnection(c websocket.Connection) {
|
||||
|
||||
// Read events from browser
|
||||
c.On("chat", func(msg string) {
|
||||
|
||||
// Print the message to the console
|
||||
fmt.Printf("%s sent: %s\n", c.Context().RemoteAddr(), msg)
|
||||
|
||||
// Write message back to browser
|
||||
c.Emit("chat", msg)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.Adapt(iris.DevLogger())
|
||||
app.Adapt(httprouter.New())
|
||||
|
||||
// create our echo websocket server
|
||||
ws := websocket.New(websocket.Config{
|
||||
ReadBufferSize: 1024,
|
||||
WriteBufferSize: 1024,
|
||||
Endpoint: "/echo",
|
||||
})
|
||||
|
||||
ws.OnConnection(handleConnection)
|
||||
|
||||
// Adapt the websocket server.
|
||||
// you can adapt more than one of course.
|
||||
app.Adapt(ws)
|
||||
|
||||
app.Get("/", func(ctx *iris.Context) {
|
||||
ctx.ServeFile("websockets.html", false) // second parameter: enable gzip?
|
||||
})
|
||||
|
||||
app.Listen(":8080")
|
||||
}
|
||||
29
_examples/examples/websockets/websockets.html
Normal file
29
_examples/examples/websockets/websockets.html
Normal file
@@ -0,0 +1,29 @@
|
||||
<input id="input" type="text" />
|
||||
<button onclick="send()">Send</button>
|
||||
<pre id="output"></pre>
|
||||
<script src="/iris-ws.js"></script>
|
||||
<script>
|
||||
var input = document.getElementById("input");
|
||||
var output = document.getElementById("output");
|
||||
|
||||
// Ws comes from the auto-served '/iris-ws.js'
|
||||
var socket = new Ws("ws://localhost:8080/echo");
|
||||
socket.OnConnect(function () {
|
||||
output.innerHTML += "Status: Connected\n";
|
||||
});
|
||||
|
||||
socket.OnDisconnect(function () {
|
||||
output.innerHTML += "Status: Disconnected\n";
|
||||
});
|
||||
|
||||
// read events from the server
|
||||
socket.On("chat", function (msg) {
|
||||
output.innerHTML += "Server: " + msg + "\n";
|
||||
});
|
||||
|
||||
function send() {
|
||||
// send chat event data to the server
|
||||
socket.Emit("chat", input.value);
|
||||
input.value = "";
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user