Идиоматический способ проверки HTTP-запроса в го - PullRequest
0 голосов
/ 25 августа 2018

Мне нужно проверить, что мой http-запрос имеет два параметра, Start и End.В настоящее время я устанавливаю значение по умолчанию, которое не должно отображаться в качестве одного из параметров, и проверяю его вместе с другими недопустимыми значениями.Тем не менее, это похоже на взломать.Какой должен быть правильный способ сделать это?

Вот мой код:

type Request struct {
    Start int `json: "start"`
    End int `json: "end"`
}


func HandlePost(w http.ResponseWriter, r *http.Request) {
    body , _ := ioutil.ReadAll(r.Body)
    reqData := Request{Start: -1, End: -1} // < whats the correct way to do this
    json.Unmarshal(body, &reqData)  

    if reqData.Start < 0 && reqData.End < 0 {
        w.WriteHeader(http.StatusBadRequest)
        return
    }
    // rest of the logic
}

Ответы [ 3 ]

0 голосов
/ 25 августа 2018

Вы можете использовать https://github.com/asaskevich/govalidator для базового способа проверки запроса. Но если вы хотите что-то более сложное, вам нужно написать свою собственную функцию валидатора. например,

type Request struct {
    Start int `json: "start"`
    End int `json: "end"`
}

func (a *Request) validate() url.Values {
    err := url.Values{}

    // Write your own validation rules
    if a.Start < 0 {
        err.Add("Start", "Start cannot be less than 0");
    }

    return err;
}

func handler(w http.ResponseWriter, r *http.Request) {
    requestBody := &Request{}

    defer r.Body.Close()
    if err := json.NewDecoder(r.Body).Decode(requestBody); err != nil {
        panic(err)
    }

    if errors := requestBody.validate(); len(errors) > 0 {
        err := map[string]interface{}{"validationError": errors}
        w.Header().Set("Content-type", "application/json")
        w.WriteHeader(http.StatusBadRequest)
        json.NewEncoder(w).Encode(err)
    }

    fmt.Fprint(w, "success request scenario!")
}
0 голосов
/ 27 августа 2018

Вот еще один способ проверки структур с использованием тегов структуры и указателей.Обратите внимание, что если 0 является допустимой вещью, то это решение не будет работать.omitempty считает значение 0 пустым.Если вы хотите, чтобы это работало, с учетом того, что 0 является действительным, удалите указатели и измените метод IsValid

package main

import (
    "encoding/json"
    "fmt"
)

type Request struct {
    Start *int `json: "start,omitempty"`
    End   *int `json: "end,omitempty"`
}

func (r Request) IsValid() (bool, error) {
    if r.Start == nil {
        return false, fmt.Errorf("start is missing")
    }

    if r.End == nil {
        return false, fmt.Errorf("end is missing")
    }

    return true, nil
}

var (
    invalidStartb = `{"end": 1}`
    invalidEndb   = `{"start": 1}`
    valid         = `{"start": 1, "end": 1}`
)

func main() {
    var r Request

    _ = json.Unmarshal([]byte(invalidStartb), &r)
    fmt.Println(r.IsValid())

    r = Request{}
    _ = json.Unmarshal([]byte(invalidEndb), &r)
    fmt.Println(r.IsValid())

    r = Request{}
    _ = json.Unmarshal([]byte(valid), &r)
    fmt.Println(r.IsValid())

}

запускаемая версия здесь https://goplay.space/#Z0eqLpEHO37

0 голосов
/ 25 августа 2018

Вы можете использовать https://github.com/buger/jsonparser getInt.Вы получите сообщение об ошибке, если в json отсутствует ожидаемый ключ.

Я рекомендую использовать бенчмарк, а не определять красоту кода или любую другую догадку

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...