github.com/phrase/openapi@v0.0.0-20240514140800-49e8a106740e/openapi-generator/templates/go/response.mustache (about) 1 package {{packageName}} 2 3 import ( 4 "net/http" 5 "net/url" 6 "strconv" 7 "strings" 8 "time" 9 ) 10 11 const ( 12 headerRateLimit = "X-Rate-Limit-Limit" 13 headerRateRemaining = "X-Rate-Limit-Remaining" 14 headerRateReset = "X-Rate-Limit-Reset" 15 ) 16 17 // Timestamp represents a time that can be unmarshalled from a JSON string 18 // formatted as either an RFC3339 or Unix timestamp. This is necessary for some 19 // fields since the GitHub API is inconsistent in how it represents times. All 20 // exported methods of time.Time can be called on Timestamp. 21 type Timestamp struct { 22 time.Time 23 } 24 25 func (t Timestamp) String() string { 26 return t.Time.String() 27 } 28 29 // UnmarshalJSON implements the json.Unmarshaler interface. 30 // Time is expected in RFC3339 or Unix format. 31 func (t *Timestamp) UnmarshalJSON(data []byte) (err error) { 32 str := string(data) 33 i, err := strconv.ParseInt(str, 10, 64) 34 if err == nil { 35 t.Time = time.Unix(i, 0) 36 } else { 37 t.Time, err = time.Parse(`"`+time.RFC3339+`"`, str) 38 } 39 return 40 } 41 42 // Equal reports whether t and u are equal based on time.Equal 43 func (t Timestamp) Equal(u Timestamp) bool { 44 return t.Time.Equal(u.Time) 45 } 46 47 // Rate represents the rate limit for the current client. 48 type Rate struct { 49 // The number of requests per hour the client is currently limited to. 50 Limit int `json:"limit"` 51 52 // The number of remaining requests the client can make this hour. 53 Remaining int `json:"remaining"` 54 55 // The time at which the current rate limit will reset. 56 Reset Timestamp `json:"reset"` 57 } 58 59 // APIResponse stores the API response returned by the server. 60 type APIResponse struct { 61 *http.Response 62 63 // These fields provide the page values for paginating through a set of 64 // results. Any or all of these may be set to the zero value for 65 // responses that are not part of a paginated set, or for which there 66 // are no additional pages. 67 // 68 // These fields support what is called "offset pagination" and should 69 // be used with the ListOptions struct. 70 NextPage int 71 FirstPage int 72 LastPage int 73 74 // Explicitly specify the Rate type so Rate's String() receiver doesn't 75 // propagate to Response. 76 Rate Rate 77 } 78 79 // populatePageValues parses the HTTP Link response headers and populates the 80 // various pagination link values in the Response. 81 func (r *APIResponse) populatePageValues() { 82 if links, ok := r.Response.Header["Link"]; ok && len(links) > 0 { 83 for _, link := range strings.Split(links[0], ",") { 84 segments := strings.Split(strings.TrimSpace(link), ";") 85 86 // link must at least have href and rel 87 if len(segments) < 2 { 88 continue 89 } 90 91 // ensure href is properly formatted 92 if !strings.HasPrefix(segments[0], "<") || !strings.HasSuffix(segments[0], ">") { 93 continue 94 } 95 96 // try to pull out page parameter 97 url, err := url.Parse(segments[0][1 : len(segments[0])-1]) 98 if err != nil { 99 continue 100 } 101 page := url.Query().Get("page") 102 if page == "" { 103 continue 104 } 105 106 for _, segment := range segments[1:] { 107 switch strings.TrimSpace(segment) { 108 case `rel=next`: 109 r.NextPage, _ = strconv.Atoi(page) 110 case `rel=first`: 111 r.FirstPage, _ = strconv.Atoi(page) 112 case `rel=last`: 113 r.LastPage, _ = strconv.Atoi(page) 114 } 115 116 } 117 } 118 } 119 } 120 121 // parseRate parses the rate related headers. 122 func parseRate(r *http.Response) Rate { 123 var rate Rate 124 if limit := r.Header.Get(headerRateLimit); limit != "" { 125 rate.Limit, _ = strconv.Atoi(limit) 126 } 127 if remaining := r.Header.Get(headerRateRemaining); remaining != "" { 128 rate.Remaining, _ = strconv.Atoi(remaining) 129 } 130 if reset := r.Header.Get(headerRateReset); reset != "" { 131 if v, _ := strconv.ParseInt(reset, 10, 64); v != 0 { 132 rate.Reset = Timestamp{time.Unix(v, 0)} 133 } 134 } 135 return rate 136 } 137 138 // newResponse creates a new Response for the provided http.Response. 139 // r must not be nil. 140 func NewAPIResponse(r *http.Response) *APIResponse { 141 response := &APIResponse{Response: r} 142 response.populatePageValues() 143 response.Rate = parseRate(r) 144 return response 145 }