Beispiel #1
0
// 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, ", ")
}
Beispiel #2
0
// 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)
}
Beispiel #3
0
// 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...)
}
Beispiel #4
0
// 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")
}
Beispiel #5
0
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
}
Beispiel #6
0
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"
Beispiel #8
0
// 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())
}
Beispiel #9
0
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()),
	}
}
Beispiel #10
0
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
}