// pathParamNames return the names of the parameters of the path factory function for the given route. func pathParamNames(r *design.RouteDefinition) string { params := r.Params() goified := make([]string, len(params)) for i, p := range params { goified[i] = codegen.Goify(p, false) } return strings.Join(goified, ", ") }
// pathParams return the function signature of the path factory function for the given route. func pathParams(r *design.RouteDefinition) string { pnames := r.Params() params := make(design.Object, len(pnames)) for _, p := range pnames { params[p] = r.Parent.Params.Type.ToObject()[p] } return join(&design.AttributeDefinition{Type: params}, pnames) }
// toSchemaHref produces a href that replaces the path wildcards with JSON schema references when // appropriate. func toSchemaHref(api *design.APIDefinition, r *design.RouteDefinition) string { params := r.Params() args := make([]interface{}, len(params)) for i, p := range params { args[i] = fmt.Sprintf("/{%s}", p) } tmpl := design.WildcardRegex.ReplaceAllLiteralString(r.FullPath(), "%s") return fmt.Sprintf(tmpl, args...) }
// pathTemplate returns a fmt format suitable to build a request path to the reoute. func pathTemplate(r *design.RouteDefinition) string { return design.WildcardRegex.ReplaceAllLiteralString(r.FullPath(), "/%v") }
func buildPathFromDefinition(s *Swagger, api *design.APIDefinition, route *design.RouteDefinition) error { action := route.Parent tagNames, err := tagNamesFromDefinition([]design.MetadataDefinition{action.Parent.Metadata, action.Metadata}) if err != nil { return err } params, err := paramsFromDefinition(action.AllParams(), route.FullPath(design.Design.APIVersionDefinition)) if err != nil { return err } responses := make(map[string]*Response, len(action.Responses)) for _, r := range action.Responses { resp, err := responseFromDefinition(s, api, r) if err != nil { return err } responses[strconv.Itoa(r.Status)] = resp } if action.Payload != nil { payloadSchema := genschema.TypeSchema(api, action.Payload) pp := &Parameter{ Name: "payload", In: "body", Description: action.Payload.Description, Required: true, Schema: payloadSchema, } params = append(params, pp) } operationID := fmt.Sprintf("%s#%s", action.Parent.Name, action.Name) index := 0 for i, rt := range action.Routes { if rt == route { index = i break } } if index > 0 { operationID = fmt.Sprintf("%s#%d", operationID, index) } schemes := action.Schemes if len(schemes) == 0 { schemes = api.Schemes } operation := &Operation{ Tags: tagNames, Description: action.Description, ExternalDocs: docsFromDefinition(action.Docs), OperationID: operationID, Parameters: params, Responses: responses, Schemes: schemes, Deprecated: false, } key := design.WildcardRegex.ReplaceAllStringFunc( route.FullPath(design.Design.APIVersionDefinition), func(w string) string { return fmt.Sprintf("/{%s}", w[2:]) }, ) if key == "" { key = "/" } key = strings.TrimPrefix(key, api.BasePath) var path *Path var ok bool if path, ok = s.Paths[key]; !ok { path = new(Path) s.Paths[key] = path } switch route.Verb { case "GET": path.Get = operation case "PUT": path.Put = operation case "POST": path.Post = operation case "DELETE": path.Delete = operation case "OPTIONS": path.Options = operation case "HEAD": path.Head = operation case "PATCH": path.Patch = operation } return nil }
func createTestMethod(resource *design.ResourceDefinition, action *design.ActionDefinition, response *design.ResponseDefinition, route *design.RouteDefinition, routeIndex int, mediaType *design.MediaTypeDefinition, view *design.ViewDefinition) TestMethod { routeNameQualifier := suffixRoute(action.Routes, routeIndex) viewNameQualifier := func() string { if view != nil && view.Name != "default" { return view.Name } return "" }() method := TestMethod{} method.Name = fmt.Sprintf("%s%s%s%s%s", codegen.Goify(action.Name, true), codegen.Goify(resource.Name, true), codegen.Goify(response.Name, true), routeNameQualifier, codegen.Goify(viewNameQualifier, true)) method.ActionName = codegen.Goify(action.Name, true) method.ResourceName = codegen.Goify(resource.Name, true) method.Comment = fmt.Sprintf("test setup") method.ControllerName = fmt.Sprintf("%s.%sController", TargetPackage, codegen.Goify(resource.Name, true)) method.ContextVarName = fmt.Sprintf("%sCtx", codegen.Goify(action.Name, false)) method.ContextType = fmt.Sprintf("%s.New%s%sContext", TargetPackage, codegen.Goify(action.Name, true), codegen.Goify(resource.Name, true)) method.RouteVerb = route.Verb method.Status = response.Status method.FullPath = goPathFormat(route.FullPath()) if view != nil && mediaType != nil { p, _, err := mediaType.Project(view.Name) if err != nil { panic(err) } tmp := codegen.GoTypeName(p, nil, 0, false) if !p.IsBuiltIn() { tmp = fmt.Sprintf("%s.%s", TargetPackage, tmp) } validate := codegen.RecursiveChecker(p.AttributeDefinition, false, false, false, "payload", "raw", 1, true) returnType := ObjectType{} returnType.Type = tmp returnType.Pointer = "*" returnType.Validatable = validate != "" method.ReturnType = &returnType } if len(route.Params()) > 0 { var params = []ObjectType{} for _, paramName := range route.Params() { for name, att := range action.Params.Type.ToObject() { if name == paramName { param := ObjectType{} param.Name = codegen.Goify(name, false) param.Type = codegen.GoTypeRef(att.Type, nil, 0, false) if att.Type.IsPrimitive() && action.Params.IsPrimitivePointer(name) { param.Pointer = "*" } params = append(params, param) } } } method.Params = params } if action.Payload != nil { payload := ObjectType{} payload.Name = "payload" payload.Type = fmt.Sprintf("%s.%s", TargetPackage, codegen.Goify(action.Payload.TypeName, true)) if !action.Payload.IsPrimitive() && !action.Payload.IsArray() && !action.Payload.IsHash() { payload.Pointer = "*" } validate := codegen.RecursiveChecker(action.Payload.AttributeDefinition, false, false, false, "payload", "raw", 1, true) if validate != "" { payload.Validatable = true } method.Payload = &payload } return method }
action = &design.ActionDefinition{Parent: resource} }) It("does not panic and merges the resource responses", func() { Ω(action.Finalize).ShouldNot(Panic()) Ω(action.Responses).Should(HaveKey("NotFound")) }) }) }) var _ = Describe("FullPath", func() { Context("Given a base resource and a resource with an action with a route", func() { var resource, parentResource *design.ResourceDefinition var action *design.ActionDefinition var route *design.RouteDefinition var actionPath string var resourcePath string var parentResourcePath string JustBeforeEach(func() { showAct := &design.ActionDefinition{} showRoute := &design.RouteDefinition{ Path: parentResourcePath, Parent: showAct, } showAct.Routes = []*design.RouteDefinition{showRoute} parentResource = &design.ResourceDefinition{} parentResource.Actions = map[string]*design.ActionDefinition{"show": showAct} parentResource.Name = "foo"
// pathParams returns the path params for the given action and route. func pathParams(action *design.ActionDefinition, route *design.RouteDefinition) []*ObjectType { return paramFromNames(action, route.Params()) }
func (g *Generator) createTestMethod(resource *design.ResourceDefinition, action *design.ActionDefinition, response *design.ResponseDefinition, route *design.RouteDefinition, routeIndex int, mediaType *design.MediaTypeDefinition, view *design.ViewDefinition) *TestMethod { var ( actionName, ctrlName, varName string routeQualifier, viewQualifier, respQualifier string comment string returnType *ObjectType payload *ObjectType ) actionName = codegen.Goify(action.Name, true) ctrlName = codegen.Goify(resource.Name, true) varName = codegen.Goify(action.Name, false) routeQualifier = suffixRoute(action.Routes, routeIndex) if view != nil && view.Name != "default" { viewQualifier = codegen.Goify(view.Name, true) } respQualifier = codegen.Goify(response.Name, true) hasReturnValue := view != nil && mediaType != nil if hasReturnValue { p, _, err := mediaType.Project(view.Name) if err != nil { panic(err) // bug } tmp := codegen.GoTypeName(p, nil, 0, false) if !p.IsError() { tmp = fmt.Sprintf("%s.%s", g.Target, tmp) } validate := g.validator.Code(p.AttributeDefinition, false, false, false, "payload", "raw", 1, false) returnType = &ObjectType{} returnType.Type = tmp if p.IsObject() && !p.IsError() { returnType.Pointer = "*" } returnType.Validatable = validate != "" } comment = "runs the method " + actionName + " of the given controller with the given parameters" if action.Payload != nil { comment += " and payload" } comment += ".\n// It returns the response writer so it's possible to inspect the response headers" if hasReturnValue { comment += " and the media type struct written to the response" } comment += "." if action.Payload != nil { payload = &ObjectType{} payload.Name = "payload" payload.Type = fmt.Sprintf("%s.%s", g.Target, codegen.Goify(action.Payload.TypeName, true)) if !action.Payload.IsPrimitive() && !action.Payload.IsArray() && !action.Payload.IsHash() { payload.Pointer = "*" } validate := g.validator.Code(action.Payload.AttributeDefinition, false, false, false, "payload", "raw", 1, false) if validate != "" { payload.Validatable = true } } return &TestMethod{ Name: fmt.Sprintf("%s%s%s%s%s", actionName, ctrlName, respQualifier, routeQualifier, viewQualifier), ActionName: actionName, ResourceName: ctrlName, Comment: comment, Params: pathParams(action, route), QueryParams: queryParams(action), Headers: headers(action), Payload: payload, ReturnType: returnType, ReturnsErrorMedia: mediaType == design.ErrorMedia, ControllerName: fmt.Sprintf("%s.%sController", g.Target, ctrlName), ContextVarName: fmt.Sprintf("%sCtx", varName), ContextType: fmt.Sprintf("%s.New%s%sContext", g.Target, actionName, ctrlName), RouteVerb: route.Verb, Status: response.Status, FullPath: goPathFormat(route.FullPath()), } }
func buildPathFromDefinition(s *Swagger, api *design.APIDefinition, route *design.RouteDefinition, basePath string) error { action := route.Parent tagNames := tagNamesFromDefinitions(action.Parent.Metadata, action.Metadata) if len(tagNames) == 0 { // By default tag with resource name tagNames = []string{route.Parent.Parent.Name} } params, err := paramsFromDefinition(action.AllParams(), route.FullPath()) if err != nil { return err } params = append(params, paramsFromHeaders(action)...) responses := make(map[string]*Response, len(action.Responses)) for _, r := range action.Responses { resp, err := responseFromDefinition(s, api, r) if err != nil { return err } responses[strconv.Itoa(r.Status)] = resp } if action.Payload != nil { payloadSchema := genschema.TypeSchema(api, action.Payload) pp := &Parameter{ Name: "payload", In: "body", Description: action.Payload.Description, Required: !action.PayloadOptional, Schema: payloadSchema, } params = append(params, pp) } operationID := fmt.Sprintf("%s#%s", action.Parent.Name, action.Name) index := 0 for i, rt := range action.Routes { if rt == route { index = i break } } if index > 0 { operationID = fmt.Sprintf("%s#%d", operationID, index) } schemes := action.Schemes if len(schemes) == 0 { schemes = api.Schemes } operation := &Operation{ Tags: tagNames, Description: action.Description, Summary: summaryFromDefinition(action.Name+" "+action.Parent.Name, action.Metadata), ExternalDocs: docsFromDefinition(action.Docs), OperationID: operationID, Parameters: params, Responses: responses, Schemes: schemes, Deprecated: false, Extensions: extensionsFromDefinition(route.Metadata), } applySecurity(operation, action.Security) key := design.WildcardRegex.ReplaceAllStringFunc( route.FullPath(), func(w string) string { return fmt.Sprintf("/{%s}", w[2:]) }, ) if key == "" { key = "/" } bp := design.WildcardRegex.ReplaceAllStringFunc( basePath, func(w string) string { return fmt.Sprintf("/{%s}", w[2:]) }, ) if bp != "/" { key = strings.TrimPrefix(key, bp) } var path interface{} var ok bool if path, ok = s.Paths[key]; !ok { path = new(Path) s.Paths[key] = path } p := path.(*Path) switch route.Verb { case "GET": p.Get = operation case "PUT": p.Put = operation case "POST": p.Post = operation case "DELETE": p.Delete = operation case "OPTIONS": p.Options = operation case "HEAD": p.Head = operation case "PATCH": p.Patch = operation } p.Extensions = extensionsFromDefinition(route.Parent.Metadata) return nil }