Add dictionary functions, cleanup documentation, and move sub element processing functions to inernal functions.
This commit is contained in:
		
							parent
							
								
									cb4d9a5c2e
								
							
						
					
					
						commit
						5b49d3a340
					
				
							
								
								
									
										14
									
								
								client.go
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								client.go
									
									
									
									
									
								
							@ -13,7 +13,7 @@ import (
 | 
				
			|||||||
	"github.com/jcmturner/gokrb5/v8/spnego"
 | 
						"github.com/jcmturner/gokrb5/v8/spnego"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Client: The base object for connections to FreeIPA API.
 | 
					// The base object for connections to FreeIPA API.
 | 
				
			||||||
type Client struct {
 | 
					type Client struct {
 | 
				
			||||||
	uriBase  string
 | 
						uriBase  string
 | 
				
			||||||
	client   *http.Client
 | 
						client   *http.Client
 | 
				
			||||||
@ -22,7 +22,7 @@ type Client struct {
 | 
				
			|||||||
	krb5     *krb5client.Client
 | 
						krb5     *krb5client.Client
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// init: Common init code for each connection type, mainly sets http.Client and uriBase.
 | 
					// Internal function with common init code for each connection type, mainly sets http.Client and uriBase.
 | 
				
			||||||
func (c *Client) init(host string, transport *http.Transport) error {
 | 
					func (c *Client) init(host string, transport *http.Transport) error {
 | 
				
			||||||
	// Create a cookie jar to store FreeIPA session cookies.
 | 
						// Create a cookie jar to store FreeIPA session cookies.
 | 
				
			||||||
	jar, err := cookiejar.New(&cookiejar.Options{})
 | 
						jar, err := cookiejar.New(&cookiejar.Options{})
 | 
				
			||||||
@ -44,7 +44,7 @@ func (c *Client) init(host string, transport *http.Transport) error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Connect: Make a new client using standard username/password login.
 | 
					// Make a new client and login using standard username/password.
 | 
				
			||||||
func Connect(host string, transport *http.Transport, user, password string) (*Client, error) {
 | 
					func Connect(host string, transport *http.Transport, user, password string) (*Client, error) {
 | 
				
			||||||
	// Make the client config and save credentials.
 | 
						// Make the client config and save credentials.
 | 
				
			||||||
	client := &Client{
 | 
						client := &Client{
 | 
				
			||||||
@ -67,7 +67,7 @@ func Connect(host string, transport *http.Transport, user, password string) (*Cl
 | 
				
			|||||||
	return client, nil
 | 
						return client, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// login: Login using standard credentials.
 | 
					// Login using standard credentials.
 | 
				
			||||||
func (c *Client) login() error {
 | 
					func (c *Client) login() error {
 | 
				
			||||||
	// If login is called, but kerberos client is configured, use kerberos login instead.
 | 
						// If login is called, but kerberos client is configured, use kerberos login instead.
 | 
				
			||||||
	// This allows standard re-authentication calls to work with both kerbeos and standard authenciation.
 | 
						// This allows standard re-authentication calls to work with both kerbeos and standard authenciation.
 | 
				
			||||||
@ -98,7 +98,7 @@ func (c *Client) login() error {
 | 
				
			|||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// KerberosConnectOptions: Options for connecting to Kerberos.
 | 
					// Options for connecting to Kerberos.
 | 
				
			||||||
type KerberosConnectOptions struct {
 | 
					type KerberosConnectOptions struct {
 | 
				
			||||||
	Krb5ConfigReader io.Reader
 | 
						Krb5ConfigReader io.Reader
 | 
				
			||||||
	KeytabReader     io.Reader
 | 
						KeytabReader     io.Reader
 | 
				
			||||||
@ -106,7 +106,7 @@ type KerberosConnectOptions struct {
 | 
				
			|||||||
	Realm            string
 | 
						Realm            string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ConnectWithKerberos: Create a new client using Kerberos authentication.
 | 
					// Create a new client using Kerberos authentication.
 | 
				
			||||||
func ConnectWithKerberos(host string, transport *http.Transport, options *KerberosConnectOptions) (*Client, error) {
 | 
					func ConnectWithKerberos(host string, transport *http.Transport, options *KerberosConnectOptions) (*Client, error) {
 | 
				
			||||||
	// Read the kerberos configuration file for server connection information.
 | 
						// Read the kerberos configuration file for server connection information.
 | 
				
			||||||
	krb5Config, err := krb5config.NewFromReader(options.Krb5ConfigReader)
 | 
						krb5Config, err := krb5config.NewFromReader(options.Krb5ConfigReader)
 | 
				
			||||||
@ -150,7 +150,7 @@ func ConnectWithKerberos(host string, transport *http.Transport, options *Kerber
 | 
				
			|||||||
	return client, nil
 | 
						return client, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// loginWithKerberos: Authenticate using kerberos client.
 | 
					// Login using kerberos client. The regular login function will call this function if needed.
 | 
				
			||||||
func (c *Client) loginWithKerberos() error {
 | 
					func (c *Client) loginWithKerberos() error {
 | 
				
			||||||
	// Wrapper for authenticating with Kerberos credentials.
 | 
						// Wrapper for authenticating with Kerberos credentials.
 | 
				
			||||||
	spnegoCl := spnego.NewClient(c.krb5, c.client, "")
 | 
						spnegoCl := spnego.NewClient(c.krb5, c.client, "")
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@ import (
 | 
				
			|||||||
// Unused port for testing.
 | 
					// Unused port for testing.
 | 
				
			||||||
const httpsPort = 8831
 | 
					const httpsPort = 8831
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// handleLogin: Test login handler.
 | 
					// Test login handler.
 | 
				
			||||||
func handleLogin(w http.ResponseWriter, req *http.Request) {
 | 
					func handleLogin(w http.ResponseWriter, req *http.Request) {
 | 
				
			||||||
	// Logins are form data posts.
 | 
						// Logins are form data posts.
 | 
				
			||||||
	req.ParseForm()
 | 
						req.ParseForm()
 | 
				
			||||||
@ -53,7 +53,7 @@ func handleLogin(w http.ResponseWriter, req *http.Request) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// sendInvalidJSON: General invalid json error response for testing error handling.
 | 
					// General invalid json error response for testing error handling.
 | 
				
			||||||
func sendInvalidJSON(w http.ResponseWriter) {
 | 
					func sendInvalidJSON(w http.ResponseWriter) {
 | 
				
			||||||
	f, err := os.Open("test/invalid_json.json")
 | 
						f, err := os.Open("test/invalid_json.json")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -63,7 +63,7 @@ func sendInvalidJSON(w http.ResponseWriter) {
 | 
				
			|||||||
	io.Copy(w, f)
 | 
						io.Copy(w, f)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// handleJSON: Handle the json session test request.
 | 
					// Handle the json session test request.
 | 
				
			||||||
func handleJSON(w http.ResponseWriter, req *http.Request) {
 | 
					func handleJSON(w http.ResponseWriter, req *http.Request) {
 | 
				
			||||||
	// If session cookie doesn't exist, something is wrong. Send unauthenticated response.
 | 
						// If session cookie doesn't exist, something is wrong. Send unauthenticated response.
 | 
				
			||||||
	cookie, err := req.Cookie("ipa_session")
 | 
						cookie, err := req.Cookie("ipa_session")
 | 
				
			||||||
@ -107,7 +107,7 @@ func handleJSON(w http.ResponseWriter, req *http.Request) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TestLogin: General library tests with test server.
 | 
					// General library tests with test server.
 | 
				
			||||||
func TestLogin(t *testing.T) {
 | 
					func TestLogin(t *testing.T) {
 | 
				
			||||||
	// Spin up test server using port specified above.
 | 
						// Spin up test server using port specified above.
 | 
				
			||||||
	srvAddr := fmt.Sprintf("127.0.0.1:%d", httpsPort)
 | 
						srvAddr := fmt.Sprintf("127.0.0.1:%d", httpsPort)
 | 
				
			||||||
 | 
				
			|||||||
@ -140,7 +140,7 @@ const (
 | 
				
			|||||||
	rejectionReasonHTTPHeader                = "X-Ipa-Rejection-Reason"
 | 
						rejectionReasonHTTPHeader                = "X-Ipa-Rejection-Reason"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// unauthorizedHTTPError: Add information from the rejection reason header to unauthorized error.
 | 
					// Add information from the rejection reason header to unauthorized error.
 | 
				
			||||||
func unauthorizedHTTPError(resp *http.Response) error {
 | 
					func unauthorizedHTTPError(resp *http.Response) error {
 | 
				
			||||||
	var errorCode int
 | 
						var errorCode int
 | 
				
			||||||
	rejectionReason := resp.Header.Get(rejectionReasonHTTPHeader)
 | 
						rejectionReason := resp.Header.Get(rejectionReasonHTTPHeader)
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,7 @@ type Request struct {
 | 
				
			|||||||
	Params []interface{} `json:"params"`
 | 
						Params []interface{} `json:"params"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewRequest: Create a new request providing method, args, and parameters.
 | 
					// Create a new API request.
 | 
				
			||||||
func NewRequest(method string, args []interface{}, parms map[string]interface{}) *Request {
 | 
					func NewRequest(method string, args []interface{}, parms map[string]interface{}) *Request {
 | 
				
			||||||
	// Add API version to the parameters.
 | 
						// Add API version to the parameters.
 | 
				
			||||||
	parms["version"] = apiVersion
 | 
						parms["version"] = apiVersion
 | 
				
			||||||
@ -34,7 +34,7 @@ func NewRequest(method string, args []interface{}, parms map[string]interface{})
 | 
				
			|||||||
	return req
 | 
						return req
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Do: Have the client do the request.
 | 
					// Have the client perform the request.
 | 
				
			||||||
func (c *Client) Do(req *Request) (*Response, error) {
 | 
					func (c *Client) Do(req *Request) (*Response, error) {
 | 
				
			||||||
	// Send request.
 | 
						// Send request.
 | 
				
			||||||
	res, err := c.sendRequest(req)
 | 
						res, err := c.sendRequest(req)
 | 
				
			||||||
@ -67,7 +67,7 @@ func (c *Client) Do(req *Request) (*Response, error) {
 | 
				
			|||||||
	return ParseResponse(res.Body)
 | 
						return ParseResponse(res.Body)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// sendRequest: Encode and send the request to the session.
 | 
					// Encode and send the request to the session.
 | 
				
			||||||
func (c *Client) sendRequest(request *Request) (*http.Response, error) {
 | 
					func (c *Client) sendRequest(request *Request) (*http.Response, error) {
 | 
				
			||||||
	// Encode to JSON.
 | 
						// Encode to JSON.
 | 
				
			||||||
	data, err := json.Marshal(request)
 | 
						data, err := json.Marshal(request)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										145
									
								
								response.go
									
									
									
									
									
								
							
							
						
						
									
										145
									
								
								response.go
									
									
									
									
									
								
							@ -12,7 +12,7 @@ import (
 | 
				
			|||||||
// https://github.com/freeipa/freeipa/blob/ipa-4-7/ipalib/constants.py#L271
 | 
					// https://github.com/freeipa/freeipa/blob/ipa-4-7/ipalib/constants.py#L271
 | 
				
			||||||
const LDAPGeneralizedTimeFormat = "20060102150405Z"
 | 
					const LDAPGeneralizedTimeFormat = "20060102150405Z"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Message: Used in providing extra messages and error response.
 | 
					// Used in providing extra messages and error response.
 | 
				
			||||||
type Message struct {
 | 
					type Message struct {
 | 
				
			||||||
	Type    string `json:"type"`
 | 
						Type    string `json:"type"`
 | 
				
			||||||
	Message string `json:"message"`
 | 
						Message string `json:"message"`
 | 
				
			||||||
@ -20,12 +20,12 @@ type Message struct {
 | 
				
			|||||||
	Name    string `json:"name"`
 | 
						Name    string `json:"name"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// string: Convert the message into a combind string.
 | 
					// Convert the message into a combind string.
 | 
				
			||||||
func (t *Message) string() string {
 | 
					func (t *Message) string() string {
 | 
				
			||||||
	return fmt.Sprintf("%v (%v): %v", t.Name, t.Code, t.Message)
 | 
						return fmt.Sprintf("%v (%v): %v", t.Name, t.Code, t.Message)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Result: Standard result in response from FreeIPA.
 | 
					// Standard result in response from FreeIPA.
 | 
				
			||||||
type Result struct {
 | 
					type Result struct {
 | 
				
			||||||
	Count     int        `json:"count"`
 | 
						Count     int        `json:"count"`
 | 
				
			||||||
	Truncated bool       `json:"truncated"`
 | 
						Truncated bool       `json:"truncated"`
 | 
				
			||||||
@ -38,7 +38,7 @@ type Result struct {
 | 
				
			|||||||
	Value   string      `json:"value,omitempty"`
 | 
						Value   string      `json:"value,omitempty"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Response: Standard response from FreeIPA.
 | 
					// Standard response from FreeIPA.
 | 
				
			||||||
type Response struct {
 | 
					type Response struct {
 | 
				
			||||||
	Error     *Message `json:"error"`
 | 
						Error     *Message `json:"error"`
 | 
				
			||||||
	Result    *Result  `json:"result"`
 | 
						Result    *Result  `json:"result"`
 | 
				
			||||||
@ -46,7 +46,7 @@ type Response struct {
 | 
				
			|||||||
	Principal string   `json:"principal"`
 | 
						Principal string   `json:"principal"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ParseResponse: Parse response from reader.
 | 
					// Parse response from reader.
 | 
				
			||||||
func ParseResponse(body io.Reader) (*Response, error) {
 | 
					func ParseResponse(body io.Reader) (*Response, error) {
 | 
				
			||||||
	// Decode JSON response.
 | 
						// Decode JSON response.
 | 
				
			||||||
	res := new(Response)
 | 
						res := new(Response)
 | 
				
			||||||
@ -66,7 +66,7 @@ func ParseResponse(body io.Reader) (*Response, error) {
 | 
				
			|||||||
	return res, nil
 | 
						return res, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// BoolResult: Decode results which are boolean formatted, usually used to indicate success or state.
 | 
					// Decode results which are boolean formatted, usually used to indicate success or state.
 | 
				
			||||||
func (r *Response) BoolResult() bool {
 | 
					func (r *Response) BoolResult() bool {
 | 
				
			||||||
	if r.Result == nil {
 | 
						if r.Result == nil {
 | 
				
			||||||
		return false
 | 
							return false
 | 
				
			||||||
@ -78,6 +78,7 @@ func (r *Response) BoolResult() bool {
 | 
				
			|||||||
	return v
 | 
						return v
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Count the number of results that this request has.
 | 
				
			||||||
func (r *Response) CountResults() int {
 | 
					func (r *Response) CountResults() int {
 | 
				
			||||||
	if r.Result == nil {
 | 
						if r.Result == nil {
 | 
				
			||||||
		return -1
 | 
							return -1
 | 
				
			||||||
@ -89,8 +90,8 @@ func (r *Response) CountResults() int {
 | 
				
			|||||||
	return len(a)
 | 
						return len(a)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetAtIndex: Get an interface for a key.
 | 
					// Return dictionary at index.
 | 
				
			||||||
func (r *Response) GetAtIndex(index int, key string) ([]interface{}, bool) {
 | 
					func (r *Response) DictAtIndex(index int) (map[string]interface{}, bool) {
 | 
				
			||||||
	if r.Result == nil {
 | 
						if r.Result == nil {
 | 
				
			||||||
		return nil, false
 | 
							return nil, false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -104,27 +105,21 @@ func (r *Response) GetAtIndex(index int, key string) ([]interface{}, bool) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	d := a[index]
 | 
						d := a[index]
 | 
				
			||||||
	dict, ok := d.(map[string]interface{})
 | 
						dict, ok := d.(map[string]interface{})
 | 
				
			||||||
	if !ok {
 | 
						return dict, ok
 | 
				
			||||||
		return nil, false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	v, ok := dict[key]
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		return nil, false
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	a, ok = v.([]interface{})
 | 
					 | 
				
			||||||
	if !ok {
 | 
					 | 
				
			||||||
		// Apparently FreeIPA sometimes returns a string outside of an array, so this catches that.
 | 
					 | 
				
			||||||
		return []interface{}{v}, true
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return a, true
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Get: Get an interface for a key.
 | 
					// Return dictionary.
 | 
				
			||||||
func (r *Response) Get(key string) ([]interface{}, bool) {
 | 
					func (r *Response) Dict() (map[string]interface{}, bool) {
 | 
				
			||||||
	if r.Result == nil {
 | 
						if r.Result == nil {
 | 
				
			||||||
		return nil, false
 | 
							return nil, false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	dict, ok := r.Result.Result.(map[string]interface{})
 | 
						dict, ok := r.Result.Result.(map[string]interface{})
 | 
				
			||||||
 | 
						return dict, ok
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Get an interface for a key.
 | 
				
			||||||
 | 
					func (r *Response) GetAtIndex(index int, key string) ([]interface{}, bool) {
 | 
				
			||||||
 | 
						dict, ok := r.DictAtIndex(index)
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		return nil, false
 | 
							return nil, false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -140,8 +135,52 @@ func (r *Response) Get(key string) ([]interface{}, bool) {
 | 
				
			|||||||
	return a, true
 | 
						return a, true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetBoolProcess: Process bool element.
 | 
					// Get an interface for a key.
 | 
				
			||||||
func (r *Response) GetBoolProcess(v interface{}) (bool, bool) {
 | 
					func (r *Response) Get(key string) ([]interface{}, bool) {
 | 
				
			||||||
 | 
						dict, ok := r.Dict()
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return nil, false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						v, ok := dict[key]
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return nil, false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						a, ok := v.([]interface{})
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							// Apparently FreeIPA sometimes returns a string outside of an array, so this catches that.
 | 
				
			||||||
 | 
							return []interface{}{v}, true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return a, true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Get all keys at index.
 | 
				
			||||||
 | 
					func (r *Response) KeysAtIndex(index int) ([]string, bool) {
 | 
				
			||||||
 | 
						var res []string
 | 
				
			||||||
 | 
						dict, ok := r.DictAtIndex(index)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return res, false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for k := range dict {
 | 
				
			||||||
 | 
							res = append(res, k)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return res, true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Get all keys.
 | 
				
			||||||
 | 
					func (r *Response) Keys() ([]string, bool) {
 | 
				
			||||||
 | 
						var res []string
 | 
				
			||||||
 | 
						dict, ok := r.Dict()
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							return res, false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for k := range dict {
 | 
				
			||||||
 | 
							res = append(res, k)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return res, true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Process sub element with bool.
 | 
				
			||||||
 | 
					func (r *Response) processBool(v interface{}) (bool, bool) {
 | 
				
			||||||
	a, ok := v.(bool)
 | 
						a, ok := v.(bool)
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		return false, false
 | 
							return false, false
 | 
				
			||||||
@ -149,26 +188,26 @@ func (r *Response) GetBoolProcess(v interface{}) (bool, bool) {
 | 
				
			|||||||
	return a, true
 | 
						return a, true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetBoolAtIndex: Get a boolean from a key at an index.
 | 
					// Get a boolean from a key at an index.
 | 
				
			||||||
func (r *Response) GetBoolAtIndex(index int, key string) (bool, bool) {
 | 
					func (r *Response) GetBoolAtIndex(index int, key string) (bool, bool) {
 | 
				
			||||||
	v, ok := r.GetAtIndex(index, key)
 | 
						v, ok := r.GetAtIndex(index, key)
 | 
				
			||||||
	if !ok || len(v) < 1 {
 | 
						if !ok || len(v) < 1 {
 | 
				
			||||||
		return false, false
 | 
							return false, false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return r.GetBoolProcess(v[0])
 | 
						return r.processBool(v[0])
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetBool: Get a boolean from a key.
 | 
					// Get a boolean from a key.
 | 
				
			||||||
func (r *Response) GetBool(key string) (bool, bool) {
 | 
					func (r *Response) GetBool(key string) (bool, bool) {
 | 
				
			||||||
	v, ok := r.Get(key)
 | 
						v, ok := r.Get(key)
 | 
				
			||||||
	if !ok || len(v) < 1 {
 | 
						if !ok || len(v) < 1 {
 | 
				
			||||||
		return false, false
 | 
							return false, false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return r.GetBoolProcess(v[0])
 | 
						return r.processBool(v[0])
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetStringProcess: Process sub element with string.
 | 
					// Process sub element with string.
 | 
				
			||||||
func (r *Response) GetStringProcess(v []interface{}) ([]string, bool) {
 | 
					func (r *Response) processString(v []interface{}) ([]string, bool) {
 | 
				
			||||||
	var res []string
 | 
						var res []string
 | 
				
			||||||
	for _, p := range v {
 | 
						for _, p := range v {
 | 
				
			||||||
		s, ok := p.(string)
 | 
							s, ok := p.(string)
 | 
				
			||||||
@ -180,25 +219,25 @@ func (r *Response) GetStringProcess(v []interface{}) ([]string, bool) {
 | 
				
			|||||||
	return res, true
 | 
						return res, true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetStringsAtIndex: Get string value for key at an index.
 | 
					// Get string value for key at an index.
 | 
				
			||||||
func (r *Response) GetStringsAtIndex(index int, key string) ([]string, bool) {
 | 
					func (r *Response) GetStringsAtIndex(index int, key string) ([]string, bool) {
 | 
				
			||||||
	v, ok := r.GetAtIndex(index, key)
 | 
						v, ok := r.GetAtIndex(index, key)
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		return []string{}, false
 | 
							return []string{}, false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return r.GetStringProcess(v)
 | 
						return r.processString(v)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetStrings: Get string value for key.
 | 
					// Get string value for key.
 | 
				
			||||||
func (r *Response) GetStrings(key string) ([]string, bool) {
 | 
					func (r *Response) GetStrings(key string) ([]string, bool) {
 | 
				
			||||||
	v, ok := r.Get(key)
 | 
						v, ok := r.Get(key)
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		return []string{}, false
 | 
							return []string{}, false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return r.GetStringProcess(v)
 | 
						return r.processString(v)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetStringAtIndex: Get string value for key at an index.
 | 
					// Get string value for key at an index.
 | 
				
			||||||
func (r *Response) GetStringAtIndex(index int, key string) (string, bool) {
 | 
					func (r *Response) GetStringAtIndex(index int, key string) (string, bool) {
 | 
				
			||||||
	v, ok := r.GetStringsAtIndex(index, key)
 | 
						v, ok := r.GetStringsAtIndex(index, key)
 | 
				
			||||||
	if !ok || len(v) < 1 {
 | 
						if !ok || len(v) < 1 {
 | 
				
			||||||
@ -207,7 +246,7 @@ func (r *Response) GetStringAtIndex(index int, key string) (string, bool) {
 | 
				
			|||||||
	return v[0], true
 | 
						return v[0], true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetString: Get string value for key.
 | 
					// Get string value for key.
 | 
				
			||||||
func (r *Response) GetString(key string) (string, bool) {
 | 
					func (r *Response) GetString(key string) (string, bool) {
 | 
				
			||||||
	v, ok := r.GetStrings(key)
 | 
						v, ok := r.GetStrings(key)
 | 
				
			||||||
	if !ok || len(v) < 1 {
 | 
						if !ok || len(v) < 1 {
 | 
				
			||||||
@ -216,8 +255,8 @@ func (r *Response) GetString(key string) (string, bool) {
 | 
				
			|||||||
	return v[0], true
 | 
						return v[0], true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetDataProcess: Process a sub element with bytes.
 | 
					// Process sub element with bytes.
 | 
				
			||||||
func (r *Response) GetDataProcess(v []interface{}) ([][]byte, bool) {
 | 
					func (r *Response) processData(v []interface{}) ([][]byte, bool) {
 | 
				
			||||||
	var res [][]byte
 | 
						var res [][]byte
 | 
				
			||||||
	for _, p := range v {
 | 
						for _, p := range v {
 | 
				
			||||||
		var bytes []byte
 | 
							var bytes []byte
 | 
				
			||||||
@ -242,25 +281,25 @@ func (r *Response) GetDataProcess(v []interface{}) ([][]byte, bool) {
 | 
				
			|||||||
	return res, true
 | 
						return res, true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetDatasAtIndex: Get byte array for key at an index.
 | 
					// Get byte array for key at an index.
 | 
				
			||||||
func (r *Response) GetDatasAtIndex(index int, key string) ([][]byte, bool) {
 | 
					func (r *Response) GetDatasAtIndex(index int, key string) ([][]byte, bool) {
 | 
				
			||||||
	v, ok := r.GetAtIndex(index, key)
 | 
						v, ok := r.GetAtIndex(index, key)
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		return [][]byte{}, false
 | 
							return [][]byte{}, false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return r.GetDataProcess(v)
 | 
						return r.processData(v)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetDatas: Get byte array for key.
 | 
					// Get byte array for key.
 | 
				
			||||||
func (r *Response) GetDatas(key string) ([][]byte, bool) {
 | 
					func (r *Response) GetDatas(key string) ([][]byte, bool) {
 | 
				
			||||||
	v, ok := r.Get(key)
 | 
						v, ok := r.Get(key)
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		return [][]byte{}, false
 | 
							return [][]byte{}, false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return r.GetDataProcess(v)
 | 
						return r.processData(v)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetDataAtIndex: Get byte array for key at an index.
 | 
					// Get byte array for key at an index.
 | 
				
			||||||
func (r *Response) GetDataAtIndex(index int, key string) ([]byte, bool) {
 | 
					func (r *Response) GetDataAtIndex(index int, key string) ([]byte, bool) {
 | 
				
			||||||
	v, ok := r.GetDatasAtIndex(index, key)
 | 
						v, ok := r.GetDatasAtIndex(index, key)
 | 
				
			||||||
	if !ok || len(v) < 1 {
 | 
						if !ok || len(v) < 1 {
 | 
				
			||||||
@ -269,7 +308,7 @@ func (r *Response) GetDataAtIndex(index int, key string) ([]byte, bool) {
 | 
				
			|||||||
	return v[0], true
 | 
						return v[0], true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetData: Get byte array for key.
 | 
					// Get byte array for key.
 | 
				
			||||||
func (r *Response) GetData(key string) ([]byte, bool) {
 | 
					func (r *Response) GetData(key string) ([]byte, bool) {
 | 
				
			||||||
	v, ok := r.GetDatas(key)
 | 
						v, ok := r.GetDatas(key)
 | 
				
			||||||
	if !ok || len(v) < 1 {
 | 
						if !ok || len(v) < 1 {
 | 
				
			||||||
@ -278,8 +317,8 @@ func (r *Response) GetData(key string) ([]byte, bool) {
 | 
				
			|||||||
	return v[0], true
 | 
						return v[0], true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetDateTimeProcess: Process a sub element with a date/time value.
 | 
					// Process sub element with a date/time value.
 | 
				
			||||||
func (r *Response) GetDateTimeProcess(v []interface{}) ([]time.Time, bool) {
 | 
					func (r *Response) processDateTime(v []interface{}) ([]time.Time, bool) {
 | 
				
			||||||
	var res []time.Time
 | 
						var res []time.Time
 | 
				
			||||||
	for _, p := range v {
 | 
						for _, p := range v {
 | 
				
			||||||
		dict, ok := p.(map[string]interface{})
 | 
							dict, ok := p.(map[string]interface{})
 | 
				
			||||||
@ -303,25 +342,25 @@ func (r *Response) GetDateTimeProcess(v []interface{}) ([]time.Time, bool) {
 | 
				
			|||||||
	return res, true
 | 
						return res, true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetDateTimesAtIndex: Get date time value for key at an index.
 | 
					// Get date time value for key at an index.
 | 
				
			||||||
func (r *Response) GetDateTimesAtIndex(index int, key string) ([]time.Time, bool) {
 | 
					func (r *Response) GetDateTimesAtIndex(index int, key string) ([]time.Time, bool) {
 | 
				
			||||||
	v, ok := r.GetAtIndex(index, key)
 | 
						v, ok := r.GetAtIndex(index, key)
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		return []time.Time{}, false
 | 
							return []time.Time{}, false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return r.GetDateTimeProcess(v)
 | 
						return r.processDateTime(v)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetDateTimes: Get date time value for key.
 | 
					// Get date time value for key.
 | 
				
			||||||
func (r *Response) GetDateTimes(key string) ([]time.Time, bool) {
 | 
					func (r *Response) GetDateTimes(key string) ([]time.Time, bool) {
 | 
				
			||||||
	v, ok := r.Get(key)
 | 
						v, ok := r.Get(key)
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		return []time.Time{}, false
 | 
							return []time.Time{}, false
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return r.GetDateTimeProcess(v)
 | 
						return r.processDateTime(v)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetDateTimeAtIndex: Get date time value for key at an index.
 | 
					// Get date time value for key at an index.
 | 
				
			||||||
func (r *Response) GetDateTimeAtIndex(index int, key string) (time.Time, bool) {
 | 
					func (r *Response) GetDateTimeAtIndex(index int, key string) (time.Time, bool) {
 | 
				
			||||||
	v, ok := r.GetDateTimesAtIndex(index, key)
 | 
						v, ok := r.GetDateTimesAtIndex(index, key)
 | 
				
			||||||
	if !ok || len(v) < 1 {
 | 
						if !ok || len(v) < 1 {
 | 
				
			||||||
@ -330,7 +369,7 @@ func (r *Response) GetDateTimeAtIndex(index int, key string) (time.Time, bool) {
 | 
				
			|||||||
	return v[0], true
 | 
						return v[0], true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetDateTime: Get date time value for key.
 | 
					// Get date time value for key.
 | 
				
			||||||
func (r *Response) GetDateTime(key string) (time.Time, bool) {
 | 
					func (r *Response) GetDateTime(key string) (time.Time, bool) {
 | 
				
			||||||
	v, ok := r.GetDateTimes(key)
 | 
						v, ok := r.GetDateTimes(key)
 | 
				
			||||||
	if !ok || len(v) < 1 {
 | 
						if !ok || len(v) < 1 {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user