zoukankan      html  css  js  c++  java
  • golang web实战之二(iris)

    之前写了一篇为:golang web实战之一(beego,mvc postgresql)

    听说iris更好:

    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("
    
     host: %s 
    
     path: %s 
    
     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.路由

    2.1用正则检查url路径是否符合要求

    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路径包含整数

    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. 静态文件服务器

    3.1.通过输入url访问静态目录下的静态文件

    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文件下载

    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/下面)

    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/

    https://blog.csdn.net/Wonderful_sky/article/details/84036366

    https://www.cnblogs.com/rabbix/p/10335126.html

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

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

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

    https://segmentfault.com/a/1190000011210869

    https://blog.csdn.net/stpeace/article/details/53512283

    https://segmentfault.com/a/1190000011118722

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

    https://blog.csdn.net/luckytanggu/article/details/83894932

    https://blog.csdn.net/light_jiang2016/article/details/86482902

    https://studygolang.com/articles/1741

    github

  • 相关阅读:
    nginx 安装配置
    mysql分表
    冲刺day7
    冲刺day6
    冲刺day5
    冲刺day4
    冲刺day3
    冲刺day2
    冲刺day1
    撰写《需求规格说明书》的工作流程、组员分工和组员工作量比例
  • 原文地址:https://www.cnblogs.com/pu369/p/10691747.html
Copyright © 2011-2022 走看看