github.com/ManabuSeki/goa-v1@v1.4.3/goagen/gen_app/writers.go (about)

     1  package genapp
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"regexp"
     7  	"strings"
     8  	"text/template"
     9  
    10  	"sort"
    11  
    12  	"github.com/goadesign/goa/design"
    13  	"github.com/goadesign/goa/goagen/codegen"
    14  )
    15  
    16  // WildcardRegex is the regex used to capture path parameters.
    17  var WildcardRegex = regexp.MustCompile("(?:[^/]*/:([^/]+))+")
    18  
    19  type (
    20  	// ContextsWriter generate codes for a goa application contexts.
    21  	ContextsWriter struct {
    22  		*codegen.SourceFile
    23  		CtxTmpl     *template.Template
    24  		CtxNewTmpl  *template.Template
    25  		CtxRespTmpl *template.Template
    26  		PayloadTmpl *template.Template
    27  		Finalizer   *codegen.Finalizer
    28  		Validator   *codegen.Validator
    29  	}
    30  
    31  	// ControllersWriter generate code for a goa application handlers.
    32  	// Handlers receive a HTTP request, create the action context, call the action code and send the
    33  	// resulting HTTP response.
    34  	ControllersWriter struct {
    35  		*codegen.SourceFile
    36  		CtrlTmpl    *template.Template
    37  		MountTmpl   *template.Template
    38  		handleCORST *template.Template
    39  		Finalizer   *codegen.Finalizer
    40  		Validator   *codegen.Validator
    41  	}
    42  
    43  	// SecurityWriter generate code for action-level security handlers.
    44  	SecurityWriter struct {
    45  		*codegen.SourceFile
    46  		SecurityTmpl *template.Template
    47  	}
    48  
    49  	// ResourcesWriter generate code for a goa application resources.
    50  	// Resources are data structures initialized by the application handlers and passed to controller
    51  	// actions.
    52  	ResourcesWriter struct {
    53  		*codegen.SourceFile
    54  		ResourceTmpl *template.Template
    55  	}
    56  
    57  	// MediaTypesWriter generate code for a goa application media types.
    58  	// Media types are data structures used to render the response bodies.
    59  	MediaTypesWriter struct {
    60  		*codegen.SourceFile
    61  		MediaTypeTmpl *template.Template
    62  		Validator     *codegen.Validator
    63  	}
    64  
    65  	// UserTypesWriter generate code for a goa application user types.
    66  	// User types are data structures defined in the DSL with "Type".
    67  	UserTypesWriter struct {
    68  		*codegen.SourceFile
    69  		UserTypeTmpl *template.Template
    70  		Finalizer    *codegen.Finalizer
    71  		Validator    *codegen.Validator
    72  	}
    73  
    74  	// ContextTemplateData contains all the information used by the template to render the context
    75  	// code for an action.
    76  	ContextTemplateData struct {
    77  		Name         string // e.g. "ListBottleContext"
    78  		ResourceName string // e.g. "bottles"
    79  		ActionName   string // e.g. "list"
    80  		Params       *design.AttributeDefinition
    81  		Payload      *design.UserTypeDefinition
    82  		Headers      *design.AttributeDefinition
    83  		Routes       []*design.RouteDefinition
    84  		Responses    map[string]*design.ResponseDefinition
    85  		API          *design.APIDefinition
    86  		DefaultPkg   string
    87  		Security     *design.SecurityDefinition
    88  	}
    89  
    90  	// ControllerTemplateData contains the information required to generate an action handler.
    91  	ControllerTemplateData struct {
    92  		API            *design.APIDefinition          // API definition
    93  		Resource       string                         // Lower case plural resource name, e.g. "bottles"
    94  		Actions        []map[string]interface{}       // Array of actions, each action has keys "Name", "DesignName", "Routes", "Context" and "Unmarshal"
    95  		FileServers    []*design.FileServerDefinition // File servers
    96  		Encoders       []*EncoderTemplateData         // Encoder data
    97  		Decoders       []*EncoderTemplateData         // Decoder data
    98  		Origins        []*design.CORSDefinition       // CORS policies
    99  		PreflightPaths []string
   100  	}
   101  
   102  	// ResourceData contains the information required to generate the resource GoGenerator
   103  	ResourceData struct {
   104  		Name              string                      // Name of resource
   105  		Identifier        string                      // Identifier of resource media type
   106  		Description       string                      // Description of resource
   107  		Type              *design.MediaTypeDefinition // Type of resource media type
   108  		CanonicalTemplate string                      // CanonicalFormat represents the resource canonical path in the form of a fmt.Sprintf format.
   109  		CanonicalParams   []string                    // CanonicalParams is the list of parameter names that appear in the resource canonical path in order.
   110  	}
   111  
   112  	// EncoderTemplateData contains the data needed to render the registration code for a single
   113  	// encoder or decoder package.
   114  	EncoderTemplateData struct {
   115  		// PackagePath is the Go package path to the package implmenting the encoder/decoder.
   116  		PackagePath string
   117  		// PackageName is the name of the Go package implementing the encoder/decoder.
   118  		PackageName string
   119  		// Function is the name of the package function implementing the decoder/encoder factory.
   120  		Function string
   121  		// MIMETypes is the list of supported MIME types.
   122  		MIMETypes []string
   123  		// Default is true if this encoder/decoder should be set as the default.
   124  		Default bool
   125  	}
   126  )
   127  
   128  // IsPathParam returns true if the given parameter name corresponds to a path parameter for all
   129  // the context action routes. Such parameter is required but does not need to be validated as
   130  // httptreemux takes care of that.
   131  func (c *ContextTemplateData) IsPathParam(param string) bool {
   132  	params := c.Params
   133  	pp := false
   134  	if params.Type.IsObject() {
   135  		for _, r := range c.Routes {
   136  			pp = false
   137  			for _, p := range r.Params() {
   138  				if p == param {
   139  					pp = true
   140  					break
   141  				}
   142  			}
   143  			if !pp {
   144  				break
   145  			}
   146  		}
   147  	}
   148  	return pp
   149  }
   150  
   151  // HasParamAndHeader returns true if the generated struct field name for the given header name
   152  // matches the generated struct field name of a param in c.Params.
   153  func (c *ContextTemplateData) HasParamAndHeader(name string) bool {
   154  	if c.Params == nil || c.Headers == nil {
   155  		return false
   156  	}
   157  
   158  	headerAtt := c.Headers.Type.ToObject()[name]
   159  	headerName := codegen.GoifyAtt(headerAtt, name, true)
   160  	for paramName, paramAtt := range c.Params.Type.ToObject() {
   161  		paramName = codegen.GoifyAtt(paramAtt, paramName, true)
   162  		if headerName == paramName {
   163  			return true
   164  		}
   165  	}
   166  	return false
   167  }
   168  
   169  // MustValidate returns true if code that checks for the presence of the given param must be
   170  // generated.
   171  func (c *ContextTemplateData) MustValidate(name string) bool {
   172  	return c.Params.IsRequired(name) && !c.IsPathParam(name)
   173  }
   174  
   175  // IterateResponses iterates through the responses sorted by status code.
   176  func (c *ContextTemplateData) IterateResponses(it func(*design.ResponseDefinition) error) error {
   177  	m := make(map[int]*design.ResponseDefinition, len(c.Responses))
   178  	var s []int
   179  	for _, resp := range c.Responses {
   180  		status := resp.Status
   181  		m[status] = resp
   182  		s = append(s, status)
   183  	}
   184  	sort.Ints(s)
   185  	for _, status := range s {
   186  		if err := it(m[status]); err != nil {
   187  			return err
   188  		}
   189  	}
   190  	return nil
   191  }
   192  
   193  // NewContextsWriter returns a contexts code writer.
   194  // Contexts provide the glue between the underlying request data and the user controller.
   195  func NewContextsWriter(filename string) (*ContextsWriter, error) {
   196  	file, err := codegen.SourceFileFor(filename)
   197  	if err != nil {
   198  		return nil, err
   199  	}
   200  	return &ContextsWriter{
   201  		SourceFile: file,
   202  		Finalizer:  codegen.NewFinalizer(),
   203  		Validator:  codegen.NewValidator(),
   204  	}, nil
   205  }
   206  
   207  // Execute writes the code for the context types to the writer.
   208  func (w *ContextsWriter) Execute(data *ContextTemplateData) error {
   209  	if err := w.ExecuteTemplate("context", ctxT, nil, data); err != nil {
   210  		return err
   211  	}
   212  	fn := template.FuncMap{
   213  		"newCoerceData":      newCoerceData,
   214  		"arrayAttribute":     arrayAttribute,
   215  		"printVal":           codegen.PrintVal,
   216  		"canonicalHeaderKey": http.CanonicalHeaderKey,
   217  		"isPathParam":        data.IsPathParam,
   218  		"valueTypeOf":        valueTypeOf,
   219  		"fromString":         fromString,
   220  	}
   221  	if err := w.ExecuteTemplate("new", ctxNewT, fn, data); err != nil {
   222  		return err
   223  	}
   224  	if data.Payload != nil {
   225  		found := false
   226  		for _, t := range design.Design.Types {
   227  			if t.TypeName == data.Payload.TypeName {
   228  				found = true
   229  				break
   230  			}
   231  		}
   232  		if !found {
   233  			fn := template.FuncMap{
   234  				"finalizeCode":   w.Finalizer.Code,
   235  				"validationCode": w.Validator.Code,
   236  			}
   237  			if err := w.ExecuteTemplate("payload", payloadT, fn, data); err != nil {
   238  				return err
   239  			}
   240  		}
   241  	}
   242  	return data.IterateResponses(func(resp *design.ResponseDefinition) error {
   243  		respData := map[string]interface{}{
   244  			"Context":  data,
   245  			"Response": resp,
   246  		}
   247  		var mt *design.MediaTypeDefinition
   248  		if resp.Type != nil {
   249  			var ok bool
   250  			if mt, ok = resp.Type.(*design.MediaTypeDefinition); !ok {
   251  				respData["Type"] = resp.Type
   252  				respData["ContentType"] = resp.MediaType
   253  				return w.ExecuteTemplate("response", ctxTRespT, nil, respData)
   254  			}
   255  		} else {
   256  			mt = design.Design.MediaTypeWithIdentifier(resp.MediaType)
   257  		}
   258  		if mt != nil {
   259  			var views []string
   260  			if resp.ViewName != "" {
   261  				views = []string{resp.ViewName}
   262  			} else {
   263  				views = make([]string, len(mt.Views))
   264  				i := 0
   265  				for name := range mt.Views {
   266  					views[i] = name
   267  					i++
   268  				}
   269  				sort.Strings(views)
   270  			}
   271  			for _, view := range views {
   272  				projected, _, err := mt.Project(view)
   273  				if err != nil {
   274  					return err
   275  				}
   276  				respData["Projected"] = projected
   277  				respData["ViewName"] = view
   278  				respData["MediaType"] = mt
   279  				respData["ContentType"] = mt.ContentType
   280  				if view == "default" {
   281  					respData["RespName"] = codegen.Goify(resp.Name, true)
   282  				} else {
   283  					base := fmt.Sprintf("%s%s", resp.Name, strings.Title(view))
   284  					respData["RespName"] = codegen.Goify(base, true)
   285  				}
   286  				if err := w.ExecuteTemplate("response", ctxMTRespT, fn, respData); err != nil {
   287  					return err
   288  				}
   289  			}
   290  			return nil
   291  		}
   292  		return w.ExecuteTemplate("response", ctxNoMTRespT, nil, respData)
   293  	})
   294  }
   295  
   296  // NewControllersWriter returns a handlers code writer.
   297  // Handlers provide the glue between the underlying request data and the user controller.
   298  func NewControllersWriter(filename string) (*ControllersWriter, error) {
   299  	file, err := codegen.SourceFileFor(filename)
   300  	if err != nil {
   301  		return nil, err
   302  	}
   303  	return &ControllersWriter{
   304  		SourceFile: file,
   305  		Finalizer:  codegen.NewFinalizer(),
   306  		Validator:  codegen.NewValidator(),
   307  	}, nil
   308  }
   309  
   310  // WriteInitService writes the initService function
   311  func (w *ControllersWriter) WriteInitService(encoders, decoders []*EncoderTemplateData) error {
   312  	ctx := map[string]interface{}{
   313  		"API":      design.Design,
   314  		"Encoders": encoders,
   315  		"Decoders": decoders,
   316  	}
   317  	return w.ExecuteTemplate("service", serviceT, nil, ctx)
   318  }
   319  
   320  // Execute writes the handlers GoGenerator
   321  func (w *ControllersWriter) Execute(data []*ControllerTemplateData) error {
   322  	if len(data) == 0 {
   323  		return nil
   324  	}
   325  	for _, d := range data {
   326  		if err := w.ExecuteTemplate("controller", ctrlT, nil, d); err != nil {
   327  			return err
   328  		}
   329  		if err := w.ExecuteTemplate("mount", mountT, nil, d); err != nil {
   330  			return err
   331  		}
   332  		if len(d.Origins) > 0 {
   333  			if err := w.ExecuteTemplate("handleCORS", handleCORST, nil, d); err != nil {
   334  				return err
   335  			}
   336  		}
   337  		fn := template.FuncMap{
   338  			"newCoerceData":  newCoerceData,
   339  			"finalizeCode":   w.Finalizer.Code,
   340  			"arrayAttribute": arrayAttribute,
   341  			"validationCode": w.Validator.Code,
   342  			"valueTypeOf":    valueTypeOf,
   343  			"fromString":     fromString,
   344  		}
   345  		if err := w.ExecuteTemplate("unmarshal", unmarshalT, fn, d); err != nil {
   346  			return err
   347  		}
   348  	}
   349  	return nil
   350  }
   351  
   352  // NewSecurityWriter returns a security functionality code writer.
   353  // Those functionalities are there to support action-middleware related to security.
   354  func NewSecurityWriter(filename string) (*SecurityWriter, error) {
   355  	file, err := codegen.SourceFileFor(filename)
   356  	if err != nil {
   357  		return nil, err
   358  	}
   359  	return &SecurityWriter{SourceFile: file}, nil
   360  }
   361  
   362  // Execute adds the different security schemes and middleware supporting functions.
   363  func (w *SecurityWriter) Execute(schemes []*design.SecuritySchemeDefinition) error {
   364  	return w.ExecuteTemplate("security_schemes", securitySchemesT, nil, schemes)
   365  }
   366  
   367  // NewResourcesWriter returns a contexts code writer.
   368  // Resources provide the glue between the underlying request data and the user controller.
   369  func NewResourcesWriter(filename string) (*ResourcesWriter, error) {
   370  	file, err := codegen.SourceFileFor(filename)
   371  	if err != nil {
   372  		return nil, err
   373  	}
   374  	return &ResourcesWriter{SourceFile: file}, nil
   375  }
   376  
   377  // Execute writes the code for the context types to the writer.
   378  func (w *ResourcesWriter) Execute(data *ResourceData) error {
   379  	return w.ExecuteTemplate("resource", resourceT, nil, data)
   380  }
   381  
   382  // NewMediaTypesWriter returns a contexts code writer.
   383  // Media types contain the data used to render response bodies.
   384  func NewMediaTypesWriter(filename string) (*MediaTypesWriter, error) {
   385  	file, err := codegen.SourceFileFor(filename)
   386  	if err != nil {
   387  		return nil, err
   388  	}
   389  	return &MediaTypesWriter{SourceFile: file, Validator: codegen.NewValidator()}, nil
   390  }
   391  
   392  // Execute writes the code for the context types to the writer.
   393  func (w *MediaTypesWriter) Execute(mt *design.MediaTypeDefinition) error {
   394  	var (
   395  		mLinks *design.UserTypeDefinition
   396  		fn     = template.FuncMap{"validationCode": w.Validator.Code}
   397  	)
   398  	err := mt.IterateViews(func(view *design.ViewDefinition) error {
   399  		p, links, err := mt.Project(view.Name)
   400  		if mLinks == nil {
   401  			mLinks = links
   402  		}
   403  		if err != nil {
   404  			return err
   405  		}
   406  		return w.ExecuteTemplate("mediatype", mediaTypeT, fn, p)
   407  	})
   408  	if err != nil {
   409  		return err
   410  	}
   411  	if mLinks != nil {
   412  		if err := w.ExecuteTemplate("mediatypelink", mediaTypeLinkT, fn, mLinks); err != nil {
   413  			return err
   414  		}
   415  	}
   416  	return nil
   417  }
   418  
   419  // NewUserTypesWriter returns a contexts code writer.
   420  // User types contain custom data structured defined in the DSL with "Type".
   421  func NewUserTypesWriter(filename string) (*UserTypesWriter, error) {
   422  	file, err := codegen.SourceFileFor(filename)
   423  	if err != nil {
   424  		return nil, err
   425  	}
   426  	return &UserTypesWriter{
   427  		SourceFile: file,
   428  		Finalizer:  codegen.NewFinalizer(),
   429  		Validator:  codegen.NewValidator(),
   430  	}, nil
   431  }
   432  
   433  // Execute writes the code for the context types to the writer.
   434  func (w *UserTypesWriter) Execute(t *design.UserTypeDefinition) error {
   435  	fn := template.FuncMap{
   436  		"finalizeCode":   w.Finalizer.Code,
   437  		"validationCode": w.Validator.Code,
   438  	}
   439  	return w.ExecuteTemplate("types", userTypeT, fn, t)
   440  }
   441  
   442  // newCoerceData is a helper function that creates a map that can be given to the "Coerce" template.
   443  func newCoerceData(name string, att *design.AttributeDefinition, pointer bool, pkg string, depth int) map[string]interface{} {
   444  	return map[string]interface{}{
   445  		"Name":      name,
   446  		"VarName":   codegen.Goify(name, false),
   447  		"Pointer":   pointer,
   448  		"Attribute": att,
   449  		"Pkg":       pkg,
   450  		"Depth":     depth,
   451  	}
   452  }
   453  
   454  // arrayAttribute returns the array element attribute definition.
   455  func arrayAttribute(a *design.AttributeDefinition) *design.AttributeDefinition {
   456  	return a.Type.(*design.Array).ElemType
   457  }
   458  
   459  func hashAttribute(a *design.AttributeDefinition) (*design.AttributeDefinition, *design.AttributeDefinition) {
   460  	hash := a.Type.(*design.Hash)
   461  	return hash.KeyType, hash.ElemType
   462  }
   463  
   464  // valueTypeOf returns the golang type definition string from attribute definition
   465  func valueTypeOf(prefix string, att *design.AttributeDefinition) string {
   466  	switch att.Type.Kind() {
   467  	case design.BooleanKind:
   468  		return prefix + "bool"
   469  	case design.IntegerKind:
   470  		return prefix + "int"
   471  	case design.NumberKind:
   472  		return prefix + "float"
   473  	case design.StringKind:
   474  		return prefix + "string"
   475  	case design.ArrayKind:
   476  		return valueTypeOf(prefix+"[]", arrayAttribute(att))
   477  	case design.HashKind:
   478  		key, elm := hashAttribute(att)
   479  		return valueTypeOf(prefix+"map["+valueTypeOf("", key)+"]", elm)
   480  	}
   481  	return prefix + "interface{}"
   482  }
   483  
   484  // fromString returns the gocode expression to convert string typed varName value to go-type defined in the attribute
   485  func fromString(att *design.AttributeDefinition, varName string) string {
   486  	switch att.Type.Kind() {
   487  	case design.BooleanKind:
   488  		return "strconv.ParseBool(" + varName + ")"
   489  	case design.IntegerKind:
   490  		return "strconv.Atoi(" + varName + ")"
   491  	case design.NumberKind:
   492  		return "strconv.ParseFloat(" + varName + ")"
   493  	case design.StringKind:
   494  		return varName + ", (error)(nil)"
   495  	case design.ArrayKind:
   496  	case design.HashKind:
   497  		return valueTypeOf("", att) + "{}, (error)(nil)"
   498  	}
   499  	return "(" + valueTypeOf("", att) + ")(nil), (error)(nil)"
   500  }
   501  
   502  const (
   503  	// ctxT generates the code for the context data type.
   504  	// template input: *ContextTemplateData
   505  	ctxT = `// {{ .Name }} provides the {{ .ResourceName }} {{ .ActionName }} action context.
   506  type {{ .Name }} struct {
   507  	context.Context
   508  	*goa.ResponseData
   509  	*goa.RequestData
   510  {{ if .Headers }}{{ range $name, $att := .Headers.Type.ToObject }}{{ if not ($.HasParamAndHeader $name) }}{{/*
   511  */}}	{{ goifyatt $att $name true }} {{ if and $att.Type.IsPrimitive ($.Headers.IsPrimitivePointer $name) }}*{{ end }}{{ gotyperef .Type nil 0 false }}
   512  {{ end }}{{ end }}{{ end }}{{ if .Params }}{{ range $name, $att := .Params.Type.ToObject }}{{/*
   513  */}}	{{ goifyatt $att $name true }} {{ if and $att.Type.IsPrimitive ($.Params.IsPrimitivePointer $name) }}*{{ end }}{{ gotyperef .Type nil 0 false }}
   514  {{ end }}{{ end }}{{ if .Payload }}	Payload {{ gotyperef .Payload nil 0 false }}
   515  {{ end }}}
   516  `
   517  	// coerceT generates the code that coerces the generic deserialized
   518  	// data to the actual type.
   519  	// template input: map[string]interface{} as returned by newCoerceData
   520  	coerceT = `{{ if eq .Attribute.Type.Kind 1 }}{{/*
   521  
   522  */}}{{/* BooleanType */}}{{/*
   523  */}}{{ $varName := or (and (not .Pointer) .VarName) tempvar }}{{/*
   524  */}}{{ tabs .Depth }}if {{ .VarName }}, err2 := strconv.ParseBool(raw{{ goify .Name true }}); err2 == nil {
   525  {{ if .Pointer }}{{ tabs .Depth }}	{{ $varName }} := &{{ .VarName }}
   526  {{ end }}{{ tabs .Depth }}	{{ .Pkg }} = {{ $varName }}
   527  {{ tabs .Depth }}} else {
   528  {{ tabs .Depth }}	err = goa.MergeErrors(err, goa.InvalidParamTypeError("{{ .Name }}", raw{{ goify .Name true }}, "boolean"))
   529  {{ tabs .Depth }}}
   530  {{ else if eq .Attribute.Type.Kind 2 }}{{/*
   531  
   532  */}}{{/* IntegerType */}}{{/*
   533  */}}{{ $tmp := tempvar }}{{/*
   534  */}}{{ tabs .Depth }}if {{ .VarName }}, err2 := strconv.Atoi(raw{{ goify .Name true }}); err2 == nil {
   535  {{ if .Pointer }}{{ $tmp2 := tempvar }}{{ tabs .Depth }}	{{ $tmp2 }} := {{ .VarName }}
   536  {{ tabs .Depth }}	{{ $tmp }} := &{{ $tmp2 }}
   537  {{ tabs .Depth }}	{{ .Pkg }} = {{ $tmp }}
   538  {{ else }}{{ tabs .Depth }}	{{ .Pkg }} = {{ .VarName }}
   539  {{ end }}{{ tabs .Depth }}} else {
   540  {{ tabs .Depth }}	err = goa.MergeErrors(err, goa.InvalidParamTypeError("{{ .Name }}", raw{{ goify .Name true }}, "integer"))
   541  {{ tabs .Depth }}}
   542  {{ else if eq .Attribute.Type.Kind 3 }}{{/*
   543  
   544  */}}{{/* NumberType */}}{{/*
   545  */}}{{ $varName := or (and (not .Pointer) .VarName) tempvar }}{{/*
   546  */}}{{ tabs .Depth }}if {{ .VarName }}, err2 := strconv.ParseFloat(raw{{ goify .Name true }}, 64); err2 == nil {
   547  {{ if .Pointer }}{{ tabs .Depth }}	{{ $varName }} := &{{ .VarName }}
   548  {{ end }}{{ tabs .Depth }}	{{ .Pkg }} = {{ $varName }}
   549  {{ tabs .Depth }}} else {
   550  {{ tabs .Depth }}	err = goa.MergeErrors(err, goa.InvalidParamTypeError("{{ .Name }}", raw{{ goify .Name true }}, "number"))
   551  {{ tabs .Depth }}}
   552  {{ else if eq .Attribute.Type.Kind 4 }}{{/*
   553  
   554  */}}{{/* StringType */}}{{/*
   555  */}}{{ tabs .Depth }}{{ .Pkg }} = {{ if .Pointer }}&{{ end }}raw{{ goify .Name true }}
   556  {{ else if eq .Attribute.Type.Kind 5 }}{{/*
   557  
   558  */}}{{/* DateTimeType */}}{{/*
   559  */}}{{ $varName := or (and (not .Pointer) .VarName) tempvar }}{{/*
   560  */}}{{ tabs .Depth }}if {{ .VarName }}, err2 := time.Parse(time.RFC3339, raw{{ goify .Name true }}); err2 == nil {
   561  {{ if .Pointer }}{{ tabs .Depth }}	{{ $varName }} := &{{ .VarName }}
   562  {{ end }}{{ tabs .Depth }}	{{ .Pkg }} = {{ $varName }}
   563  {{ tabs .Depth }}} else {
   564  {{ tabs .Depth }}	err = goa.MergeErrors(err, goa.InvalidParamTypeError("{{ .Name }}", raw{{ goify .Name true }}, "datetime"))
   565  {{ tabs .Depth }}}
   566  {{ else if eq .Attribute.Type.Kind 6 }}{{/*
   567  
   568  */}}{{/* UUIDType */}}{{/*
   569  */}}{{ $varName := or (and (not .Pointer) .VarName) tempvar }}{{/*
   570  */}}{{ tabs .Depth }}if {{ .VarName }}, err2 := uuid.FromString(raw{{ goify .Name true }}); err2 == nil {
   571  {{ if .Pointer }}{{ tabs .Depth }}	{{ $varName }} := &{{ .VarName }}
   572  {{ end }}{{ tabs .Depth }}	{{ .Pkg }} = {{ $varName }}
   573  {{ tabs .Depth }}} else {
   574  {{ tabs .Depth }}	err = goa.MergeErrors(err, goa.InvalidParamTypeError("{{ .Name }}", raw{{ goify .Name true }}, "uuid"))
   575  {{ tabs .Depth }}}
   576  {{ else if eq .Attribute.Type.Kind 7 }}{{/*
   577  
   578  */}}{{/* AnyType */}}{{/*
   579  */}}{{ if .Pointer }}{{ $tmp := tempvar }}{{ tabs .Depth }}{{ $tmp }} := interface{}(raw{{ goify .Name true }})
   580  {{ tabs .Depth }}{{ .Pkg }} = &{{ $tmp }}
   581  {{ else }}{{ tabs .Depth }}{{ .Pkg }} = raw{{ goify .Name true }}{{/*
   582  */}}{{ end }}
   583  {{ else if eq .Attribute.Type.Kind 8 }}{{/*
   584  
   585  */}}{{/* ArrayType */}}{{/*
   586  */}}{{ tabs .Depth }}tmp{{ goify .Name true }} := make({{ valueTypeOf "" .Attribute }}, len(raw{{ goify .Name true }}))
   587  {{ tabs .Depth }}for i := 0; i < len(raw{{ goify .Name true }}); i++ {
   588  {{ if eq (arrayAttribute .Attribute).Type.Kind 4 }}{{ tabs .Depth}}	tmp := raw{{ goify .Name true }}[i]{{ else }}{{/*
   589  */}}{{ tabs .Depth }}	tmp, err2 := {{ fromString (arrayAttribute .Attribute) (printf "raw%s[i]" (goify .Name true)) }}
   590  {{ tabs .Depth }}	if err2 != nil {
   591  {{ tabs .Depth }}		err = goa.MergeErrors(err, goa.InvalidParamTypeError("{{ .Name }}", raw{{ goify .Name true }}, "{{ valueTypeOf "" .Attribute }}"))
   592  {{ tabs .Depth }}		break
   593  {{ tabs .Depth }}	}{{ end }}
   594  {{ tabs .Depth}}	tmp{{ goify .Name true }}[i] = tmp
   595  {{ tabs .Depth}}}
   596  {{ tabs .Depth }}{{ .Pkg }} = tmp{{ goify .Name true }}{{/*
   597  */}}
   598  {{ else if eq .Attribute.Type.Kind 13 }}{{/*
   599  
   600  */}}{{/* FileType */}}{{/*
   601  */}}{{ tabs .Depth }}if err2 == nil {
   602  {{ tabs .Depth }}	{{ .Pkg }} = {{ printf "raw%s" (goify .VarName true) }}
   603  {{ tabs .Depth }}} else {
   604  {{ tabs .Depth }}	err = goa.MergeErrors(err, goa.InvalidParamTypeError("{{ .Name }}", "{{ .Name }}", "file"))
   605  {{ tabs .Depth }}}
   606  {{ end }}`
   607  
   608  	// ctxNewT generates the code for the context factory method.
   609  	// template input: *ContextTemplateData
   610  	ctxNewT = `{{ define "Coerce" }}` + coerceT + `{{ end }}` + `
   611  // New{{ goify .Name true }} parses the incoming request URL and body, performs validations and creates the
   612  // context used by the {{ .ResourceName }} controller {{ .ActionName }} action.
   613  func New{{ .Name }}(ctx context.Context, r *http.Request, service *goa.Service) (*{{ .Name }}, error) {
   614  	var err error
   615  	resp := goa.ContextResponse(ctx)
   616  	resp.Service = service
   617  	req := goa.ContextRequest(ctx)
   618  	req.Request = r
   619  	rctx := {{ .Name }}{Context: ctx, ResponseData: resp, RequestData: req}{{/*
   620  */}}
   621  {{ if .Headers }}{{ range $name, $att := .Headers.Type.ToObject }}	header{{ goify $name true }} := req.Header["{{ canonicalHeaderKey $name }}"]
   622  {{ $mustValidate := $.Headers.IsRequired $name }}{{ if $mustValidate }}	if len(header{{ goify $name true }}) == 0 {
   623  		err = goa.MergeErrors(err, goa.MissingHeaderError("{{ $name }}"))
   624  	} else {
   625  {{ else }}	if len(header{{ goify $name true }}) > 0 {
   626  {{ end }}{{/* if $mustValidate */}}{{ if $att.Type.IsArray }}		req.Params["{{ $name }}"] = header{{ goify $name true }}
   627  {{ if eq (arrayAttribute $att).Type.Kind 4 }}		headers := header{{ goify $name true }}
   628  {{ else }}		headers := make({{ gotypedef $att 2 true false }}, len(header{{ goify $name true }}))
   629  		for i, raw{{ goify $name true}} := range header{{ goify $name true}} {
   630  {{ template "Coerce" (newCoerceData $name (arrayAttribute $att) ($.Headers.IsPrimitivePointer $name) "headers[i]" 3) }}{{/*
   631  */}}		}
   632  {{ end }}		{{ printf "rctx.%s" (goifyatt $att $name true) }} = headers
   633  {{ else }}		raw{{ goify $name true}} := header{{ goify $name true}}[0]
   634  		req.Params["{{ $name }}"] = []string{raw{{ goify $name true }}}
   635  {{ template "Coerce" (newCoerceData $name $att ($.Headers.IsPrimitivePointer $name) (printf "rctx.%s" (goifyatt $att $name true)) 2) }}{{ end }}{{/*
   636  */}}{{ $validation := validationChecker $att ($.Headers.IsNonZero $name) ($.Headers.IsRequired $name) ($.Headers.HasDefaultValue $name) (printf "rctx.%s" (goifyatt $att $name true)) $name 2 false }}{{/*
   637  */}}{{ if $validation }}{{ $validation }}
   638  {{ end }}	}
   639  {{ end }}{{ end }}{{/* if .Headers }}{{/*
   640  
   641  */}}{{ if .Params }}{{ range $name, $att := .Params.Type.ToObject }}{{/*
   642  */}}	param{{ goify $name true }} := req.Params["{{ $name }}"]
   643  {{ $mustValidate := $.MustValidate $name }}{{ if $mustValidate }}	if len(param{{ goify $name true }}) == 0 {
   644  		{{ if $.Params.HasDefaultValue $name }}{{printf "rctx.%s" (goifyatt $att $name true) }} = {{ printVal $att.Type $att.DefaultValue }}{{else}}{{/*
   645  */}}err = goa.MergeErrors(err, goa.MissingParamError("{{ $name }}")){{end}}
   646  	} else {
   647  {{ else }}{{ if $.Params.HasDefaultValue $name }}	if len(param{{ goify $name true }}) == 0 {
   648  		{{printf "rctx.%s" (goifyatt $att $name true) }} = {{ printVal $att.Type $att.DefaultValue }}
   649  	} else {
   650  {{ else }}	if len(param{{ goify $name true }}) > 0 {
   651  {{ end }}{{ end }}{{/* if $mustValidate */}}{{ if $att.Type.IsArray }}{{ if eq (arrayAttribute $att).Type.Kind 4 }}		params := param{{ goify $name true }}
   652  {{ else }}		params := make({{ gotypedef $att 2 true false }}, len(param{{ goify $name true }}))
   653  		for i, raw{{ goify $name true}} := range param{{ goify $name true}} {
   654  {{ template "Coerce" (newCoerceData $name (arrayAttribute $att) ($.Params.IsPrimitivePointer $name) "params[i]" 3) }}{{/*
   655  */}}		}
   656  {{ end }}		{{ printf "rctx.%s" (goifyatt $att $name true) }} = params
   657  {{ else }}		raw{{ goify $name true}} := param{{ goify $name true}}[0]
   658  {{ template "Coerce" (newCoerceData $name $att ($.Params.IsPrimitivePointer $name) (printf "rctx.%s" (goifyatt $att $name true)) 2) }}{{ end }}{{/*
   659  */}}{{ if $att.Type.IsArray }}{{ $validation := validationChecker (arrayAttribute $att) true true false "param" (printf "%s[0]" $name) 2 false }}{{/*
   660  */}}{{ if $validation }}for _, param := range {{ printf "rctx.%s" (goifyatt $att $name true) }} {
   661  	{{ $validation }}
   662  	}{{ end }}{{/*
   663  */}}{{ else }}{{ $validation := validationChecker $att ($.Params.IsNonZero $name) ($.Params.IsRequired $name) ($.Params.HasDefaultValue $name) (printf "rctx.%s" (goifyatt $att $name true)) $name 2 false }}{{/*
   664  */}}{{ if $validation }}{{ $validation }}{{ end }}{{ end }}	}
   665  {{ end }}{{ end }}{{/* if .Params */}}	return &rctx, err
   666  }
   667  `
   668  
   669  	// ctxMTRespT generates the response helpers for responses with media types.
   670  	// template input: map[string]interface{}
   671  	ctxMTRespT = `// {{ goify .RespName true }} sends a HTTP response with status code {{ .Response.Status }}.
   672  func (ctx *{{ .Context.Name }}) {{ goify .RespName true }}(r {{ gotyperef .Projected .Projected.AllRequired 0 false }}) error {
   673  	if ctx.ResponseData.Header().Get("Content-Type") == "" {
   674  		ctx.ResponseData.Header().Set("Content-Type", "{{ .ContentType }}")
   675  	}
   676  {{ if .Projected.Type.IsArray }}	if r == nil {
   677  		r = {{ gotyperef .Projected .Projected.AllRequired 0 false }}{}
   678  	}
   679  {{ end }}	return ctx.ResponseData.Service.Send(ctx.Context, {{ .Response.Status }}, r)
   680  }
   681  `
   682  
   683  	// ctxTRespT generates the response helpers for responses with overridden types.
   684  	// template input: map[string]interface{}
   685  	ctxTRespT = `// {{ goify .Response.Name true }} sends a HTTP response with status code {{ .Response.Status }}.
   686  func (ctx *{{ .Context.Name }}) {{ goify .Response.Name true }}(r {{ gotyperef .Type nil 0 false }}) error {
   687  	if ctx.ResponseData.Header().Get("Content-Type") == "" {
   688  		ctx.ResponseData.Header().Set("Content-Type", "{{ .ContentType }}")
   689  	}
   690  	return ctx.ResponseData.Service.Send(ctx.Context, {{ .Response.Status }}, r)
   691  }
   692  `
   693  
   694  	// ctxNoMTRespT generates the response helpers for responses with no known media type.
   695  	// template input: *ContextTemplateData
   696  	ctxNoMTRespT = `
   697  // {{ goify .Response.Name true }} sends a HTTP response with status code {{ .Response.Status }}.
   698  func (ctx *{{ .Context.Name }}) {{ goify .Response.Name true }}({{ if .Response.MediaType }}resp []byte{{ end }}) error {
   699  {{ if .Response.MediaType }}	if ctx.ResponseData.Header().Get("Content-Type") == "" {
   700  		ctx.ResponseData.Header().Set("Content-Type", "{{ .Response.MediaType }}")
   701  	}
   702  {{ end }}	ctx.ResponseData.WriteHeader({{ .Response.Status }}){{ if .Response.MediaType }}
   703  	_, err := ctx.ResponseData.Write(resp)
   704  	return err{{ else }}
   705  	return nil{{ end }}
   706  }
   707  `
   708  
   709  	// payloadT generates the payload type definition GoGenerator
   710  	// template input: *ContextTemplateData
   711  	payloadT = `{{ $payload := .Payload }}{{ if .Payload.IsObject }}// {{ gotypename .Payload nil 0 true }} is the {{ .ResourceName }} {{ .ActionName }} action payload.{{/*
   712  */}}{{ $privateTypeName := gotypename .Payload nil 1 true }}
   713  type {{ $privateTypeName }} {{ gotypedef .Payload 0 true true }}
   714  
   715  {{ $assignment := finalizeCode .Payload.AttributeDefinition "payload" 1 }}{{ if $assignment }}// Finalize sets the default values defined in the design.
   716  func (payload {{ gotyperef .Payload .Payload.AllRequired 0 true }}) Finalize() {
   717  {{ $assignment }}
   718  }{{ end }}
   719  
   720  {{ $validation := validationCode .Payload.AttributeDefinition false false false "payload" "raw" 1 true }}{{ if $validation }}// Validate runs the validation rules defined in the design.
   721  func (payload {{ gotyperef .Payload .Payload.AllRequired 0 true }}) Validate() (err error) {
   722  {{ $validation }}
   723  	return
   724  }{{ end }}
   725  {{ $typeName := gotypename .Payload .Payload.AllRequired 1 false }}
   726  // Publicize creates {{ $typeName }} from {{ $privateTypeName }}
   727  func (payload {{ gotyperef .Payload .Payload.AllRequired 0 true }}) Publicize() {{ gotyperef .Payload .Payload.AllRequired 0 false }} {
   728  	var pub {{ $typeName }}
   729  	{{ recursivePublicizer .Payload.AttributeDefinition "payload" "pub" 1 }}
   730  	return &pub
   731  }{{ end }}
   732  
   733  // {{ gotypename .Payload nil 0 false }} is the {{ .ResourceName }} {{ .ActionName }} action payload.
   734  type {{ gotypename .Payload nil 1 false }} {{ gotypedef .Payload 0 true false }}
   735  
   736  {{ $validation := validationCode .Payload.AttributeDefinition false false false "payload" "raw" 1 false }}{{ if $validation }}// Validate runs the validation rules defined in the design.
   737  func (payload {{ gotyperef .Payload .Payload.AllRequired 0 false }}) Validate() (err error) {
   738  {{ $validation }}
   739  	return
   740  }{{ end }}
   741  `
   742  	// ctrlT generates the controller interface for a given resource.
   743  	// template input: *ControllerTemplateData
   744  	ctrlT = `// {{ .Resource }}Controller is the controller interface for the {{ .Resource }} actions.
   745  type {{ .Resource }}Controller interface {
   746  	goa.Muxer
   747  {{ if .FileServers }}	goa.FileServer
   748  {{ end }}{{ range .Actions }}	{{ .Name }}(*{{ .Context }}) error
   749  {{ end }}}
   750  `
   751  
   752  	// serviceT generates the service initialization code.
   753  	// template input: *ControllerTemplateData
   754  	serviceT = `
   755  // initService sets up the service encoders, decoders and mux.
   756  func initService(service *goa.Service) {
   757  	// Setup encoders and decoders
   758  {{ range .Encoders }}{{/*
   759  */}}	service.Encoder.Register({{ .PackageName }}.{{ .Function }}, "{{ join .MIMETypes "\", \"" }}")
   760  {{ end }}{{ range .Decoders }}{{/*
   761  */}}	service.Decoder.Register({{ .PackageName }}.{{ .Function }}, "{{ join .MIMETypes "\", \"" }}")
   762  {{ end }}
   763  
   764  	// Setup default encoder and decoder
   765  {{ range .Encoders }}{{ if .Default }}{{/*
   766  */}}	service.Encoder.Register({{ .PackageName }}.{{ .Function }}, "*/*")
   767  {{ end }}{{ end }}{{ range .Decoders }}{{ if .Default }}{{/*
   768  */}}	service.Decoder.Register({{ .PackageName }}.{{ .Function }}, "*/*")
   769  {{ end }}{{ end }}}
   770  `
   771  
   772  	// mountT generates the code for a resource "Mount" function.
   773  	// template input: *ControllerTemplateData
   774  	mountT = `
   775  // Mount{{ .Resource }}Controller "mounts" a {{ .Resource }} resource controller on the given service.
   776  func Mount{{ .Resource }}Controller(service *goa.Service, ctrl {{ .Resource }}Controller) {
   777  	initService(service)
   778  	var h goa.Handler
   779  {{ $res := .Resource }}{{ if .Origins }}{{ range .PreflightPaths }}{{/*
   780  */}}	service.Mux.Handle("OPTIONS", {{ printf "%q" . }}, ctrl.MuxHandler("preflight", handle{{ $res }}Origin(cors.HandlePreflight()), nil))
   781  {{ end }}{{ end }}{{ range .Actions }}{{ $action := . }}
   782  	h = func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
   783  		// Check if there was an error loading the request
   784  		if err := goa.ContextError(ctx); err != nil {
   785  			return err
   786  		}
   787  		// Build the context
   788  		rctx, err := New{{ .Context }}(ctx, req, service)
   789  		if err != nil {
   790  			return err
   791  		}
   792  {{ if .Payload }}		// Build the payload
   793  		if rawPayload := goa.ContextRequest(ctx).Payload; rawPayload != nil {
   794  			rctx.Payload = rawPayload.({{ gotyperef .Payload nil 1 false }})
   795  {{ if not .PayloadOptional }}		} else {
   796  			return goa.MissingPayloadError()
   797  {{ end }}		}
   798  {{ end }}		return ctrl.{{ .Name }}(rctx)
   799  	}
   800  {{ if .Security }}	h = handleSecurity({{ printf "%q" .Security.Scheme.SchemeName }}, h{{ range .Security.Scopes }}, {{ printf "%q" . }}{{ end }})
   801  {{ end }}{{ if $.Origins }}	h = handle{{ $res }}Origin(h)
   802  {{ end }}{{ range .Routes }}	service.Mux.Handle("{{ .Verb }}", {{ printf "%q" .FullPath }}, ctrl.MuxHandler({{ printf "%q" $action.DesignName }}, h, {{ if $action.Payload }}{{ $action.Unmarshal }}{{ else }}nil{{ end }}))
   803  	service.LogInfo("mount", "ctrl", {{ printf "%q" $res }}, "action", {{ printf "%q" $action.Name }}, "route", {{ printf "%q" (printf "%s %s" .Verb .FullPath) }}{{ with $action.Security }}, "security", {{ printf "%q" .Scheme.SchemeName }}{{ end }})
   804  {{ end }}{{ end }}{{ range .FileServers }}
   805  	h = ctrl.FileHandler({{ printf "%q" .RequestPath }}, {{ printf "%q" .FilePath }})
   806  {{ if .Security }}	h = handleSecurity({{ printf "%q" .Security.Scheme.SchemeName }}, h{{ range .Security.Scopes }}, {{ printf "%q" . }}{{ end }})
   807  {{ end }}{{ if $.Origins }}	h = handle{{ $res }}Origin(h)
   808  {{ end }}	service.Mux.Handle("GET", "{{ .RequestPath }}", ctrl.MuxHandler("serve", h, nil))
   809  	service.LogInfo("mount", "ctrl", {{ printf "%q" $res }}, "files", {{ printf "%q" .FilePath }}, "route", {{ printf "%q" (printf "GET %s" .RequestPath) }}{{ with .Security }}, "security", {{ printf "%q" .Scheme.SchemeName }}{{ end }})
   810  {{ end }}}
   811  `
   812  
   813  	// handleCORST generates the code that checks whether a CORS request is authorized
   814  	// template input: *ControllerTemplateData
   815  	handleCORST = `// handle{{ .Resource }}Origin applies the CORS response headers corresponding to the origin.
   816  func handle{{ .Resource }}Origin(h goa.Handler) goa.Handler {
   817  {{ range $i, $policy := .Origins }}{{ if $policy.Regexp }}	spec{{$i}} := regexp.MustCompile({{ printf "%q" $policy.Origin }})
   818  {{ end }}{{ end }}
   819  	return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
   820  		origin := req.Header.Get("Origin")
   821  		if origin == "" {
   822  			// Not a CORS request
   823  			return h(ctx, rw, req)
   824  		}
   825  {{ range $i, $policy := .Origins }}		{{ if $policy.Regexp }}if cors.MatchOriginRegexp(origin, spec{{$i}}){{else}}if cors.MatchOrigin(origin, {{ printf "%q" $policy.Origin }}){{end}} {
   826  			ctx = goa.WithLogContext(ctx, "origin", origin)
   827  			rw.Header().Set("Access-Control-Allow-Origin", origin)
   828  {{ if not (eq $policy.Origin "*") }}			rw.Header().Set("Vary", "Origin")
   829  {{ end }}{{ if $policy.Exposed }}			rw.Header().Set("Access-Control-Expose-Headers", "{{ join $policy.Exposed ", " }}")
   830  {{ end }}{{ if gt $policy.MaxAge 0 }}			rw.Header().Set("Access-Control-Max-Age", "{{ $policy.MaxAge }}")
   831  {{ end }}			rw.Header().Set("Access-Control-Allow-Credentials", "{{ $policy.Credentials }}")
   832  			if acrm := req.Header.Get("Access-Control-Request-Method"); acrm != "" {
   833  				// We are handling a preflight request
   834  {{ if $policy.Methods }}				rw.Header().Set("Access-Control-Allow-Methods", "{{ join $policy.Methods ", " }}")
   835  {{ end }}{{ if $policy.Headers }}				rw.Header().Set("Access-Control-Allow-Headers", "{{ join $policy.Headers ", " }}")
   836  {{ end }}			}
   837  			return h(ctx, rw, req)
   838  		}
   839  {{ end }}
   840  		return h(ctx, rw, req)
   841  	}
   842  }
   843  `
   844  
   845  	// unmarshalT generates the code for an action payload unmarshal function.
   846  	// template input: *ControllerTemplateData
   847  	unmarshalT = `{{ define "Coerce" }}` + coerceT + `{{ end }}` + `{{ range .Actions }}{{ if .Payload }}
   848  // {{ .Unmarshal }} unmarshals the request body into the context request data Payload field.
   849  func {{ .Unmarshal }}(ctx context.Context, service *goa.Service, req *http.Request) error {
   850  	{{ if .PayloadMultipart}}var err error
   851  	var payload {{ gotypename .Payload nil 1 true }}
   852  {{ $o := .Payload.ToObject }}{{ range $name, $att := $o -}}
   853  	{{ if eq $att.Type.Kind 13 }}	_, raw{{ goify $name true }}, err2 := req.FormFile("{{ $name }}"){{ else if eq $att.Type.Kind 8 }}{{/*
   854  */}}	raw{{ goify $name true }} := req.Form["{{ $name }}[]"]{{ else }}{{/*
   855  */}}	raw{{ goify $name true }} := req.FormValue("{{ $name }}"){{ end }}
   856  {{ template "Coerce" (newCoerceData $name $att true (printf "payload.%s" (goifyatt $att $name true)) 1) }}{{ end }}{{/*
   857  */}}	if err != nil {
   858  		return err
   859  	}{{ else if .Payload.IsObject }}payload := &{{ gotypename .Payload nil 1 true }}{}
   860  	if err := service.DecodeRequest(req, payload); err != nil {
   861  		return err
   862  	}{{ $assignment := finalizeCode .Payload.AttributeDefinition "payload" 1 }}{{ if $assignment }}
   863  	payload.Finalize(){{ end }}{{ else }}var payload {{ gotypename .Payload nil 1 false }}
   864  	if err := service.DecodeRequest(req, &payload); err != nil {
   865  		return err
   866  	}{{ end }}{{ $validation := validationCode .Payload.AttributeDefinition false false false "payload" "raw" 1 true }}{{ if $validation }}
   867  	if err := payload.Validate(); err != nil {
   868  		// Initialize payload with private data structure so it can be logged
   869  		goa.ContextRequest(ctx).Payload = payload
   870  		return err
   871  	}{{ end }}
   872  	goa.ContextRequest(ctx).Payload = payload{{ if .Payload.IsObject }}.Publicize(){{ end }}
   873  	return nil
   874  }
   875  {{ end }}
   876  {{ end }}`
   877  
   878  	// resourceT generates the code for a resource.
   879  	// template input: *ResourceData
   880  	resourceT = `{{ if .CanonicalTemplate }}// {{ .Name }}Href returns the resource href.
   881  func {{ .Name }}Href({{ if .CanonicalParams }}{{ join .CanonicalParams ", " }} interface{}{{ end }}) string {
   882  {{ range $param := .CanonicalParams }}	param{{$param}} := strings.TrimLeftFunc(fmt.Sprintf("%v", {{$param}}), func(r rune) bool { return r == '/' })
   883  {{ end }}{{ if .CanonicalParams }}	return fmt.Sprintf("{{ .CanonicalTemplate }}", param{{ join .CanonicalParams ", param" }})
   884  {{ else }}	return "{{ .CanonicalTemplate }}"
   885  {{ end }}}
   886  {{ end }}`
   887  
   888  	// mediaTypeT generates the code for a media type.
   889  	// template input: MediaTypeTemplateData
   890  	mediaTypeT = `// {{ gotypedesc . true }}
   891  //
   892  // Identifier: {{ .Identifier }}{{ $typeName := gotypename . .AllRequired 0 false }}
   893  type {{ $typeName }} {{ gotypedef . 0 true false }}
   894  
   895  {{ $validation := validationCode .AttributeDefinition false false false "mt" "response" 1 false }}{{ if $validation }}// Validate validates the {{$typeName}} media type instance.
   896  func (mt {{ gotyperef . .AllRequired 0 false }}) Validate() (err error) {
   897  {{ $validation }}
   898  	return
   899  }
   900  {{ end }}
   901  `
   902  
   903  	// mediaTypeLinkT generates the code for a media type link.
   904  	// template input: MediaTypeLinkTemplateData
   905  	mediaTypeLinkT = `// {{ gotypedesc . true }}{{ $typeName := gotypename . .AllRequired 0 false }}
   906  type {{ $typeName }} {{ gotypedef . 0 true false }}
   907  {{ $validation := validationCode .AttributeDefinition false false false "ut" "response" 1 false }}{{ if $validation }}// Validate validates the {{$typeName}} type instance.
   908  func (ut {{ gotyperef . .AllRequired 0 false }}) Validate() (err error) {
   909  {{ $validation }}
   910  	return
   911  }{{ end }}
   912  `
   913  
   914  	// userTypeT generates the code for a user type.
   915  	// template input: UserTypeTemplateData
   916  	userTypeT = `// {{ gotypedesc . false }}{{ $privateTypeName := gotypename . .AllRequired 0 true }}
   917  type {{ $privateTypeName }} {{ gotypedef . 0 true true }}
   918  {{ $assignment := finalizeCode .AttributeDefinition "ut" 1 }}{{ if $assignment }}// Finalize sets the default values for {{$privateTypeName}} type instance.
   919  func (ut {{ gotyperef . .AllRequired 0 true }}) Finalize() {
   920  {{ $assignment }}
   921  }{{ end }}
   922  {{ $validation := validationCode .AttributeDefinition false false false "ut" "request" 1 true }}{{ if $validation }}// Validate validates the {{$privateTypeName}} type instance.
   923  func (ut {{ gotyperef . .AllRequired 0 true }}) Validate() (err error) {
   924  {{ $validation }}
   925  	return
   926  }{{ end }}
   927  {{ $typeName := gotypename . .AllRequired 0 false }}
   928  // Publicize creates {{ $typeName }} from {{ $privateTypeName }}
   929  func (ut {{ gotyperef . .AllRequired 0 true }}) Publicize() {{ gotyperef . .AllRequired 0 false }} {
   930  	var pub {{ gotypename . .AllRequired 0 false }}
   931  	{{ recursivePublicizer .AttributeDefinition "ut" "pub" 1 }}
   932  	return &pub
   933  }
   934  
   935  // {{ gotypedesc . true }}
   936  type {{ $typeName }} {{ gotypedef . 0 true false }}
   937  {{ $validation := validationCode .AttributeDefinition false false false "ut" "type" 1 false }}{{ if $validation }}// Validate validates the {{$typeName}} type instance.
   938  func (ut {{ gotyperef . .AllRequired 0 false }}) Validate() (err error) {
   939  {{ $validation }}
   940  	return
   941  }{{ end }}
   942  `
   943  
   944  	// securitySchemesT generates the code for the security module.
   945  	// template input: []*design.SecuritySchemeDefinition
   946  	securitySchemesT = `
   947  type (
   948  	// Private type used to store auth handler info in request context
   949  	authMiddlewareKey string
   950  )
   951  
   952  {{ range . }}
   953  {{ $funcName := printf "Use%sMiddleware" (goify .SchemeName true) }}// {{ $funcName }} mounts the {{ .SchemeName }} auth middleware onto the service.
   954  func {{ $funcName }}(service *goa.Service, middleware goa.Middleware) {
   955  	service.Context = context.WithValue(service.Context, authMiddlewareKey({{ printf "%q" .SchemeName }}), middleware)
   956  }
   957  
   958  {{ $funcName := printf "New%sSecurity" (goify .SchemeName true) }}// {{ $funcName }} creates a {{ .SchemeName }} security definition.
   959  func {{ $funcName }}() *goa.{{ .Context }} {
   960  	def := goa.{{ .Context }}{
   961  {{ if eq .Context "APIKeySecurity" }}{{/*
   962  */}}		In:   {{ if eq .In "header" }}goa.LocHeader{{ else }}goa.LocQuery{{ end }},
   963  		Name: {{ printf "%q" .Name }},
   964  {{ else if eq .Context "OAuth2Security" }}{{/*
   965  */}}		Flow:             {{ printf "%q" .Flow }},
   966  		TokenURL:         {{ printf "%q" .TokenURL }},
   967  		AuthorizationURL: {{ printf "%q" .AuthorizationURL }},{{ with .Scopes }}
   968  		Scopes: map[string]string{
   969  {{ range $k, $v := . }}			{{ printf "%q" $k }}: {{ printf "%q" $v }},
   970  {{ end }}{{/*
   971  */}}		},{{ end }}{{/*
   972  */}}{{ else if eq .Context "BasicAuthSecurity" }}{{/*
   973  */}}{{ else if eq .Context "JWTSecurity" }}{{/*
   974  */}}		In:   {{ if eq .In "header" }}goa.LocHeader{{ else }}goa.LocQuery{{ end }},
   975  		Name:             {{ printf "%q" .Name }},
   976  		TokenURL:         {{ printf "%q" .TokenURL }},{{ with .Scopes }}
   977  		Scopes: map[string]string{
   978  {{ range $k, $v := . }}			{{ printf "%q" $k }}: {{ printf "%q" $v }},
   979  {{ end }}{{/*
   980  */}}		},{{ end }}
   981  {{ end }}{{/*
   982  */}}	}
   983  {{ if .Description }} def.Description = {{ printf "%q" .Description }}
   984  {{ end }}	return &def
   985  }
   986  
   987  {{ end }}// handleSecurity creates a handler that runs the auth middleware for the security scheme.
   988  func handleSecurity(schemeName string, h goa.Handler, scopes ...string) goa.Handler {
   989  	return func(ctx context.Context, rw http.ResponseWriter, req *http.Request) error {
   990  		scheme := ctx.Value(authMiddlewareKey(schemeName))
   991  		am, ok := scheme.(goa.Middleware)
   992  		if !ok {
   993  			return goa.NoAuthMiddleware(schemeName)
   994  		}
   995  		ctx = goa.WithRequiredScopes(ctx, scopes)
   996  		return am(h)(ctx, rw, req)
   997  	}
   998  }
   999  `
  1000  )