Kiểu Handler

Một Handler, như tên của nó để xử lý các yêu cầu.

Một Handler đáp ứng cho một yêu cầu HTTP. Nó ghi các tiêu đề trả lời và dữ liệu vào Context.ResponseWriter() sau đó trả về. Trả lại tín hiệu rằng yêu cầu đã kết thúc; Sẽ không hợp lệ để sử dụng Context sau hoặc đồng thời với việc hoàn thành lện gọi Handler.

Tùy thuộc vào phần mềm trên HTTP phía máy khách, phiên bản giao thức HTTP và bất kỳ trung gian nào giữa máy chủ Iris và máy khách, có thể không đọc được từ Context.Request().Body sau khi viết vào context.ResponseWriter(). Người xử lý thận trọng nên đọc Context.Request().Body trước sau đó trả lời.

Ngoại trừ việc đọc phần thân, trình xử lý không nên thay đổi Context được cung cấp.

Nếu Handler panics, máy chủ (gọi Handler) sẽ cho rằng hiệu ứng của panics đã bị cô lập với yêu cầu hoạt động. Nó phục hồi panics, ghi lại stack trace vào nhật ký lỗi máy chủ và treo kết nối.

type Handler func(iris.Context)

Khi trình xử lý được đăng ký, chúng ta có thể sử dụng Route được trả về để đặt tên cho đăng ký trình xử lý để gỡ lỗi dễ dàng hơn hoặc khớp các đường dẫn trong views. Đễ biết thêm thông tin hãy kiểm tra phần Reverse lookups.

 


 

Hành vi

Hành vi mặc định của Iris là chấp nhận và đăng ký các route với các đường dẫn như /api/user,  mà không có dấu gạch chéo. Nếu khách hàng cố gắng truy cập $your_host/api/user/, thì bộ định tuyến Iris sẽ tự động chuyển hướng này sang $your_host/api/user để được xử lý theo tuyến đã đăng ký. Đây là cách thiết kế API hiện đại.

Tuy nhiên nếu bạn muốn tắt hiệu chỉnh đường dẫn cho các tài nguyên được yêu cầu, bạn có thể chuyển tùy chọn iris.WithoutPathCorrection của cấu hình trong iris cho app.Run.  Ví dụ :

// [app := iris.New...]
// [...]

app.Run(iris.Addr(":8080"), iris.WithoutPathCorrection)

Nếu bạn muốn giữ cùng một trình xử lý và định tuyến cho các đường dẫn /api/user and /api/user/không chuyển hướng (kịch bản chung), chỉ sử dụng tùy chọn iris.WithoutPathCorrectionRedirection thay thế:

app.Run(iris.Addr(":8080"), iris.WithoutPathCorrectionRedirection)

 


 

API

Tất cả các phương thức HTTP đều được hỗ trợ, các nhà phát triển cũng có thể đăng ký trình xử lý trên cùng một đường dẫn với các phương thức khác nhau.

Tham số đầu tiên là phương thức HTTP, tham số thứ hai là đường dẫn của tuyến yêu cầu, tham số biến động thứ ba sẽ chứa một hoặc nhiều iris.Handler được thực hiện bởi lệnh đã đăng ký khi máy khách yêu cầu đường dẫn cụ thể từ máy chủ.

Ví dụ:

app := iris.New()

app.Handle("GET", "/contact", func(ctx iris.Context) {
    ctx.HTML("<h1> Hello from /contact </h1>")
})

Để làm cho mọi thứ dễ dàng hơn cho nhà phát triển cuối cùng, iris cung cấp các trình trợ giúp phương thức cho tất cả các phương thức HTTP. Tham số đầu tiên là đường dẫn yêu cầu của tuyến, tham số thứ hai (variadic parameter) sẽ chứa một hoặc nhiều iris.Handler được thực hiện theo lệnh đã đăng ký khi người dùng yêu cầu đường dẫn từ máy chủ.

Ví dụ:

app := iris.New()

// Method: "GET"
app.Get("/", handler)

// Method: "POST"
app.Post("/", handler)

// Method: "PUT"
app.Put("/", handler)

// Method: "DELETE"
app.Delete("/", handler)

// Method: "OPTIONS"
app.Options("/", handler)

// Method: "TRACE"
app.Trace("/", handler)

// Method: "CONNECT"
app.Connect("/", handler)

// Method: "HEAD"
app.Head("/", handler)

// Method: "PATCH"
app.Patch("/", handler)

// register the route for all HTTP Methods
app.Any("/", handler)

func handler(ctx iris.Context){
    ctx.Writef("Hello from method: %s and path: %s\n", ctx.Method(), ctx.Path())
}

Tuyến ngoại tuyến

Có một phương pháp đặc biệt trong Iris mà bạn cũng có thể sử dụng. Nó được gọi là None và bạn có thể sử dụng để ẩn tuyến từ bên ngoài nhưng có thể gọi nó từ trình xử lý của tuyến khác thông qua phương thức Context.Exec. Mỗi phương thức xử lý API trả về giá trị tuyến. Một định tuyến phương thức IsOnline báo cáo lại trạng thái hiện tại của tuyến đó. Bạn có thể thay đổi trạng thái của tuyến từ ngoại tuyến sang trực tuyến và ngược lại thông qua giá trị của trường Route.Method. Tất nhiên mỗi thay đổi của bộ định tuyến tại thời điểm yêu cầu một cuộc gọi app.RefreshRouter() an toàn để sử dụng. Hãy xem bên dưới một ví dụ đầy đủ hơn:

// file: main.go
package main

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

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

    none := app.None("/invisible/{username}", func(ctx iris.Context) {
        ctx.Writef("Hello %s with method: %s", ctx.Params().Get("username"), ctx.Method())

        if from := ctx.Values().GetString("from"); from != "" {
            ctx.Writef("\nI see that you're coming from %s", from)
        }
    })

    app.Get("/change", func(ctx iris.Context) {

        if none.IsOnline() {
            none.Method = iris.MethodNone
        } else {
            none.Method = iris.MethodGet
        }

        // refresh re-builds the router at serve-time in order to be notified for its new routes.
        app.RefreshRouter()
    })

    app.Get("/change", func(ctx iris.Context) {

        if none.IsOnline() {
            none.Method = iris.MethodNone
        } else {
            none.Method = iris.MethodGet
        }

        // refresh re-builds the router at serve-time in order to
        // be notified for its new routes.
        app.RefreshRouter()
    })

    app.Get("/execute", func(ctx iris.Context) {
        if !none.IsOnline() {
            ctx.Values().Set("from", "/execute with offline access")
            ctx.Exec("NONE", "/invisible/iris")
            return
        }

        // same as navigating to "http://localhost:8080/invisible/iris"
        // when /change has being invoked and route state changed
        // from "offline" to "online"
        ctx.Values().Set("from", "/execute")
        // values and session can be
        // shared when calling Exec from a "foreign" context.
        //     ctx.Exec("NONE", "/invisible/iris")
        // or after "/change":
        ctx.Exec("GET", "/invisible/iris")
    })

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

Cách chạy

  1. Chạy file main.go
  2. Mở trình duyệt với đường dẫn http://localhost:8080/invisible/iris và bạn sẽ thấy lỗi 404 not found
  3. Tuy nhiên http://localhost:8080/execute sẽ có thể thực thi tuyến đó.
  4. Bây giờ nếu bạn điều hướng đến http://localhost:8080/change và refresh tab /invisible/iris bạn sẽ thấy rằng bạn có thể thấy nó.

 


Nhóm tuyến

Một tập hợp các tuyến đang được nhóm theo tiền tố đường dẫn (tùy chọn) có thể chia sẻ cùng các trình xử lý phần mềm trung gian và bố cục mẫu. Một nhóm có thể chứa một nhóm lồng nhau.

.Party đang được sử dụng để nhóm các tuyến, các nhà phát triển có thể khai báo không giới hạn số lượng nhóm (lồng nhau).

Ví dụ:

app := iris.New()

users := app.Party("/users", myAuthMiddlewareHandler)

// http://localhost:8080/users/42/profile
users.Get("/{id:uint64}/profile", userProfileHandler)
// http://localhost:8080/users/messages/1
users.Get("/messages/{id:uint64}", userMessageHandler)

Điều tương tự cũng có thể được viết bằng phương thức PartyFunc chấp nhận bộ định tuyến con

app := iris.New()

app.PartyFunc("/users", func(users iris.Party) {
    users.Use(myAuthMiddlewareHandler)

    // http://localhost:8080/users/42/profile
    users.Get("/{id:uint64}/profile", userProfileHandler)
    // http://localhost:8080/users/messages/1
    users.Get("/messages/{id:uint64}", userMessageHandler)
})

 


 

Thông số đường dẫn

Không giống như các bộ định tuyến khác mà bạn đã thấy, Iris có thể xử lý các tuyến khác mà không xung đột giữa chúng.

Matches với GET "/".

app.Get("/", indexHandler)

Matches với tất cả các yêu cầu GET có tiền tố "/assets/**/*", đó là ký tự đại diện với ctx.Params().Get("asset") bằng với bất kỳ đường dẫn nào sau /assets/.

app.Get("/assets/{asset:path}", assetsWildcardHandler)

Matches với tất cả các yêu cầu GET có tiền tố "/profile/" và theo sau là một phần đường dẫn.

app.Get("/profile/{username:string}", userHandler)

Matches với GET "/profile/me" và nó không xung đột với /profile/{username:string} hoặc bất kỳ ký tự đại diện gốc /{root:path}.

app.Get("/profile/me", userHandler)

Matches với tất cả các yêu cầu GET có tiền tố là /users/ và theo sau là một số phải bằng hoặc hơn 1.

app.Get("/user/{userid:int min(1)}", getUserHandler)

Matches với tất cả các yêu cầu DELETE có tiền tố /users/ và theo sau bởi một số phải bằng hoặc hơn 1.

app.Delete("/user/{userid:int min(1)}", deleteUserHandler)

Matches với tất cả các yêu cầu GET ngoại trừ các yêu cầu đã được xử lý bởi các tuyến khác. Ví dụ trong trường hợp này bởi các tuyến trên ; /, /assets/{asset:path}, /profile/{username}, "/profile/me", /user/{userid:int ...}.  Nó không xung đột với phần còn lại của các tuyến(!).

app.Get("{root:path}", rootWildcardHandler)

Matches với tất cả các yêu cầu GET của:

  1. /u/abcd maps to :alphabetical (if :alphabetical registered otherwise :string)

  2. /u/42 maps to :uint (if :uint registered otherwise :int)

  3. /u/-1 maps to :int (if :int registered otherwise :string)

  4. /u/abcd123 maps to :string

app.Get("/u/{username:string}", func(ctx iris.Context) {
    ctx.Writef("username (string): %s", ctx.Params().Get("username"))
})

app.Get("/u/{id:int}", func(ctx iris.Context) {
    ctx.Writef("id (int): %d", ctx.Params().GetIntDefault("id", 0))
})

app.Get("/u/{uid:uint}", func(ctx iris.Context) {
    ctx.Writef("uid (uint): %d", ctx.Params().GetUintDefault("uid", 0))
})

app.Get("/u/{firstname:alphabetical}", func(ctx iris.Context) {
    ctx.Writef("firstname (alphabetical): %s", ctx.Params().Get("firstname"))
})

 Matches với tất cả các yêu cầu GET của /abctenchars.xml và /abcdtenchars respectfully.

app.Get("/{alias:string regexp(^[a-z0-9]{1,10}\\.xml$)}", PanoXML)
app.Get("/{alias:string regexp(^[a-z0-9]{1,10}$)}", Tour)

Bạn có thể tự hỏi {id:uint64} hoặc :path hoặc min(1) là gì. 

Chúng ta sẽ tìm hiểu thêm ở phần sau Các loại tham số đường dẫn.