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?
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")
}
Komentar yang paling membantu
coba dengan gin middleware
maka Anda bisa mendapatkan
matched_path
darigin.Context