github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/api/handlers/decoder.go (about)

     1  package handlers
     2  
     3  import (
     4  	"encoding/json"
     5  	"reflect"
     6  	"syscall"
     7  	"time"
     8  
     9  	"github.com/hanks177/podman/v4/libpod/define"
    10  	"github.com/hanks177/podman/v4/pkg/util"
    11  	"github.com/gorilla/schema"
    12  	"github.com/sirupsen/logrus"
    13  )
    14  
    15  // NewAPIDecoder returns a configured schema.Decoder
    16  func NewAPIDecoder() *schema.Decoder {
    17  	_ = ParseDateTime
    18  
    19  	d := schema.NewDecoder()
    20  	d.IgnoreUnknownKeys(true)
    21  	d.RegisterConverter(map[string][]string{}, convertURLValuesString)
    22  	d.RegisterConverter(time.Time{}, convertTimeString)
    23  	d.RegisterConverter(define.ContainerStatus(0), convertContainerStatusString)
    24  	d.RegisterConverter(map[string]string{}, convertStringMap)
    25  
    26  	var Signal syscall.Signal
    27  	d.RegisterConverter(Signal, convertSignal)
    28  	return d
    29  }
    30  
    31  // On client:
    32  // 	v := map[string][]string{
    33  //		"dangling": {"true"},
    34  //	}
    35  //
    36  //	payload, err := jsoniter.MarshalToString(v)
    37  //	if err != nil {
    38  //		panic(err)
    39  //	}
    40  //	payload = url.QueryEscape(payload)
    41  func convertURLValuesString(query string) reflect.Value {
    42  	f := map[string][]string{}
    43  
    44  	err := json.Unmarshal([]byte(query), &f)
    45  	if err != nil {
    46  		logrus.Infof("convertURLValuesString: Failed to Unmarshal %s: %s", query, err.Error())
    47  	}
    48  
    49  	return reflect.ValueOf(f)
    50  }
    51  
    52  func convertStringMap(query string) reflect.Value {
    53  	res := make(map[string]string)
    54  	err := json.Unmarshal([]byte(query), &res)
    55  	if err != nil {
    56  		logrus.Infof("convertStringMap: Failed to Unmarshal %s: %s", query, err.Error())
    57  	}
    58  	return reflect.ValueOf(res)
    59  }
    60  
    61  func convertContainerStatusString(query string) reflect.Value {
    62  	result, err := define.StringToContainerStatus(query)
    63  	if err != nil {
    64  		logrus.Infof("convertContainerStatusString: Failed to parse %s: %s", query, err.Error())
    65  
    66  		// We return nil here instead of result because reflect.ValueOf().IsValid() will be true
    67  		// in github.com/gorilla/schema's decoder, which means there's no parsing error
    68  		return reflect.ValueOf(nil)
    69  	}
    70  
    71  	return reflect.ValueOf(result)
    72  }
    73  
    74  // isZero() can be used to determine if parsing failed.
    75  func convertTimeString(query string) reflect.Value {
    76  	var (
    77  		err error
    78  		t   time.Time
    79  	)
    80  
    81  	for _, f := range []string{
    82  		time.UnixDate,
    83  		time.ANSIC,
    84  		time.RFC1123,
    85  		time.RFC1123Z,
    86  		time.RFC3339,
    87  		time.RFC3339Nano,
    88  		time.RFC822,
    89  		time.RFC822Z,
    90  		time.RFC850,
    91  		time.RubyDate,
    92  		time.Stamp,
    93  		time.StampMicro,
    94  		time.StampMilli,
    95  		time.StampNano,
    96  	} {
    97  		t, err = time.Parse(f, query)
    98  		if err == nil {
    99  			return reflect.ValueOf(t)
   100  		}
   101  
   102  		if _, isParseError := err.(*time.ParseError); isParseError {
   103  			// Try next format
   104  			continue
   105  		} else {
   106  			break
   107  		}
   108  	}
   109  
   110  	// We've exhausted all formats, or something bad happened
   111  	if err != nil {
   112  		logrus.Infof("convertTimeString: Failed to parse %s: %s", query, err.Error())
   113  	}
   114  	return reflect.ValueOf(time.Time{})
   115  }
   116  
   117  // ParseDateTime is a helper function to aid in parsing different Time/Date formats
   118  // isZero() can be used to determine if parsing failed.
   119  func ParseDateTime(query string) time.Time {
   120  	return convertTimeString(query).Interface().(time.Time)
   121  }
   122  
   123  func convertSignal(query string) reflect.Value {
   124  	signal, err := util.ParseSignal(query)
   125  	if err != nil {
   126  		logrus.Infof("convertSignal: Failed to parse %s: %s", query, err.Error())
   127  	}
   128  	return reflect.ValueOf(signal)
   129  }