Esempio n. 1
0
func addHandlers(router *httprouter.Router, midl *idl.Idl) error {
	count := 0
	re := regexp.MustCompile(`\{(\w+)\}`)
	for _, svc := range allServices(midl) {
		for _, mth := range svc.Methods {
			count++
			op, err := rest.ReadOp(mth)
			if err != nil {
				log.Fatal("Cannot process %s.%s: %s", svc.Name, mth.Name, err)
			}
			if !op.Hide {
				routePath := re.ReplaceAllString(path.Join(conf.RestPath, op.Path), ":$1")
				handle, err := makeHandler(midl, svc, mth)
				if err != nil {
					return err
				}
				router.Handle(op.Method.String(), routePath, handle)
				log.Printf("%s %s -> %s", op.Method.String(), path.Join(conf.RestPath, op.Path), path.Join(conf.BabelPath, svc.Name, mth.Name))
			}
			babelPath := path.Join(conf.BabelPath, svc.Name, mth.Name)
			if !strings.HasPrefix(babelPath, "/") {
				babelPath = "/" + babelPath
			}
			handle, err := makeBabelHandler(midl, svc, mth)
			if err != nil {
				return err
			}
			router.Handle("POST", babelPath, handle)
			log.Printf("%s %s -> %s", op.Method.String(), babelPath, babelPath)
		}
	}
	if count == 0 {
		log.Fatal("No services to process")
	}

	return nil
}
Esempio n. 2
0
// addRestService adds Swagger service definitions for RESTful services
func addRestService(swag *swagger2.Swagger, midl *idl.Idl, svc *idl.Service) error {
	svcComments := strings.Join(svc.Comments, "\n")

	// sort methods by common paths
	pathmap := make(PathMap)
	for _, mth := range svc.Methods {
		// Read annotations
		op, err := rest.ReadOp(mth)
		if err != nil {
			return err
		}
		if !op.Hide {
			methmap, ok := pathmap[op.Path]
			if !ok {
				methmap = make(HttpMethodMap)
				pathmap[op.Path] = methmap
			}
			if _, ok := methmap[op.Method]; ok {
				return errors.New("The " + op.Method.String() + " method is defined multiple times for the same path of " + op.Path)
			}
			methmap[op.Method] = RestOperation{Annotation: op, IdlMethod: mth}
		}
	}

	// Loop through the paths
	for path, methmap := range pathmap {
		var p swagger2.PathItem

		for httpmethod, restop := range methmap {
			op := new(swagger2.Operation)
			switch httpmethod {
			case rest.GET:
				p.Get = op
			case rest.PUT:
				p.Put = op
			case rest.POST:
				p.Post = op
			case rest.DELETE:
				p.Delete = op
			case rest.OPTIONS:
				p.Options = op
			case rest.HEAD:
				p.Head = op
			case rest.PATCH:
				p.Patch = op
			}
			op.Tags = []string{svc.Name}
			mthComments := strings.Join(restop.IdlMethod.Comments, "\n")
			theseArgs := make([]string, 0)
			for _, s := range restop.IdlMethod.Parameters {
				// SWAGGER-BUG: Swagger should be HTML escaping this
				theseArgs = append(theseArgs, html.EscapeString(s.Type.String())+" "+s.Name)
			}
			// SWAGGER-BUG: Swagger should be HTML escaping this
			op.Description = html.EscapeString(restop.IdlMethod.Returns.String()) + " " + restop.IdlMethod.Name + "(" + strings.Join(theseArgs, ", ") + ")"
			if mthComments != "" {
				op.Description += "\n\n" + mthComments
			}
			if svcComments != "" {
				op.Description += "\n\n" + svc.Name + ": " + svcComments
			}
			op.OperationId = svc.Name + "_" + restop.IdlMethod.Name
			op.Summary = svc.Name + "." + restop.IdlMethod.Name
			op.Deprecated = restop.Annotation.Deprecated

			// Add parameters
			op.Parameters = make([]swagger2.Parameter, 0)
			for _, fld := range restop.IdlMethod.Parameters {
				parm, err := rest.ReadParm(fld)
				if err != nil {
					return err
				}
				var p *swagger2.Parameter
				if parm.In == rest.BODY {
					p = fieldToBodyParm(midl, fld)
				} else {
					p = fieldToParm(midl, fld)
				}
				if parm.Name != "" {
					p.Name = parm.Name
				}
				p.In = strings.ToLower(parm.In.String())
				if parm.Format != rest.NONE {
					p.Format = strings.ToLower(parm.Format.String())
				}
				if parm.Required == true {
					p.Required = new(bool)
					*p.Required = parm.Required
				}
				op.Parameters = append(op.Parameters, *p)
			}

			// Add responses
			op.Responses = make(swagger2.Responses, 0)
			for statuscode, resp := range restop.Annotation.Responses {
				strcode := strconv.Itoa(statuscode)
				if statuscode <= 0 {
					strcode = "default"
				}
				desc := resp.Desc
				if desc == "" {
					desc = "Response of type " + html.EscapeString(resp.Type.String())
				}
				theResp := swagger2.Response{
					Description: desc,
					Schema:      returnsToSchema(midl, resp.Type),
					Headers:     make(swagger2.Headers),
				}
				// Headers
				// SWAGGER-BUG: Swagger-ui doesn't show response headers
				for hdrname, hdr := range resp.Headers {
					theHeader := swagger2.Header{
						Description: hdr.Desc,
						ItemsDef:    *typeToItems(midl, hdr.Type),
					}
					if hdr.Format != rest.NONE {
						theHeader.ItemsDef.CollectionFormat = strings.ToLower(hdr.Format.String())
					}
					theResp.Headers[hdrname] = theHeader
				}
				op.Responses[strcode] = theResp
			}
		}
		swag.Paths[path] = p
	}

	return nil
}