상세 컨텐츠

본문 제목

Golang - echo Binding Request Data

Web/Echo

by Yongari 2023. 4. 11. 15:25

본문

바인딩 요청 데이터

 

구조체 태그 바인딩
- 데이터 소스
- 데이터 유형
- 다중 소스
- 직접 소스
- 보안
- 예제

Fluent 바인딩
- 오류 처리
- 예제
- 지원되는 데이터 유형
사용자 지정 바인딩

요청 데이터 구문 분석은 웹 애플리케이션에서 매우 중요한 부분입니다. Echo에서는 바인딩이라는 프로세스를 통해 이 작업을 수행합니다. 바인딩은 HTTP 요청의 다음 부분에서 클라이언트가 전달한 정보로 수행됩니다:

- URL 경로 매개변수
- URL 쿼리 매개변수
- 헤더
- 요청 본문
- Echo는 바인딩을 수행하는 다양한 방법을 제공하며, 각 방법은 아래 섹션에 설명되어 있습니다.

- 구조체 태그 바인딩
구조체 바인딩을 사용하면 데이터 소스와 해당 키를 지정하는 태그가 있는 Go 구조체를 정의할 수 있습니다. 요청 핸들러에서 구조체에 대한 포인터와 함께 Context#Bind(i interface{})를 호출하기만 하면 됩니다. 태그는 바인더가 요청에서 데이터를 로드하기 위해 알아야 할 모든 것을 알려줍니다.

이 예제에서 구조체 유형 User는 바인더에게 쿼리 문자열 매개변수 id를 해당 문자열 필드 ID에 바인딩하도록 지시합니다:

 

type User struct {
  ID string `query:"id"`
}

// in the handler for /users?id=<userID>
var user User
err := c.Bind(&user); if err != nil {
    return c.String(http.StatusBadRequest, "bad request")
}

데이터 소스
Echo는 데이터 소스를 지정하는 다음 태그를 지원합니다:

query - 쿼리 매개변수
param - 경로 매개변수(경로라고도 함)
header - 헤더 매개변수
json - 요청 본문. 언마샬링에 내장된 Go json 패키지를 사용합니다.
xml - 요청 본문. 언마샬링에 내장된 Go xml 패키지를 사용합니다.
form - 양식 데이터. 쿼리 및 요청 본문에서 값을 가져옵니다. Go 표준 라이브러리 양식 구문 분석을 사용합니다.

 

데이터 유형
요청 본문을 디코딩할 때 Content-Type 헤더에 지정된 대로 다음과 같은 데이터 유형이 지원됩니다:

application/json
application/xml
application/x-www-form-urlencoded

경로 매개변수, 쿼리 매개변수, 헤더 또는 양식 데이터를 바인딩할 때는 각 구조체 필드에 태그를 명시적으로 설정해야 합니다. 그러나 태그가 생략된 경우 구조체 필드 이름에 JSON 및 XML 바인딩이 수행됩니다. 이는 Go의 json 패키지의 동작에 따른 것입니다.

양식 데이터의 경우, Echo는 Go 표준 라이브러리 양식 파싱을 사용합니다. 콘텐츠 유형이 MIMEMultipartForm이 아닌 경우 요청 URL과 본문 모두에서 양식 데이터를 구문 분석합니다. MIMEMultipartForm이 아닌 양식에 대한 설명서를 참조하세요.

 

 

Multiple Sources

 

동일한 필드에 여러 소스를 지정할 수 있습니다. 이 경우 요청 데이터는 이 순서대로 바인딩됩니다:

  1. Path parameters (경로 매개변수) 
  2. Query parameters (only for GET/DELETE methods) (쿼리 매개변수(GET/DELETE 메서드에만 해당))
  3. Request body ( 요청 본문)
type User struct {
  ID string `param:"id" query:"id" form:"id" json:"id" xml:"id"`
}

각 단계에서 바인딩하면 이전 단계에서 바인딩된 데이터를 덮어쓰게 됩니다. 즉, JSON 요청에 쿼리 매개변수 name=query와 본문 {"name": "body"}가 포함된 경우 결과는 User{Name: "body"}가 됩니다.

 

Direct Source

특정 소스에서 직접 데이터를 바인딩할 수도 있습니다:

Request body:

err := (&DefaultBinder{}).BindBody(c, &payload)
Copy

Query parameters:

err := (&DefaultBinder{}).BindQueryParams(c, &payload)
Copy

Path parameters:

err := (&DefaultBinder{}).BindPathParams(c, &payload)
Copy

Header parameters:

err := (&DefaultBinder{}).BindHeaders(c, &payload)

헤더는 Context#Bind에 포함된 소스 중 하나가 아니라는 점에 유의하세요. 헤더 데이터를 바인딩하는 유일한 방법은 BindHeaders를 직접 호출하는 것입니다. 

 

 

Security


애플리케이션의 보안을 유지하려면 바인딩할 수 없는 필드가 포함된 경우 바인딩된 구조체를 다른 메서드에 직접 전달하지 마세요. 바인딩을 위한 별도의 구조체를 만들어 비즈니스 구조체에 명시적으로 매핑하는 것이 좋습니다.

바인딩된 구조체에 Exported 필드 IsAdmin 부울이 있고 요청 본문에 {IsAdmin: true, Name: "hacker"}.

Example


이 예에서는 json, 양식 또는 쿼리 요청 데이터에서 바인딩할 필드 태그가 있는 User 구조체 유형을 정의합니다:

 

type User struct {
  Name  string `json:"name" form:"name" query:"name"`
  Email string `json:"email" form:"email" query:"email"`
}

type UserDTO struct {
  Name    string
  Email   string
  IsAdmin bool
}

 

그리고 POST /users 경로의 핸들러는 요청 데이터를 구조체에 바인딩합니다:

e.POST("/users", func(c echo.Context) (err error) {
  u := new(User)
  if err = c.Bind(u); err != nil {
    return c.String(http.StatusBadRequest, "bad request")
  }

  // Load into separate struct for security
  user := UserDTO{
    Name: u.Name,
    Email: u.Email,
    IsAdmin: false // avoids exposing field that should not be bound
  }

  executeSomeBusinessLogic(user)
  
  return c.JSON(http.StatusOK, u)
})

 

 

JSON Data

curl -X POST http://localhost:1323/users \
  -H 'Content-Type: application/json' \
  -d '{"name":"Joe","email":"joe@labstack"}'
Copy

Form Data

curl -X POST http://localhost:1323/users \
  -d 'name=Joe' \
  -d 'email=joe@labstack.com'
Copy

Query Parameters

curl -X GET 'http://localhost:1323/users?name=Joe&email=joe@labstack.com'

 

Fluent Binding

Echo는 지정된 소스의 명시적 데이터 유형을 바인딩하는 인터페이스를 제공합니다. 플루언트 인터페이스라고도 하는 메서드 체인을 사용합니다.

다음 메서드는 Go 데이터 유형에 바인딩하기 위한 몇 가지 메서드를 제공합니다. 이러한 바인더는 유창한 구문을 제공하며 바인딩을 구성 및 실행하고 오류를 처리하기 위해 체인으로 연결할 수 있습니다.

echo.QueryParamsBinder(c) - 쿼리 매개변수(소스 URL)를 바인딩합니다.
echo.PathParamsBinder(c) - 경로 매개변수(소스 URL)를 바인딩합니다.
echo.FormFieldBinder(c) - 양식 필드(소스 URL + 본문)를 바인딩합니다. Request.ParseForm도 참조하세요.
오류 처리
바인더는 일반적으로 BindError() 또는 BindErrors()를 호출하여 완료됩니다. 에러가 발생한 경우 BindError()는 처음 발생한 에러를 반환하고, BindErrors()는 모든 바인딩 에러를 반환합니다. 바인더에 저장된 모든 오류도 재설정됩니다.

FailFast(true)를 사용하면 첫 번째 오류 발생 시 바인딩을 중지하도록 바인더를 구성할 수 있고, FailFast(false)를 사용하면 전체 바인더 호출 체인을 실행할 수 있습니다. Fail fast는 기본적으로 활성화되어 있으며 BindErrors()를 사용할 때는 비활성화해야 합니다.

 

 

Example

// url =  "/api/search?active=true&id=1&id=2&id=3&length=25"
var opts struct {
  IDs []int64
  Active bool
}
length := int64(50) // default length is 50

// creates query params binder that stops binding at first error
err := echo.QueryParamsBinder(c).
  Int64("length", &length).
  Int64s("ids", &opts.IDs).
  Bool("active", &opts.Active).
  BindError() // returns first binding error
 

 

Supported Data Types

Data TypeNotes
bool  
float32  
float64  
int  
int8  
int16  
int32  
int64  
uint  
uint8/byte Does not support bytes(). Use BindUnmarshaler/CustomFunc to convert value from base64 etc to []byte{}.
uint16  
uint32  
uint64  
string  
time  
duration  
BindUnmarshaler() binds to a type implementing BindUnmarshaler interface
TextUnmarshaler() binds to a type implementing encoding.TextUnmarshaler interface
JsonUnmarshaler() binds to a type implementing json.Unmarshaler interface
UnixTime() converts Unix time (integer) to time.Time
UnixTimeMilli() converts Unix time with millisecond precision (integer) to time.Time
UnixTimeNano() converts Unix time with nanosecond precision (integer) to time.Time
CustomFunc() callback function for your custom conversion logic

지원되는 각 유형에는 다음과 같은 메서드가 있습니다:

<Type>("param", &destination) - 매개변수 값이 존재하면 해당 유형의 지정된 대상(예: Int64(...))에 바인딩합니다.
Must<Type>("param", &destination) - 매개변수 값이 존재해야 하는 경우 해당 유형의 지정된 대상(예: MustInt64(...))에 바인딩합니다.
<Type>s("param", &destination) - (슬라이스의 경우) 매개변수 값이 존재하면 해당 유형의 지정된 대상(예: Int64s(...)에 바인딩합니다.
Must<Type>s("param", &destination) - (슬라이스의 경우) 매개변수 값이 존재해야 하는 경우, 해당 유형의 지정된 대상(예: MustInt64s(...))에 바인딩합니다.
특정 슬라이스 타입의 경우 BindWithDelimiter("param", &dest, ",")는 타입 변환이 완료되기 전에 매개변수 값을 분할하는 기능을 지원합니다. 예를 들어 URL /api/search?id=1,2,3&id=1에서 정수 슬라이스를 바인딩하면 []int64{1,2,3,1}이 됩니다.

사용자 정의 바인딩

 

type CustomBinder struct {}

func (cb *CustomBinder) Bind(i interface{}, c echo.Context) (err error) {
  // You may use default binder
  db := new(echo.DefaultBinder)
  if err := db.Bind(i, c); err != echo.ErrUnsupportedMediaType {
    return
  }

  // Define your custom implementation here
  return
}

 

 

출처 : https://echo.labstack.com/guide/binding/

 

Echo - High performance, minimalist Go web framework

Echo is a high performance, extensible, minimalist web framework for Go (Golang).

echo.labstack.com

 

'Web > Echo' 카테고리의 다른 글

Golang - Echo BoilerPlate (해외 github repository 참고)  (0) 2023.04.12

관련글 더보기