github.com/josephbuchma/goa@v1.2.0/design/apidsl/resource.go (about) 1 package apidsl 2 3 import ( 4 "github.com/goadesign/goa/design" 5 "github.com/goadesign/goa/dslengine" 6 ) 7 8 // Resource implements the resource definition dsl. There is one resource definition per resource 9 // exposed by the API. The resource dsl allows setting the resource default media type. This media 10 // type is used to render the response body of actions that return the OK response (unless the 11 // action overrides the default). The default media type also sets the properties of the request 12 // payload attributes with the same name. See DefaultMedia. 13 // 14 // The resource dsl also allows listing the supported resource collection and resource collection 15 // item actions. Each action corresponds to a specific API endpoint. See Action. 16 // 17 // The resource dsl can also specify a parent resource. Parent resources have two effects. 18 // First, they set the prefix of all resource action paths to the parent resource href. Note that 19 // actions can override the path using an absolute path (that is a path starting with "//"). 20 // Second, goa uses the parent resource href coupled with the resource BasePath if any to build 21 // hrefs to the resource collection or resource collection items. By default goa uses the show 22 // action if present to compute a resource href (basically concatenating the parent resource href 23 // with the base path and show action path). The resource definition may specify a canonical action 24 // via CanonicalActionName to override that default. Here is an example of a resource definition: 25 // 26 // Resource("bottle", func() { 27 // Description("A wine bottle") // Resource description 28 // DefaultMedia(BottleMedia) // Resource default media type 29 // BasePath("/bottles") // Common resource action path prefix if not "" 30 // Parent("account") // Name of parent resource if any 31 // CanonicalActionName("get") // Name of action that returns canonical representation if not "show" 32 // UseTrait("Authenticated") // Included trait if any, can appear more than once 33 // 34 // Origin("http://swagger.goa.design", func() { // Define CORS policy, may be prefixed with "*" wildcard 35 // Headers("X-Shared-Secret") // One or more authorized headers, use "*" to authorize all 36 // Methods("GET", "POST") // One or more authorized HTTP methods 37 // Expose("X-Time") // One or more headers exposed to clients 38 // MaxAge(600) // How long to cache a prefligh request response 39 // Credentials() // Sets Access-Control-Allow-Credentials header 40 // }) 41 // 42 // Response(Unauthorized, ErrorMedia) // Common responses to all actions 43 // Response(BadRequest, ErrorMedia) 44 // 45 // Action("show", func() { // Action definition, can appear more than once 46 // // ... Action dsl 47 // }) 48 // }) 49 func Resource(name string, dsl func()) *design.ResourceDefinition { 50 if design.Design.Resources == nil { 51 design.Design.Resources = make(map[string]*design.ResourceDefinition) 52 } 53 if !dslengine.IsTopLevelDefinition() { 54 dslengine.IncompatibleDSL() 55 return nil 56 } 57 58 if _, ok := design.Design.Resources[name]; ok { 59 dslengine.ReportError("resource %#v is defined twice", name) 60 return nil 61 } 62 resource := design.NewResourceDefinition(name, dsl) 63 design.Design.Resources[name] = resource 64 return resource 65 } 66 67 // DefaultMedia sets a resource default media type by identifier or by reference using a value 68 // returned by MediaType: 69 // 70 // var _ = Resource("bottle", func() { 71 // DefaultMedia(BottleMedia) 72 // // ... 73 // }) 74 // 75 // var _ = Resource("region", func() { 76 // DefaultMedia("vnd.goa.region") 77 // // ... 78 // }) 79 // 80 // The default media type is used to build OK response definitions when no specific media type is 81 // given in the Response function call. The default media type is also used to set the default 82 // properties of attributes listed in action payloads and params. So if a media type defines an 83 // attribute "name" with associated validations then simply calling Attribute("name") inside a 84 // request Payload or Param defines the attribute with the same type and validations. 85 func DefaultMedia(val interface{}, viewName ...string) { 86 if r, ok := resourceDefinition(); ok { 87 if m, ok := val.(*design.MediaTypeDefinition); ok { 88 if m.UserTypeDefinition == nil { 89 dslengine.ReportError("invalid media type specification, media type is not initialized") 90 } else { 91 r.MediaType = m.Identifier 92 m.Resource = r 93 } 94 } else if identifier, ok := val.(string); ok { 95 r.MediaType = identifier 96 } else { 97 dslengine.ReportError("media type must be a string or a *design.MediaTypeDefinition, got %#v", val) 98 return 99 } 100 if len(viewName) == 1 { 101 r.DefaultViewName = viewName[0] 102 } else if len(viewName) > 1 { 103 dslengine.ReportError("too many arguments given to DefaultMedia") 104 } 105 } 106 } 107 108 // Parent sets the resource parent. The parent resource is used to compute the path to the resource 109 // actions as well as resource collection item hrefs. See Resource. 110 func Parent(p string) { 111 if r, ok := resourceDefinition(); ok { 112 r.ParentName = p 113 } 114 } 115 116 // CanonicalActionName sets the name of the action used to compute the resource collection and 117 // resource collection items hrefs. See Resource. 118 func CanonicalActionName(a string) { 119 if r, ok := resourceDefinition(); ok { 120 r.CanonicalActionName = a 121 } 122 }