github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/cmd/protoc-gen-openapi/converter/service.go (about)

     1  package converter
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/getkin/kin-openapi/openapi3"
     7  	"github.com/golang/protobuf/protoc-gen-go/descriptor"
     8  	"github.com/tickoalcantara12/micro/v3/service/logger"
     9  )
    10  
    11  // Converts a proto "SERVICE" into an OpenAPI path:
    12  func (c *Converter) convertServiceType(file *descriptor.FileDescriptorProto, curPkg *ProtoPackage, svc *descriptor.ServiceDescriptorProto) (map[string]*openapi3.PathItem, error) {
    13  	pathItems := make(map[string]*openapi3.PathItem)
    14  
    15  	// Add a path item for each method in the service:
    16  	for _, method := range svc.GetMethod() {
    17  		logger.Debugf("Processing method %s.%s()", svc.GetName(), method.GetName())
    18  
    19  		// Figure out the URL path:
    20  		path := urlPath(c.microServiceName, svc.GetName(), method.GetName())
    21  
    22  		// We need to reformat the request name to match what is produced by the message converter:
    23  		requestPayloadSchemaName := protoServiceName(*method.InputType)
    24  
    25  		// See if we can get the request paylod schema:
    26  		if _, ok := c.openAPISpec.Components.Schemas[requestPayloadSchemaName]; !ok {
    27  			logger.Warnf("Couldn't find request body payload (%s)", requestPayloadSchemaName)
    28  			continue
    29  		}
    30  
    31  		// Make a request body:
    32  		requestBodyName := requestBodyName(svc.GetName(), method.GetName())
    33  		requestBody := &openapi3.RequestBodyRef{
    34  			Value: &openapi3.RequestBody{
    35  				Content: openapi3.Content{
    36  					"application/json": &openapi3.MediaType{
    37  						Schema: &openapi3.SchemaRef{
    38  							Ref: messageSchemaPath(requestPayloadSchemaName),
    39  						},
    40  					},
    41  				},
    42  				Description: requestBodyName,
    43  			},
    44  		}
    45  
    46  		// Add it to the spec:
    47  		c.openAPISpec.Components.RequestBodies[requestBodyName] = requestBody
    48  
    49  		// We need to reformat the response name to match what is produced by the message converter:
    50  		responsePayloadSchemaName := protoServiceName(*method.OutputType)
    51  
    52  		// See if we can get the response paylod schema:
    53  		if _, ok := c.openAPISpec.Components.Schemas[responsePayloadSchemaName]; !ok {
    54  			logger.Warnf("Couldn't find response body payload (%s)", responsePayloadSchemaName)
    55  			continue
    56  		}
    57  
    58  		// Make a response body:
    59  		responseBodyName := responseBodyName(svc.GetName(), method.GetName())
    60  		responseBody := &openapi3.ResponseRef{
    61  			Value: &openapi3.Response{
    62  				Content: openapi3.Content{
    63  					"application/json": &openapi3.MediaType{
    64  						Schema: &openapi3.SchemaRef{
    65  							Ref: messageSchemaPath(responsePayloadSchemaName),
    66  						},
    67  					},
    68  				},
    69  				Description: &responseBodyName,
    70  			},
    71  		}
    72  
    73  		// Add it to the spec:
    74  		c.openAPISpec.Components.Responses[responseBodyName] = responseBody
    75  
    76  		// Prepare a path item based on these payloads:
    77  		pathItem := &openapi3.PathItem{
    78  			Parameters: openapi3.Parameters{
    79  				{
    80  					Value: &openapi3.Parameter{
    81  						In:       "header",
    82  						Name:     "Micro-Namespace",
    83  						Required: true,
    84  						Schema: &openapi3.SchemaRef{
    85  							Value: &openapi3.Schema{
    86  								Type:    "string",
    87  								Default: "micro",
    88  							},
    89  						},
    90  					},
    91  				},
    92  			},
    93  			Post: &openapi3.Operation{
    94  				RequestBody: &openapi3.RequestBodyRef{
    95  					Ref: requestBodySchemaPath(requestBodyName),
    96  				},
    97  				Responses: openapi3.Responses{
    98  					"default": &openapi3.ResponseRef{
    99  						Ref: responseBodySchemaPath("MicroAPIError"),
   100  					},
   101  					"200": &openapi3.ResponseRef{
   102  						Ref: responseBodySchemaPath(responseBodyName),
   103  					},
   104  				},
   105  				Security: &openapi3.SecurityRequirements{
   106  					{
   107  						"MicroAPIToken": []string{},
   108  					},
   109  				},
   110  				Summary: fmt.Sprintf("%s.%s(%s)", svc.GetName(), method.GetName(), requestPayloadSchemaName),
   111  			},
   112  		}
   113  
   114  		// check if it's a streaming response
   115  		if method.GetServerStreaming() {
   116  			pathItem.Post.Responses["stream"] = &openapi3.ResponseRef{
   117  				Ref: responseBodySchemaPath(responseBodyName),
   118  			}
   119  		}
   120  
   121  		// TODO: check for method.GetClientStreaming()
   122  
   123  		// Generate a description from src comments (if available)
   124  		if src := c.sourceInfo.GetService(svc); src != nil {
   125  			pathItem.Description = formatDescription(src)
   126  		}
   127  
   128  		pathItems[path] = pathItem
   129  	}
   130  
   131  	return pathItems, nil
   132  }