Как получить данные из интерфейса в джине? - PullRequest
0 голосов
/ 10 ноября 2018

К своему стыду, я не смог понять, как получить данные из интерфейса в Gin Framework. В Джанго я получаю данные Итак:

user=request.data.get('user')
print(user)

Все просто и понятно как день. Как мне это сделать в джине?

user := c.Query("user")
user := c.Param("user")
user := c.Params.ByName("user")
user := c.PostForm("user")
println(user)//emptiness....

Ответы [ 4 ]

0 голосов
/ 15 ноября 2018

Сервер GIN не может обрабатывать стандартные запросы приложений / json от axios !!! Какие??? Запросы следует отправлять в виде application / x-www-form-urlencoded. Мое решение в проекте Vue: Используйте vue-resource вместо axios (axios.post => this. $ Http.post) с опцией Vue.http.options.emulateJSON = true; в main.js

0 голосов
/ 10 ноября 2018

Ну, я бы сказал, что вы должны взять какую-нибудь книгу / HOWTO о том, как работает HTTP, и потратить некоторое время на него, потому что кажется, что вы пытаетесь решить проблему, не понимая, что происходит между вашим браузером и бэкэндомобслуживание.

Реальная проблема здесь в том, что есть больше движущихся частей, о которых вы, кажется, знаете, и путь зависит от того, что делает ваш фронт.

Вы не сказали намточно как вы выполняете свой запрос, но из запрошенного комментария оказывается, что вы используете этот "аксиос" с оттенком.Если мне удалось правильно отыскать этот проект в Google, в его README указано :

По умолчанию axios сериализует объекты JavaScript в JSON.Вместо этого, чтобы отправлять данные в формате application/x-www-form-urlencoded, вы можете использовать один из следующих вариантов:

Это означает две вещи:

  1. Если вы как-то не настроили осевое 'Когда вы сделали axios.port, в настройках предположительно выполняется HTTP-запрос POST с полем Content-Type, установленным на application/json, а его полезная нагрузка (или «тело», если вы предпочитаете) является сериализацией JSON этого {user:this.user} объекта JavaScript.
  2. Поэтому бесполезно пытаться разобрать строку запроса.И бесполезно пытаться проанализировать запрос как HTTP-форму, а это не так.

Вместо этого вы, вероятно, хотите интерпретировать тело входящего запроса как JSON-форматированное.Я понятия не имею, как это сделать в "go-gin", но в простом Go это будет что-то вроде

func (h *Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
  defer req.Body.Close()

  var user User

  dec := json.NewDecoder(req.Body)
  err := dec.Decode(&user)
  if err != nil {
    rw.Header().Set("Content-Type", "text/plain; charset=UTF-8")
    rw.WriteHeader(http.StatusBadRequest)
    fmt.Fprintln(rw, "Error parsing request body: ", err)
    return
  }
}

И в идеале вы сначала должны проверить, что тип содержимого входящего запросабыл действительно application/json и отклонить его сразу с http.StatusBadRequest, если это не так.

Примером рабочего кода, который нужно сделать, является

// VerifyContentTypeIsJSON makes sure the HTTP header of a server
// http.Request contains the Content-Type field and it indicates
// the request payload is JSON.
// The implementation is based on RFC 7231 (section 3.1.1.5) and RFC 8259.
func VerifyContentTypeIsJSON(header http.Header) error {
    var s string

    if values := header["Content-Type"]; len(values) > 0 {
        s = values[0]
    } else {
        return errors.New("missing Content-Type")
    }

    if s == "" {
        return errors.New("empty Content-Type")
    }

    if i := strings.IndexByte(s, ';'); i != -1 {
        s = strings.TrimSpace(s[:i])
    }

    if strings.ToLower(s) != "application/json" {
        return fmt.Errorf("unknown Content-Type: %v, must be application/json", s)
    }

    return nil
}

Имея эту функцию, выпосле defer req.Body.Close() будет что-то вроде этого и фактически проанализировано:

if err := VerifyContentTypeIsJSON(req.Header); err != nil {
  rw.Header().Set("Content-Type", "text/plain; charset=utf-8")
  rw.WriteHeader(http.StatusBadRequest)
  fmt.Fprintln(rw, err)
  return
}

(Обратите внимание, что в go-gin может быть что-то похожее на это уже встроенное, поэтому, пожалуйста, проверьте это.)

Тип User должен быть некоторого типа struct, соответствующего форме объекта JSON, который вы намерены удалить из запроса.Примерно так:

type User struct {
  User string `json:"user"`
}

Нет, что в двух местах мой пример вернул пользователю ошибку, он использовал тип содержимого простого текста (в кодировке UTF-8).Это может быть хорошо, но может и нет.Скажем, ваши клиенты могут ожидать документ в формате JSON какой-то согласованной формы.

Или вы можете использовать согласование контента , но я бы рекомендовал сначала разобраться с простыми вещами.


Литература для проверки:


И, возможно, ответьте на ту часть вашего вопроса о том, почему это «просто сработало» в Django.Я могу только догадываться, но я думаю, что он просто реализует тонны магии, которая смотрит на входящий запрос и пытается угадать , как извлечь из него данные.

Проблема в том, что угадывание действительно можетхорошо работают для одноразовых одноразовых сценариев, но когда вы собираетесь реализовать что-то вроде веб-API (то, что многие не совсем корректно называют «REST», но давайте не будем отступать), лучше быть очень откровенным о том, что ваша конечная точка принимает точно и как точно они реагируют на запросы - как законные, так и недопустимые.

Что касается магии в Go, вы можете прочитать this .

0 голосов
/ 11 ноября 2018

Если вы ожидаете тело JSON в запросе, вы можете сделать это с помощью gin. Создайте структуру для данных, которые вы хотите извлечь из тела. Используйте json теги для имен ключей JSON, если вы не собираетесь точно сопоставлять им имена полей Go. Затем вызовите метод BindJSON в контексте джина.

Например:

type User struct {
    FirstName string `json:"first_name"`
    LastName  string `json:"last_name"`
    Login     string `json:"login"`
}

func (h *Handler) HandleUser(gctx *gin.Context) {
    user := new(User)
    err := gctx.BindJSON(user)
    if err != nil {
        text := fmt.Sprintf("Failed to read user data from request: %s", err)
        log.Error(text)
        gctx.JSON(http.StatusBadRequest, gin.H{"error": text})
        return
    }
    // do something with user
}
0 голосов
/ 10 ноября 2018

Вам необходимо позвонить c.Request.ParseForm() перед использованием request.Form

говорит здесь :

Для всех запросов ParseForm анализирует необработанный запрос с URL и обновляет r.Form

Для других методов HTTP, или когда Content-Type не является application / x-www-form-urlencoded, тело запроса не читается, и r.PostForm инициализируется как ненулевое пустое значение.

...