Amandeep kaur
Amandeep kaur

Reputation: 1025

Gin context variable overrridden with parallel REST api requests

I have a saas project which is based upon Rest APIs. All apis are developed in GO using gin package. When the user logs in then I set current user details in the request context so that I can access these details furthere to display some data. However I had a case in which 2 requests hits in parallel & the context values for the 1st request are override with the context values in the 2nd request. Due to this, my data is displaying wrong.

package main

import (
    "fmt"
    "strings"

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

func main() {
    g := gin.Default()
    g.Use(ParseJWTToken)
    g.GET("/hello/:name", hello)
    g.Run(":9000")
}

func hello(c *gin.Context) {
    c.Keys = make(map[string]interface{})
    c.Keys["current_user_id"] = 10
    c.Keys["current_user_name"] = c.Param("name")
    fmt.Println(c.Keys)
    c.String(200, "Hello %s", c.Param("name"))
}

var role, userName string
var userId float64

func ParseJWTToken(c *gin.Context) {
    merchantDatabase := make(map[string]interface{})
    if values, _ := c.Request.Header["Authorization"]; len(values) > 0 {
        bearer := strings.Split(c.Request.Header["Authorization"][0], "Bearer")
        bearerToken := strings.TrimSpace(bearer[1])
        var userAgent string
        var userAgentCheck bool
        if values, _ := c.Request.Header["User-Agent"]; len(values) > 0 {
            userAgent = values[0]
        }
        _ = config.InitKeys()
        token, err := jwt.Parse(bearerToken, func(token *jwt.Token) (interface{}, error) {
            return config.SignKey, nil
        })

        if err != nil {
            c.Abort()
            return
        }
        if !token.Valid {
            c.Abort()
            return
        }
        if len(token.Claims.(jwt.MapClaims)) > 0 {
            for key, claim := range token.Claims.(jwt.MapClaims) {
                if key == "user_agent" {
                    if claim == userAgent {
                        userAgentCheck = true
                    }
                }
                if key == "role" {
                    role = claim.(string)
                }
                if key == "id" {
                    userId = claim.(float64)
                }
                if key == "name" {
                    userName = claim.(string)
                }
            }
        }
        merchantDatabase["userid"] = userId
        merchantDatabase["role"] = role
        merchantDatabase["username"] = userName
        c.Keys = merchantDatabase
        if userAgentCheck {
            c.Next()
        } else {
            c.Abort()
            return
        }
    } else {
        c.Abort()
        return
    }
}

This issue is not produced every time for parallel requests.

How can I fix that ?

Upvotes: 1

Views: 798

Answers (1)

Amandeep kaur
Amandeep kaur

Reputation: 1025

I have used global variables for the details that were overridden. Declaring these inside the middleware fixed the issue. Find complete thread here: https://github.com/gin-gonic/gin/issues/3437

Upvotes: 0

Related Questions