Go Resty는 RESTful API 클라이언트를 구축하기 위한 Go 언어 라이브러리입니다. Go Resty를 사용하면 개발자는 더 빠르고 효율적으로 신뢰할 수 있는 RESTful API 클라이언트를 구축할 수 있습니다. 본 장에서는 Go Resty로 빠르게 시작하는 방법을 소개합니다.

설치

require github.com/go-resty/resty/v2 v2.7.0

또는

go get github.com/go-resty/resty/v2

Resty 예제

다음 예제는 resty 라이브러리를 가능한 편안하게 사용할 수 있도록 도와줍니다.

// 코드에 resty를 가져와 `resty`로 참조합니다.
import "github.com/go-resty/resty/v2"

간단한 GET 요청

// Resty 클라이언트 생성
client := resty.New()

resp, err := client.R().
    EnableTrace().
    Get("https://httpbin.org/get")

// 응답 객체 탐색
fmt.Println("응답 정보:")
fmt.Println("  에러       :", err)
fmt.Println("  상태 코드  :", resp.StatusCode())
fmt.Println("  상태       :", resp.Status())
fmt.Println("  프로토콜   :", resp.Proto())
fmt.Println("  시간       :", resp.Time())
fmt.Println("  받은 시각  :", resp.ReceivedAt())
fmt.Println("  본문       :\n", resp)
fmt.Println()

// 추적 정보 탐색
fmt.Println("요청 추적 정보:")
ti := resp.Request.TraceInfo()
fmt.Println("  DNS 조회         :", ti.DNSLookup)
fmt.Println("  연결 시간        :", ti.ConnTime)
fmt.Println("  TCP 연결 시간    :", ti.TCPConnTime)
fmt.Println("  TLS 핸드쉐이크   :", ti.TLSHandshake)
fmt.Println("  서버 시간        :", ti.ServerTime)
fmt.Println("  응답 시간        :", ti.ResponseTime)
fmt.Println("  총 시간          :", ti.TotalTime)
fmt.Println("  연결 재사용 여부 :", ti.IsConnReused)
fmt.Println("  연결이 유휴 상태 :", ti.IsConnWasIdle)
fmt.Println("  연결 유휴 시간  :", ti.ConnIdleTime)
fmt.Println("  요청 시도        :", ti.RequestAttempt)
fmt.Println("  원격 주소        :", ti.RemoteAddr.String())
출력
응답 정보:
  에러       : 
  상태 코드  : 200
  상태       : 200 OK
  프로토콜   : HTTP/2.0
  시간       : 457.034718ms
  받은 시각  : 2020-09-14 15:35:29.784681 -0700 PDT m=+0.458137045
  본문       :
  {
    "args": {},
    "headers": {
      "Accept-Encoding": "gzip",
      "Host": "httpbin.org",
      "User-Agent": "go-resty/2.4.0 (https://github.com/go-resty/resty)",
      "X-Amzn-Trace-Id": "Root=1-5f5ff031-000ff6292204aa6898e4de49"
    },
    "origin": "0.0.0.0",
    "url": "https://httpbin.org/get"
  }

요청 추적 정보:
  DNS 조회         : 4.074657ms
  연결 시간        : 381.709936ms
  TCP 연결 시간    : 77.428048ms
  TLS 핸드쉐이크   : 299.623597ms
  서버 시간        : 75.414703ms
  응답 시간        : 79.337µs
  총 시간          : 457.034718ms
  연결 재사용 여부 : false
  연결이 유휴 상태 : false
  연결 유휴 시간  : 0s
  요청 시도        : 1
  원격 주소        : 3.221.81.55:443

복잡한 GET 요청

// Resty 클라이언트 생성
client := resty.New()

// 쿼리 매개변수 설정
resp, err := client.R().
      SetQueryParams(map[string]string{
          "page_no": "1",
          "limit": "20",
          "sort":"name",
          "order": "asc",
          "random":strconv.FormatInt(time.Now().Unix(), 10),
      }).
      SetHeader("Accept", "application/json").
      SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F").
      Get("/search_result")

// Request.SetQueryString 메서드 사용 예시
resp, err := client.R().
      SetQueryString("productId=232&template=fresh-sample&cat=resty&source=google&kw=buy a lot more").
      SetHeader("Accept", "application/json").
      SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F").
      Get("/show_product")

// 필요한 경우 지정된 응답 콘텐츠 유형을 강제하여 Resty가 JSON 응답을 구조체로 파싱하도록 지시
resp, err := client.R().
      SetResult(result).
      ForceContentType("application/json").
      Get("v2/alpine/manifests/latest")

다양한 POST 요청 예제

// Resty 클라이언트 생성
client := resty.New()

// JSON 문자열로 POST
// 클라이언트 수준의 설정이 이미 되어 있으면 콘텐츠 유형을 설정할 필요가 없음
resp, err := client.R().
      SetHeader("Content-Type", "application/json").
      SetBody(`{"username":"testuser", "password":"testpass"}`).
      SetResult(&AuthSuccess{}).    // 또는 SetResult(AuthSuccess{}).
      Post("https://myapp.com/login")

// []byte 배열로 POST
// 클라이언트 수준의 설정이 이미 되어 있으면 콘텐츠 유형을 설정할 필요가 없음
resp, err := client.R().
      SetHeader("Content-Type", "application/json").
      SetBody([]byte(`{"username":"testuser", "password":"testpass"}`)).
      SetResult(&AuthSuccess{}).    // 또는 SetResult(AuthSuccess{}).
      Post("https://myapp.com/login")

// 구조체로 POST, 기본적으로 JSON 콘텐츠 유형, 설정할 필요가 없음
resp, err := client.R().
      SetBody(User{Username: "testuser", Password: "testpass"}).
      SetResult(&AuthSuccess{}).    // 또는 SetResult(AuthSuccess{}).
      SetError(&AuthError{}).       // 또는 SetError(AuthError{}).
      Post("https://myapp.com/login")

// 맵으로 POST, 기본적으로 JSON 콘텐츠 유형, 설정할 필요가 없음
resp, err := client.R().
      SetBody(map[string]interface{}{"username": "testuser", "password": "testpass"}).
      SetResult(&AuthSuccess{}).    // 또는 SetResult(AuthSuccess{}).
      SetError(&AuthError{}).       // 또는 SetError(AuthError{}).
      Post("https://myapp.com/login")

// 파일을 원시 바이트 배열로 업로드. 예: 파일을 Dropbox에 업로드
fileBytes, _ := os.ReadFile("/Users/jeeva/mydocument.pdf")

// Content-Type 헤더를 설정하지 않는 것에 주의. go-resty가 자동으로 Content-Type을 감지함
resp, err := client.R().
      SetBody(fileBytes).
      SetContentLength(true).          // Dropbox가 이 값을 요구함
      SetAuthToken("").
      SetError(&DropboxError{}).       // 또는 SetError(DropboxError{}).
      Post("https://content.dropboxapi.com/1/files_put/auto/resty/mydocument.pdf") // DropBox는 PUT 메서드 업로드도 지원함

// 참고: Content-Type 헤더가 설정되지 않으면 resty는 요청 본문의 Content-Type을 감지함
//   * 구조체 및 맵 데이터 유형의 경우 기본값은 'application/json'
//   * 그런 다음 일반 텍스트 콘텐츠 유형임

PUT 요청

POST와 같이 PUT 메소드 호출의 다양한 조합을 사용할 수 있습니다.

// 참고: 이것은 PUT 메소드를 사용하는 예시입니다. 더 많은 조합은 POST를 참고하세요.

// Resty 클라이언트 생성
client := resty.New()

// JSON 콘텐츠 유형으로 요청 보내기
// 클라이언트 수준의 설정이 있다면, 인증 토큰은 생략될 수 있고 에러를 처리할 수 있습니다
resp, err := client.R().
      SetBody(Article{
        Title: "go-resty",
        Content: "이것은 내 기사 콘텐츠입니다, 응! :)",
        Author: "Jeevanandam M",
        Tags: []string{"article", "example", "resty"},
      }).
      SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD").
      SetError(&Error{}).       // 또는 SetError(Error{}).
      Put("https://myapp.com/article/1234")

PATCH 요청

POST와 같이 PATCH 메소드 호출의 다양한 조합을 사용할 수 있습니다.

// 참고: 이것은 PATCH 메소드를 사용하는 예시입니다. 더 많은 조합은 POST를 참고하세요.

// Resty 클라이언트 생성
client := resty.New()

// JSON 콘텐츠 유형으로 요청 보내기
// 클라이언트 수준의 설정이 있다면, 인증 토큰은 생략될 수 있고 에러를 처리할 수 있습니다
resp, err := client.R().
      SetBody(Article{
        Tags: []string{"새로운 태그 1", "새로운 태그 2"},
      }).
      SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD").
      SetError(&Error{}).       // 또는 SetError(Error{}).
      Patch("https://myapp.com/articles/1234")

DELETE, HEAD, OPTIONS 요청

// Resty 클라이언트 생성
client := resty.New()

// 기사 삭제
// 클라이언트 수준의 설정이 있다면, 인증 토큰은 생략될 수 있고 에러를 처리할 수 있습니다
resp, err := client.R().
      SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD").
      SetError(&Error{}).       // 또는 SetError(Error{}).
      Delete("https://myapp.com/articles/1234")

// JSON 문자열로 여러 기사 삭제
// 클라이언트 수준의 설정이 있다면, 인증 토큰은 생략될 수 있고 에러를 처리할 수 있습니다
resp, err := client.R().
      SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD").
      SetError(&Error{}).       // 또는 SetError(Error{}).
      SetHeader("Content-Type", "application/json").
      SetBody(`{article_ids: [1002, 1006, 1007, 87683, 45432] }`).
      Delete("https://myapp.com/articles")

// 리소스의 헤더 정보 가져오기
// 클라이언트 수준의 설정이 있다면, 인증 토큰은 생략될 수 있습니다
resp, err := client.R().
      SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD").
      Head("https://myapp.com/videos/hi-res-video")

// 리소스의 옵션 정보 가져오기
// 클라이언트 수준의 설정이 있다면, 인증 토큰은 생략될 수 있습니다
resp, err := client.R().
      SetAuthToken("C6A79608-782F-4ED0-A11D-BD82FAD829CD").
      Options("https://myapp.com/servers/nyc-dc-01")

JSON 및 XML 직렬화/역직렬화 작업 설정

사용자는 resty에 선택한 JSON/XML 라이브러리를 등록하거나 자체 라이브러리를 작성할 수 있습니다. Resty는 기본적으로 표준 encoding/jsonencoding/xml 라이브러리를 등록합니다.

// json-iterator 등록 예시
import jsoniter "github.com/json-iterator/go"

json := jsoniter.ConfigCompatibleWithStandardLibrary

client := resty.New().
    SetJSONMarshaler(json.Marshal).
    SetJSONUnmarshaler(json.Unmarshal)

// 마찬가지로, 사용자는 다음과 같이 XML을 설정할 수 있습니다 -
client.SetXMLMarshaler(xml.Marshal).
    SetXMLUnmarshaler(xml.Unmarshal)