2015-09-08 3 views
1

У меня есть следующий Gin межплатформенное:Не удалось Прервать() контекст - джин

func CheckAppId(appC *core.Context) gin.HandlerFunc { 
    return func(c *gin.Context) { 
     //get Basic Auth credentials 
     appId, token, _ := c.Request.BasicAuth() 

     if appId == "" { 
      c.JSON(http.StatusOK, gin.H{"code": "MISSING_APP_ID", "message": "Your request is missing an application id"}) 
      return //this is being ignored??? 
     } 

     c.Next() //this still gets hit 
    } 
} 

но если appId == "" JSON получает вернулся и c.Next() запускается на выполнение слишком. Это ожидаемое поведение?

EDIT Я думал, что проблема была продана, но происходит то же самое. Теперь у меня есть:

func CheckAppId(appC *core.Context) gin.HandlerFunc { 
    return func(c *gin.Context) { 
     //get Basic Auth credentials 
     appId, token, _ := c.Request.BasicAuth() 

     if appId == "" { 
      //I'm getting this JSON in the response 
      c.JSON(http.StatusOK, gin.H{"code": "MISSING_APP_ID", "message": "Your request is missing an application id"}) 
      c.Abort() 
     } 

     //find app_id in database 
     app := core.App{} 
     err := appC.Database.C("apps").Find(bson.M{"id" : appId}).One(&app) 
     if err != nil { //no app found 
      //and I'm getting this JSON in the response 
      c.JSON(http.StatusOK, gin.H{"code": "INVALID_APP_ID", "message": "The application id provided could not be found"}) 
      c.Abort() 
     } 

     c.Next() 
    } 
} 

В вызове API я получаю как «MISSING_APP_ID» Json и «INVALID_APP_ID» Json

+1

Вы уверены, что это действительно так? Сделайте 'fmt.Printf («% # v \ n », appId)' right before 'c.Next()' – Lander

+0

В ответе есть JSON в вопросе и больше JSON от фактического маршрута, по которому запрос был ! – tommyd456

ответ

4

Глядя на Gin API Docs, вам нужно позвонить context.Abort() вместо того, чтобы вернуться от вашего метода.

Abort останавливает систему, чтобы продолжить вызов ожидающих обработчиков в цепочке. Допустим, у вас есть промежуточное ПО авторизации, которое проверяет, разрешен ли запрос, если авторизация завершается с ошибкой (пароль не совпадает). Этот метод (Abort()) должен быть вызван, чтобы остановить выполнение фактического обработчика.

Так что в вашем конкретном случае

if appId == "" { 
    c.JSON(http.StatusOK, gin.H{"code": "MISSING_APP_ID", "message": "Your request is missing an application id"}) 
    c.Abort() 
    return 
} 
+0

Хорошее место - не видел, что – tommyd456

+1

К сожалению, после дальнейшего тестирования у меня все еще остались те же проблемы. Код по-прежнему 'c.Abort()' по-прежнему выполняется по какой-либо причине? – tommyd456

+0

Я отредактировал мой вопрос, чтобы продемонстрировать – tommyd456

1

TL; DR

Вам нужно сделать:

if condition { 
    c.Abort() 
} else { 
    c.Next() 
} 

Объяснение

(Примечание: это основывается на ответе @Landers)

c.Abort() только устанавливает некоторые внутренние флаги, которые обозначают контекст определенным образом, что указывает на ненормальное завершение. Это имеет смысл, это беспараметрический метод, который ничего не возвращает, поэтому вы вызываете его только для своих побочных эффектов. не

То же самое с c.Next()

Из-за потока управления Гоу (без исключений или прыжков) его ясно, что эти два метода не предпринимать никаких немедленных действий, а «создать почву» для следующего этапа, представьте Джины код, который вызывает ваш CheckAppId FUNC:

// gin code 
doStuff() 
ctx := getContext() 

// this is your CheckAppId 
nextAction := FindAction() 
nextAction(&ctx) 

// here the context is evaluated to see if you either abort or continue. 
checkContextStatus(&ctx) 

Так что, если вы звоните c.Abort(), а затем c.Next() вы перекрывая показания Прервать.

+0

Извините, если я неправильно понял, но как я могу прекратить выполнение кода за пределами первого 'c.Abort()' - я не хочу запрашивать базу данных, если 'appId' не был предоставлен. Я вижу, что мой код заканчивается множеством вложенных условностей, имея в виду, что приведенный выше код является «обрезанной» версией того, что у меня действительно есть. – tommyd456

+0

Я предполагаю добавить оператор return после каждого 'c.Abort()' и 'c.Next()', если он не последний. –

+0

Справа - поэтому сочетание того и другого было необходимым - оцените помощь и объяснение – tommyd456