Gin: Dapatkan rute yang cocok dalam konteks

Dibuat pada 27 Nov 2016  ·  24Komentar  ·  Sumber: gin-gonic/gin

Saya memiliki kasus penggunaan di mana daftar api yang terbuka harus tersedia sebagai api, di mana pengguna admin dapat menambahkan beberapa parameter tambahan untuk disimpan ke DB.

Yang pada dasarnya saya butuhkan adalah mendapatkan rute yang cocok dalam konteks untuk diproses dalam fungsi middleware atau handler.

router.GET("/get_user_details",func (c *gin.Context){c.JSON(200, gin.H{
           "matched_route":c.MatchedRoute(),
        })})

Jadi apakah ada yang seperti c.MatchedRoute atau cara lain untuk mencapai hasil?

Komentar yang paling membantu

coba dengan gin middleware

       r.Use(func(c *gin.Context) {
        url := c.Request.URL.String()
        for _, p := range c.Params {
            url = strings.Replace(url, p.Value, ":"+p.Key, 1)
        }
        c.Set("matched_path", url)
    })

maka Anda bisa mendapatkan matched_path dari gin.Context

    func(c *gin.Context) {
            if path, exist := c.Get("matched_path"); exist {
           ...
        }
    }

Semua 24 komentar

Anda dapat menggunakan c.Request.URL dan mengekstrak data yang Anda butuhkan dari URL

Jadi c.Request.URL memberikan jalur aktual yang dipanggil dan bukan jalur yang cocok dengan gin (atau httprouter). Misalnya untuk permintaan yang memiliki params, katakanlah /user/:id Saya ingin dapat mengambil string mentah /user/:id apakah itu mungkin?

@Depado bisa tolong beri contoh?

Hei disana

Katakanlah saya memiliki kode ini:

package main

import (
    "net/http"

    "github.com/gin-gonic/gin"
)

func mymiddleware() gin.HandlerFunc {
    return func(c *gin.Context) {
        // There ?
        c.Next()
    }
}

func main() {
    r := gin.New()
    r.GET("/user/:id", mymiddleware(), func(c *gin.Context) {
        // How can I get the litteral string "/user/:id" here ?
        c.JSON(http.StatusOK, gin.H{"message": "received request"})
    })
}

Apakah ada cara saya dapat mengambil di dalam pawang string literal /user/:id , pola yang cocok dengan permintaan? Jika saya menggunakan c.Request.Path itu akan memberi saya output penuh dari path jadi hal-hal seperti /user/123456

Mengapa Anda tidak menyimpannya dalam konstan dan Anda akan memilikinya sebagai variabel. Maksud saya, jika fungsinya berjalan, itu berarti cocok dengan polanya

Tentu tapi itu berarti tidak ada cara umum untuk mendapatkan pola yang cocok di handler dan mungkin mengotomatiskan hal-hal. Saya ingin menambahkan ini sebagai label prometheus. Apa yang saya temukan adalah middleware yang menggunakan pola ini sebagai argumen, membuatnya menjadi berlebihan r.GET("/user/:id", p.Instrument("/user/:id"), func(c *gin.Context) {})

Sekali lagi, saya tidak bisa benar-benar memahami masalah Anda.

Rute sudah ditentukan sebelumnya, tidak dibuat secara dinamis. Oleh karena itu, jika suatu rute cocok maka itu berarti Anda tahu router mana yang digunakan.

Saya bisa melihatnya sebagai masalah yang perlu dipecahkan dalam skala yang lebih besar. Solusi mudah adalah menyediakan rute yang cocok melalui Konteks.

Mungkin Anda bisa membuat permintaan tarik dengan fitur ini?

Saya akan senang jika saya punya waktu ^^ Saya akan mencoba melihatnya nanti.

Sepertinya ini akan membutuhkan penggunaan node.getValue dan node.path.

node.getValue harus mengembalikan node.path dan mengikatnya ke konteks atau sesuatu seperti itu. Atau mungkin ikat simpul ke konteks ...

Saya melakukannya seperti ini di middleware prometehus saya:

func(c *gin.Context) {
        if c.Request.URL.String() == p.MetricsPath {
            c.Next()
            return
        }
        routes := p.parent.Routes()
        url := ""
        for _, r := range routes {
            if r.Handler == c.HandlerName() {
                url = r.Path
                break
            }
        }
.........
......

Apa itu p.parent.Routes() ?

gin.Mesin

Pada Kamis, 19 Oktober 2017, 16:50 Depado [email protected] menulis:

Apa itu p.parent.Routes() ?


Anda menerima ini karena Anda berkomentar.
Balas email ini secara langsung, lihat di GitHub
https://github.com/gin-gonic/gin/issues/748#issuecomment-337932638 , atau bisukan
benang
https://github.com/notifications/unsubscribe-auth/ABF-FeXrALCzTR_Jj9W7xjkKHV0xwu0Yks5st2HRgaJpZM4K9F8w
.

Jadi begitu ! Saya akan mencobanya terima kasih! 👍

Itu berfungsi dengan baik @jonaz 👍
Meskipun bersepeda lain semua rute Anda setiap kali ada permintaan dapat dioptimalkan, jadi saya menggunakan map[string]string seperti ini:

func (p *Prometheus) Instrument() gin.HandlerFunc {
    return func(c *gin.Context) {
        var path string
        start := time.Now()
        reqSz := computeApproximateRequestSize(c.Request)

        if c.Request.URL.String() == p.MetricsPath {
            c.Next()
            return
        }

        if in, ok := p.PathMap[c.HandlerName()]; ok {
            path = in
        } else {
            // We miss some routes so let's parse that again
            for _, ri := range p.Engine.Routes() {
                p.PathMap[ri.Handler] = ri.Path
            }
            if in, ok := p.PathMap[c.HandlerName()]; ok {
                path = in
            } // If we don't know the path here, then we'll never have it
        }

        c.Next()

        status := strconv.Itoa(c.Writer.Status())
        elapsed := float64(time.Since(start)) / float64(time.Second)
        resSz := float64(c.Writer.Size())

        p.reqDur.Observe(elapsed)
        p.reqCnt.WithLabelValues(status, c.Request.Method, c.HandlerName(), c.Request.Host, path).Inc()
        p.reqSz.Observe(float64(reqSz))
        p.resSz.Observe(resSz)
    }
}

Dengan cara ini saya memiliki kesempatan untuk menginisialisasi peta ketika r.Use(mymiddleware) digunakan, dan jika rute tidak ditemukan saat menanggapi permintaan, saya memperbarui peta. Jadi hanya permintaan pertama yang berpotensi menjadi sedikit lebih lambat.

saya menemukan masalah yang sama, dan jika melakukannya seperti yang Anda katakan, harus menjamin setiap rute cocok dengan penangan yang berbeda.

Saya akhirnya membuat ulang middleware gin untuk Prometheus di sana . Saya harus menggunakan peta yang dilindungi (termasuk mutex).
Dan ya memang Anda harus menggunakan penangan yang berbeda untuk jalur yang berbeda.

Saya juga telah melakukan metode yang sama (argumen fungsi redundan) untuk menyelesaikan ini tahun lalu.

coba dengan gin middleware

       r.Use(func(c *gin.Context) {
        url := c.Request.URL.String()
        for _, p := range c.Params {
            url = strings.Replace(url, p.Value, ":"+p.Key, 1)
        }
        c.Set("matched_path", url)
    })

maka Anda bisa mendapatkan matched_path dari gin.Context

    func(c *gin.Context) {
            if path, exist := c.Get("matched_path"); exist {
           ...
        }
    }

@tsirolnik alasan untuk hal seperti ini adalah untuk menambahkan metrik per-api misalnya. Senang rasanya dapat memiliki jumlah metrik berdasarkan jalur istirahat seperti metrik dimensi untuk:

POST /users/:userid/stories/:storyid

Alternatif saat ini adalah Anda hanya memiliki metrik per pengguna/kombo storyid yang tidak terlalu berguna.

Info yang dibutuhkan ada di router dan saat ini kami harus memeriksa secara mendalam ke router untuk mengetahuinya (beberapa tambalan terkait), atau harus memiliki middleware yang mengetahui semua pemetaan rute dan memahaminya.

Middleware Prometheus adalah contoh yang sangat bagus untuk ini. https://github.com/Depado/ginprom/blob/master/prom.go

Baru saja menemukan ini dan ingin menyebutkan cara lain untuk mencapai ini adalah dengan mendeklarasikan "metricName" sambil mendeklarasikan nama titik akhir. Ini adalah bagaimana kami melakukannya sebelumnya.

Jadi rute kami terlihat seperti ini:

r.GET("/users/:userId", metrics("users"), getUserById)

Di mana middleware metrik menangkap latensi dan mengirimkannya ke DataDog.

Apa ada?

PR #1826 menambahkan gin.Context.FullPath() . Itu digabungkan ke master tetapi belum dirilis.

Kapan versi berikutnya akan dirilis?

Jika Anda sudah menggunakan rute seperti router.GET("/:serviceEnv/*routePath", controllers.ProxyToAnotherServer) ,

maka Anda dapat mengakses rute yang cocok dengan baik melalui *routePath bukan?

func ProxyToAnotherServer(c *gin.Context) {
    relativeRoutePath := c.Param("routePath")
}
Apakah halaman ini membantu?
0 / 5 - 0 peringkat