golang web實戰之二(iris)

以前寫了一篇爲:golang web實戰之一(beego,mvc postgresql)css

據說iris更好:html

1.  iris hello world前端

package main

import "github.com/kataras/iris"

func main() {
    app := iris.New()
    app.Get("/", func(ctx iris.Context) {
        //ctx.HTML(`<p>hello world!</p>`)
        //ctx.Writef("\n\n host: %s \n\n path: %s \n\n request:%s ", ctx.Host(), ctx.Path(), ctx.Request())        
        //ctx.JSON(iris.Map{"message": "ping", "reply": "pong"})
        ctx.Text("hello world!")
    })
    app.Run(iris.Addr(":8080"))
}

2.路由git

2.1用正則檢查url路徑是否符合要求github

package main

import (
    "github.com/kataras/iris"
)

func main() {
    app := iris.New()
    //regexp來驗證路徑參數。分別匹配大寫、小寫字母。若包含數字等,則不會匹配
    //eg.  http://localhost:8080/ANYUPPERCASE/anylowercase
    app.Get("/{first:string regexp(^[A-Z]+)}/{second:string regexp(^[a-z]+)}", func(ctx iris.Context) {
        ctx.Writef("first should be only UPPERCASE:%s,second should be only lowercase:%s, otherwise this handler will never executed!", ctx.Params().Get("first"), ctx.Params().Get("second"))
    })
    app.Run(iris.Addr(":8080"))
}

2.2 url路徑包含整數golang

package main

import (
    "github.com/kataras/iris"
)

func main() {
    app := iris.New()
    //eg.  http://localhost:8080/123
    app.Get("/{page:int}", func(ctx iris.Context) {
        p, _ := ctx.Params().GetInt("page")
        ctx.Writef("page:%d", p)
    })
    app.Run(iris.Addr(":8080"))
}

 

3. 靜態文件服務器web

3.1.經過輸入url訪問靜態目錄下的靜態文件sql

package main

import (
    "github.com/kataras/iris"
)

func main() {
    app := iris.New()
    app.StaticWeb("/static", "./assets")
    // eg: http://localhost:8080/static/css/main.css
    app.Run(iris.Addr(":8080"))
    //路由不容許.StaticWeb("/","./ assets")
}

3.2文件下載json

package main

import (
    "github.com/kataras/iris"
)

func main() {
    app := iris.New()
    app.Get("/", func(ctx iris.Context) {
        file := "./main.go"
        ctx.SendFile(file, "main.go")
    })
    app.Run(iris.Addr(":8080"))
}

 

4.模板輸出(模板hello.html存放於view/main/下面)segmentfault

package main

import (
    "github.com/kataras/iris"
)

func main() {
    /*
       //views/main/hello.html的內容
           <html>
       <head>
           <title>{{ .Page.Title }}</title>
       </head>
       <body>
           <h1> Hello {{.Page.Name}}from index.html </h1>
           <script src="/app.js">  </script>
       </body>
       </html>
    */
    type page struct {
        Title, Name string
    }
    app := iris.New()
    app.RegisterView(iris.HTML("./views", ".html"))
    // 方法:    GET
    // 資源:  http://localhost:8080
    app.Get("/", func(ctx iris.Context) {
        //綁定數據
        ctx.ViewData("Page", page{Title: "Hi Page", Name: "iris"})
        // 渲染視圖文件: ./views/hello.html
        ctx.View("main/hello.html")
    })
    app.Run(iris.Addr(":8080"))
}

5.上傳文件

package main

import (
    "io"
    "os"

    "github.com/kataras/iris"
)

const maxSize = 5 << 20 // 5MB
var tpl = `
<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>
`

func main() {
    app := iris.New()
    app.Get("/upload", func(ctx iris.Context) {
        ctx.HTML(tpl)
    })
    //處理來自upload_form.html的請求數據處理
    //用iris.LimitRequestBodySize的好處是:在上傳過程當中,若檢測到文件大小超過限制,就會當即切斷與客戶端的鏈接。
    app.Post("/upload", iris.LimitRequestBodySize(maxSize+1<<20), func(ctx iris.Context) {
        // Get the file from the request.
        file, info, err := ctx.FormFile("uploadfile")
        if err != nil {
            ctx.StatusCode(iris.StatusInternalServerError)
            ctx.HTML("Error while uploading: <b>" + err.Error() + "</b>")
            return
        }
        defer file.Close()
        fname := info.Filename
        //建立一個具備相同名稱的文件
        //假設你有一個名爲'uploads'的文件夾
        out, err := os.OpenFile("./uploads/"+fname, os.O_WRONLY|os.O_CREATE, 0666)
        if err != nil {
            ctx.StatusCode(iris.StatusInternalServerError)
            ctx.HTML("Error while uploading: <b>" + err.Error() + "</b>")
            return
        }
        defer out.Close()
        io.Copy(out, file)
    })
    //在http//localhost:8080啓動服務器,上傳限制爲5MB。
    app.Run(iris.Addr(":8080") /* 0.*/, iris.WithPostMaxMemory(maxSize))
}

6.cookies

package main

import "github.com/kataras/iris"

func newApp() *iris.Application {
    app := iris.New()
    app.Get("/cookies/{name}/{value}", func(ctx iris.Context) {
        name := ctx.Params().Get("name")
        value := ctx.Params().Get("value")
        ctx.SetCookieKV(name, value)
        // 另外也能夠用: ctx.SetCookie(&http.Cookie{...})
        ctx.Request().Cookie(name)
        //若是您但願僅對當前請求路徑可見:
        //(請注意,若是服務器發送空cookie的路徑,全部瀏覽器都兼容,將會使用客戶端自定義路徑)
        // ctx.SetCookieKV(name, value, iris.CookieCleanPath /* or iris.CookiePath("") */)
        // 學習更多:
        //                              iris.CookieExpires(time.Duration)
        //                              iris.CookieHTTPOnly(false)
        ctx.Writef("cookie added: %s = %s", name, value)
    })
    app.Get("/cookies/{name}", func(ctx iris.Context) {
        name := ctx.Params().Get("name")
        value := ctx.GetCookie(name) // <-- 檢索,獲取Cookie
        //判斷命名cookie不存在,再獲取值
        // cookie, err := ctx.Request().Cookie(name)
        // if err != nil {
        //  handle error.
        // }
        ctx.WriteString(value)
    })
    app.Get("/cookiesd/{name}", func(ctx iris.Context) {
        name := ctx.Params().Get("name")
        ctx.RemoveCookie(name) // <-- 刪除Cookie
        //若是要設置自定義路徑:
        // ctx.SetCookieKV(name, value, iris.CookiePath("/custom/path/cookie/will/be/stored"))
        ctx.Writef("cookie %s removed", name)
    })
    return app
}

func main() {
    app := newApp()
    // GET:    http://localhost:8080/cookies/my_name/my_value
    // GET:    http://localhost:8080/cookies/my_name
    // DELETE: http://localhost:8080/cookiesd/my_name
    app.Run(iris.Addr(":8080"))
}

7.jwt

package main

import (
    "fmt"

    "time"

    "github.com/dgrijalva/jwt-go"
)

var (
    SIGN_NAME_SCERET = "aweQurt178BNI"
)

func main() {
    fmt.Println("Hello World!")

    tokenString, err := createJwt()
    if err != nil {
        fmt.Println(err.Error())
        return
    }

    fmt.Println(tokenString)

    claims := parseJwt(tokenString)
    fmt.Println(claims)

}

//驗證
//在調用Parse時,會進行加密驗證,同時若是提供了exp,會進行過時驗證;
//若是提供了iat,會進行發行時間驗證;若是提供了nbf,會進行發行時間驗證.

//建立 tokenString
func createJwt() (string, error) {
    //    token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{
    //        "foo": "bar",
    //        "nbf": time.Date(2015, 10, 10, 12, 0, 0, 0, time.UTC).Unix(),

    //    })

    token := jwt.New(jwt.SigningMethodHS256)
    claims := make(jwt.MapClaims)
    claims["foo"] = "bar"
    claims["exp"] = time.Now().Add(time.Hour * time.Duration(1)).Unix()
    claims["iat"] = time.Now().Unix()
    token.Claims = claims

    // Sign and get the complete encoded token as a string using the secret
    tokenString, err := token.SignedString([]byte(SIGN_NAME_SCERET))
    return tokenString, err
}

//解析tokenString
func parseJwt(tokenString string) jwt.MapClaims {
    token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
        // Don't forget to validate the alg is what you expect:
        if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
            return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
        }

        // hmacSampleSecret is a []byte containing your secret, e.g. []byte("my_secret_key")
        return []byte(SIGN_NAME_SCERET), nil
    })

    var claims jwt.MapClaims
    var ok bool

    if claims, ok = token.Claims.(jwt.MapClaims); ok && token.Valid {
        fmt.Println(claims["foo"], claims["nbf"])
    } else {
        fmt.Println(err)
    }

    return claims
}

關於JWT 這篇 https://blog.csdn.net/idwtwt/article/details/80865209 詳解的較清楚

很安全的方式就是把 XSRF Token 加入到 JWT ( JSON Web Token)中,而且把 JWT 存放在設置 httpOnly 的 cookie 中,而後單獨把 XSRF Token 設置在 httpOnly=false 的 cookie 中,前端請求時,須要獲取 XSRF Token 並放入請求頭(RequestHeader)。服務器端能夠直接驗證JWT中XSRF的值和XSRF的值便可。由於用了哈希密鑰簽名的技術,這樣就能夠防止篡改內容。

這樣的安全防禦就能抵禦全部的 XSRF 攻擊了。

另外, 儘可能不用GET而用POST  ,可過濾用戶輸入,填寫驗證碼等.....

個人理解是,jwt和session區別只是一個放在用戶client端、一個放在服務器server端。能夠相互代替()。

 

8.iris自定義結構體映射獲取Form表單請求數據

// package main包含一個關於如何使用ReadForm的示例,但使用相同的方法能夠執行ReadJSON和ReadJSON
/*
//templates/form.html
<!DOCTYPE html>
<head>
<meta charset="utf-8">
</head>
<body>
    <form action="/form_action" method="post">
        Username: <input type="text" name="Username" /> <br />
        Mail: <input type="text" name="Mail" /> <br />
        Select one or more:  <br/>
        <select multiple="multiple" name="mydata">
            <option value='one'>第一</option>
            <option value='two'>第二</option>
            <option value='three'>第三</option>
            <option value='four'>第四</option>
        </select>
        <hr />
        <input type="submit" value="Send data"/>
    </form>
</body>
</html>
*/
package main

import (
    "github.com/kataras/iris"
)

type Visitor struct {
    Username string
    Mail     string
    Data     []string `form:"mydata"`
}

func main() {
    app := iris.New()
    //設置視圖html模板引擎
    app.RegisterView(iris.HTML("./views", ".html").Reload(true))
    app.Get("/", func(ctx iris.Context) {
        if err := ctx.View("form.html"); err != nil {
            ctx.StatusCode(iris.StatusInternalServerError)
            ctx.WriteString(err.Error())
        }
    })
    app.Post("/form_action", func(ctx iris.Context) {
        visitor := Visitor{}
        err := ctx.ReadForm(&visitor)
        if err != nil {
            ctx.StatusCode(iris.StatusInternalServerError)
            ctx.WriteString(err.Error())
        }
        //%#v    相應值的 Go 語法表示;  %+v 會添加字段名 ;  %%    字面上的百分號,並不是值的佔位符
        ctx.Writef("Visitor: %#v", visitor)
    })
    app.Post("/post_value", func(ctx iris.Context) {
        username := ctx.PostValueDefault("Username", "iris")
        ctx.Writef("Username: %s", username)
    })
    app.Run(iris.Addr(":8080"))
}

 9.讀取配置文件

/*
//config.json
{
  "appname": "IrisDemo",
  "port": 8000
}
*/
package main

import (
    "encoding/json"
    "fmt"
    "os"

    "github.com/kataras/iris"
)

type Coniguration struct {
    Appname string `json:appname`
    Port    int64  `json:port`
}

func main() {
    app := iris.New()

    app.Get("/", func(ctx iris.Context) {
        file, _ := os.Open("config.json")
        defer file.Close()
        decoder := json.NewDecoder(file)
        conf := Coniguration{}
        err := decoder.Decode(&conf)
        if err != nil {
            fmt.Println("Error:", err)
        }
        fmt.Println(conf.Port)
        ctx.WriteString(conf.Appname)
    })

    app.Run(iris.Addr(":8080"))
}

 

 10.  golang iris web項目熱重啓

在開發web的時候,若是項目不支持熱重啓,每添加或修改個接口都須要重啓項目才能測試,會很麻煩。都知道beegobee工具,bee run啓動項目便可,而在iris項目中熱重啓方法以下

# 安裝rizla包
$ go get -u github.com/kataras/rizla
# 熱重啓方式啓動iris項目
$ rizla main.go

 

參考:https://www.studyiris.com/

http://www.javashuo.com/article/p-bmnvapps-ke.html

http://www.javashuo.com/article/p-xkmqxnbx-y.html

https://blog.csdn.net/tianwenxue/article/details/84998517

https://blog.csdn.net/idwtwt/article/details/80865209

https://www.jianshu.com/p/af8360b83a9f

http://www.javashuo.com/article/p-wnmnixmk-hz.html

http://www.javashuo.com/article/p-fohdfxmp-gz.html

http://www.javashuo.com/article/p-auklggsg-bm.html

https://blog.csdn.net/weixin_43420337/article/details/86151619

http://www.javashuo.com/article/p-cnftdfvx-nc.html

http://www.javashuo.com/article/p-epbwyhrn-kz.html

https://studygolang.com/articles/1741

github

相關文章
相關標籤/搜索