github.com/go-swagger/go-swagger@v0.31.0/generator/media.go (about)

     1  package generator
     2  
     3  import (
     4  	"regexp"
     5  	"sort"
     6  	"strings"
     7  
     8  	"github.com/go-openapi/runtime"
     9  	"github.com/go-openapi/swag"
    10  )
    11  
    12  const jsonSerializer = "json"
    13  
    14  var mediaTypeNames = map[*regexp.Regexp]string{
    15  	regexp.MustCompile("application/.*json"):                jsonSerializer,
    16  	regexp.MustCompile("application/.*yaml"):                "yaml",
    17  	regexp.MustCompile("application/.*protobuf"):            "protobuf",
    18  	regexp.MustCompile("application/.*capnproto"):           "capnproto",
    19  	regexp.MustCompile("application/.*thrift"):              "thrift",
    20  	regexp.MustCompile("(?:application|text)/.*xml"):        "xml",
    21  	regexp.MustCompile("text/.*markdown"):                   "markdown",
    22  	regexp.MustCompile("text/.*html"):                       "html",
    23  	regexp.MustCompile("text/.*csv"):                        "csv",
    24  	regexp.MustCompile("text/.*tsv"):                        "tsv",
    25  	regexp.MustCompile("text/.*javascript"):                 "js",
    26  	regexp.MustCompile("text/.*css"):                        "css",
    27  	regexp.MustCompile("text/.*plain"):                      "txt",
    28  	regexp.MustCompile("application/.*octet-stream"):        "bin",
    29  	regexp.MustCompile("application/.*tar"):                 "tar",
    30  	regexp.MustCompile("application/.*gzip"):                "gzip",
    31  	regexp.MustCompile("application/.*gz"):                  "gzip",
    32  	regexp.MustCompile("application/.*raw-stream"):          "bin",
    33  	regexp.MustCompile("application/x-www-form-urlencoded"): "urlform",
    34  	regexp.MustCompile("application/javascript"):            "txt",
    35  	regexp.MustCompile("multipart/form-data"):               "multipartform",
    36  	regexp.MustCompile("image/.*"):                          "bin",
    37  	regexp.MustCompile("audio/.*"):                          "bin",
    38  	regexp.MustCompile("application/pdf"):                   "bin",
    39  }
    40  
    41  var knownProducers = map[string]string{
    42  	jsonSerializer:  "runtime.JSONProducer()",
    43  	"yaml":          "yamlpc.YAMLProducer()",
    44  	"xml":           "runtime.XMLProducer()",
    45  	"txt":           "runtime.TextProducer()",
    46  	"bin":           "runtime.ByteStreamProducer()",
    47  	"urlform":       "runtime.DiscardProducer",
    48  	"multipartform": "runtime.DiscardProducer",
    49  }
    50  
    51  var knownConsumers = map[string]string{
    52  	jsonSerializer:  "runtime.JSONConsumer()",
    53  	"yaml":          "yamlpc.YAMLConsumer()",
    54  	"xml":           "runtime.XMLConsumer()",
    55  	"txt":           "runtime.TextConsumer()",
    56  	"bin":           "runtime.ByteStreamConsumer()",
    57  	"urlform":       "runtime.DiscardConsumer",
    58  	"multipartform": "runtime.DiscardConsumer",
    59  }
    60  
    61  func wellKnownMime(tn string) (string, bool) {
    62  	for k, v := range mediaTypeNames {
    63  		if k.MatchString(tn) {
    64  			return v, true
    65  		}
    66  	}
    67  	return "", false
    68  }
    69  
    70  func mediaMime(orig string) string {
    71  	return strings.SplitN(orig, ";", 2)[0]
    72  }
    73  
    74  func mediaGoName(media string) string {
    75  	return pascalize(strings.ReplaceAll(media, "*", "Star"))
    76  }
    77  
    78  func mediaParameters(orig string) string {
    79  	parts := strings.SplitN(orig, ";", 2)
    80  	if len(parts) < 2 {
    81  		return ""
    82  	}
    83  	return parts[1]
    84  }
    85  
    86  func (a *appGenerator) makeSerializers(mediaTypes []string, known func(string) (string, bool)) (GenSerGroups, bool) {
    87  	supportsJSON := false
    88  	uniqueSerializers := make(map[string]*GenSerializer, len(mediaTypes))
    89  	uniqueSerializerGroups := make(map[string]*GenSerGroup, len(mediaTypes))
    90  
    91  	// build all required serializers
    92  	for _, media := range mediaTypes {
    93  		key := mediaMime(media)
    94  		nm, ok := wellKnownMime(key)
    95  		if !ok {
    96  			// keep this serializer named, even though its implementation is empty (cf. #1557)
    97  			nm = key
    98  		}
    99  		name := swag.ToJSONName(nm)
   100  		impl, _ := known(name)
   101  
   102  		ser, ok := uniqueSerializers[key]
   103  		if !ok {
   104  			ser = &GenSerializer{
   105  				AppName:        a.Name,
   106  				ReceiverName:   a.Receiver,
   107  				Name:           name,
   108  				MediaType:      key,
   109  				Implementation: impl,
   110  				Parameters:     []string{},
   111  			}
   112  			uniqueSerializers[key] = ser
   113  		}
   114  		// provide all known parameters (currently unused by codegen templates)
   115  		if params := strings.TrimSpace(mediaParameters(media)); params != "" {
   116  			found := false
   117  			for _, p := range ser.Parameters {
   118  				if params == p {
   119  					found = true
   120  					break
   121  				}
   122  			}
   123  			if !found {
   124  				ser.Parameters = append(ser.Parameters, params)
   125  			}
   126  		}
   127  
   128  		uniqueSerializerGroups[name] = &GenSerGroup{
   129  			GenSerializer: GenSerializer{
   130  				AppName:        a.Name,
   131  				ReceiverName:   a.Receiver,
   132  				Name:           name,
   133  				Implementation: impl,
   134  			},
   135  		}
   136  	}
   137  
   138  	if len(uniqueSerializers) == 0 {
   139  		impl, _ := known(jsonSerializer)
   140  		uniqueSerializers[runtime.JSONMime] = &GenSerializer{
   141  			AppName:        a.Name,
   142  			ReceiverName:   a.Receiver,
   143  			Name:           jsonSerializer,
   144  			MediaType:      runtime.JSONMime,
   145  			Implementation: impl,
   146  			Parameters:     []string{},
   147  		}
   148  		uniqueSerializerGroups[jsonSerializer] = &GenSerGroup{
   149  			GenSerializer: GenSerializer{
   150  				AppName:        a.Name,
   151  				ReceiverName:   a.Receiver,
   152  				Name:           jsonSerializer,
   153  				Implementation: impl,
   154  			},
   155  		}
   156  		supportsJSON = true
   157  	}
   158  
   159  	// group serializers by consumer/producer to serve several mime media types
   160  	serializerGroups := make(GenSerGroups, 0, len(uniqueSerializers))
   161  
   162  	for _, group := range uniqueSerializerGroups {
   163  		if group.Name == jsonSerializer {
   164  			supportsJSON = true
   165  		}
   166  		serializers := make(GenSerializers, 0, len(uniqueSerializers))
   167  		for _, ser := range uniqueSerializers {
   168  			if group.Name == ser.Name {
   169  				sort.Strings(ser.Parameters)
   170  				serializers = append(serializers, *ser)
   171  			}
   172  		}
   173  		sort.Sort(serializers)
   174  		group.AllSerializers = serializers // provides the full list of mime media types for this serializer group
   175  		serializerGroups = append(serializerGroups, *group)
   176  	}
   177  	sort.Sort(serializerGroups)
   178  	return serializerGroups, supportsJSON
   179  }
   180  
   181  func (a *appGenerator) makeConsumes() (GenSerGroups, bool) {
   182  	// builds a codegen struct from all consumes in the spec
   183  	return a.makeSerializers(a.Analyzed.RequiredConsumes(), func(media string) (string, bool) {
   184  		c, ok := knownConsumers[media]
   185  		return c, ok
   186  	})
   187  }
   188  
   189  func (a *appGenerator) makeProduces() (GenSerGroups, bool) {
   190  	// builds a codegen struct from all produces in the spec
   191  	return a.makeSerializers(a.Analyzed.RequiredProduces(), func(media string) (string, bool) {
   192  		p, ok := knownProducers[media]
   193  		return p, ok
   194  	})
   195  }