Skip to content
This repository was archived by the owner on Feb 23, 2024. It is now read-only.

Commit 453c5d6

Browse files
springcompMaxime LABELLERupengLiu
authored
Add an OpenAPI specification format specifier to prevent unnecessarily downloading the service contract (#504)
* #499 - Prevent crash when no products are associated with a particular api. * Do *not* unnecessarily download the OpenAPI definition. Co-authored-by: Maxime LABELLE <maxime.labelle@chanel.com> Co-authored-by: RupengLiu <rliu1211@terpmail.umd.edu>
1 parent fdd5552 commit 453c5d6

File tree

3 files changed

+98
-13
lines changed

3 files changed

+98
-13
lines changed

src/APIM_ARMTemplate/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ The utility requires one argument, --configFile, which points to a yaml file tha
4848
| serviceUrl | string | No | Absolute URL of the backend service implementing this API. |
4949
| type | enum | No | Type of API. - http or soap |
5050
| openApiSpec | string | Yes | Location of the Open API Spec file. Can be url or local file. |
51+
| openApiSpecFormat | string | No | Format of the API definition. When the `openApiSpec` property refers to a local file, the program will infer the format if this property is omitted. If the `openApiSpec` property refers to a url, you can prevent downloading the API definition by specifying this property. Valid values are `Swagger` (JSON), `Swagger_Json`, `OpenApi20` (YAML), `OpenApi20_Yaml`, `OpenApi20_Json`, `OpenApi30` (YAML), `OpenApi30_Yaml`, or `OpenApi30_Json`.
5152
| policy | string | No | Location of the API policy XML file. Can be url or local file. |
5253
| suffix | string | Yes | Relative URL uniquely identifying this API and all of its resource paths within the API Management service instance. It is appended to the API endpoint base URL specified during the service instance creation to form a public URL for this API. |
5354
| subscriptionRequired | boolean | No | Specifies whether an API or Product subscription is required for accessing the API. |
@@ -170,6 +171,7 @@ apis:
170171
description: myFirstAPI
171172
serviceUrl: http://myApiBackendUrl.com
172173
openApiSpec: C:\Users\myUsername\Projects\azure-api-management-devops-example\src\APIM_ARMTemplate\apimtemplate\Creator\ExampleFile\OpenApiSpecs\swaggerPetstore.json
174+
openApiSpecFormat: swagger
173175
policy: C:\Users\myUsername\Projects\azure-api-management-devops-example\src\APIM_ARMTemplate\apimtemplate\Creator\ExampleFiles\XMLPolicies\apiPolicyHeaders.xml
174176
suffix: conf
175177
subscriptionRequired: true

src/APIM_ARMTemplate/apimtemplate/Creator/Models/CreatorConfiguration.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ public class APIConfig
5353
public string type { get; set; }
5454
// openApiSpec file location (local or url), used to build protocols, value, and format from APITemplateResource schema
5555
public string openApiSpec { get; set; }
56+
// format of the API definition.
57+
public OpenApiSpecFormat openApiSpecFormat { get; set; }
5658
// policy file location (local or url)
5759
public string policy { get; set; }
5860
// used to buld path from APITemplateResource schema
@@ -74,6 +76,22 @@ public class APIConfig
7476
// does not currently include subscriptionKeyParameterNames, sourceApiId, and wsdlSelector from APITemplateResource schema
7577
}
7678

79+
public enum OpenApiSpecFormat
80+
{
81+
Unspecified,
82+
83+
Swagger,
84+
Swagger_Json = Swagger,
85+
86+
OpenApi20,
87+
OpenApi20_Yaml = OpenApi20,
88+
OpenApi20_Json,
89+
90+
OpenApi30,
91+
OpenApi30_Yaml = OpenApi30,
92+
OpenApi30_Json,
93+
}
94+
7795
public class OperationsConfig
7896
{
7997
// policy file location (local or url)

src/APIM_ARMTemplate/apimtemplate/Creator/TemplateCreators/APITemplateCreator.cs

Lines changed: 78 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -172,35 +172,43 @@ public async Task<APITemplateResource> CreateAPITemplateResourceAsync(APIConfig
172172
string value;
173173

174174
// determine if the open api spec is remote or local, yaml or json
175-
Uri uriResult;
176-
string fileContents = await this.fileReader.RetrieveFileContentsAsync(api.openApiSpec);
177-
bool isJSON = this.fileReader.isJSON(fileContents);
178-
bool isUrl = Uri.TryCreate(api.openApiSpec, UriKind.Absolute, out uriResult) && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps);
175+
bool isJSON = false;
176+
bool isUrl = IsUri(api, out var _);
177+
178+
string fileContents = null;
179+
if (!isUrl || api.openApiSpecFormat == OpenApiSpecFormat.Unspecified)
180+
fileContents = await this.fileReader.RetrieveFileContentsAsync(api.openApiSpec);
179181

180182
value = isUrl
181183
? api.openApiSpec
182184
: fileContents
183185
;
184186

185187
bool isVersionThree = false;
186-
if (isJSON == true)
188+
if (api.openApiSpecFormat == OpenApiSpecFormat.Unspecified)
187189
{
188-
// open api spec is remote json file, use swagger-link-json for v2 and openapi-link for v3
189-
OpenAPISpecReader openAPISpecReader = new OpenAPISpecReader();
190-
isVersionThree = await openAPISpecReader.isJSONOpenAPISpecVersionThreeAsync(api.openApiSpec);
190+
isJSON = this.fileReader.isJSON(fileContents);
191+
192+
if (isJSON == true)
193+
{
194+
var openAPISpecReader = new OpenAPISpecReader();
195+
isVersionThree = await openAPISpecReader.isJSONOpenAPISpecVersionThreeAsync(api.openApiSpec);
196+
}
197+
format = GetOpenApiSpecFormat(isUrl, isJSON, isVersionThree);
191198
}
192199

193-
format = isUrl
194-
? (isJSON ? (isVersionThree ? "openapi-link" : "swagger-link-json") : "openapi-link")
195-
: (isJSON ? (isVersionThree ? "openapi+json" : "swagger-json") : "openapi")
196-
;
200+
else
201+
{
202+
isJSON = IsOpenApiSpecJson(api.openApiSpecFormat);
203+
format = GetOpenApiSpecFormat(isUrl, api.openApiSpecFormat);
204+
}
197205

198206
// if the title needs to be modified
199207
// we need to embed the OpenAPI definition
200208

201209
if (!string.IsNullOrEmpty(api.displayName))
202210
{
203-
format = (isJSON ? (isVersionThree ? "openapi+json" : "swagger-json") : "openapi");
211+
format = GetOpenApiSpecFormat(false, isJSON, isVersionThree);
204212

205213
// download definition
206214

@@ -217,6 +225,7 @@ public async Task<APITemplateResource> CreateAPITemplateResourceAsync(APIConfig
217225
.GetDefinition()
218226
;
219227
}
228+
220229
// set the version set id
221230
if (api.apiVersionSetId != null)
222231
{
@@ -234,6 +243,62 @@ public async Task<APITemplateResource> CreateAPITemplateResourceAsync(APIConfig
234243
return apiTemplateResource;
235244
}
236245

246+
private static string GetOpenApiSpecFormat(bool isUrl, bool isJSON, bool isVersionThree)
247+
{
248+
return isUrl
249+
? (isJSON ? (isVersionThree ? "openapi-link" : "swagger-link-json") : "openapi-link")
250+
: (isJSON ? (isVersionThree ? "openapi+json" : "swagger-json") : "openapi");
251+
}
252+
253+
private static string GetOpenApiSpecFormat(bool isUrl, OpenApiSpecFormat openApiSpecFormat)
254+
{
255+
switch (openApiSpecFormat)
256+
{
257+
case OpenApiSpecFormat.Swagger_Json:
258+
return isUrl ? "swagger-link-json" : "swagger-json";
259+
260+
case OpenApiSpecFormat.OpenApi20_Yaml:
261+
return isUrl ? "openapi-link" : "openapi";
262+
263+
case OpenApiSpecFormat.OpenApi20_Json:
264+
return isUrl ? "openapi-link" : "swagger-json";
265+
266+
case OpenApiSpecFormat.OpenApi30_Yaml:
267+
return isUrl ? "openapi-link" : "openapi";
268+
269+
case OpenApiSpecFormat.OpenApi30_Json:
270+
return isUrl ? "openapi-link" : "openapi+json";
271+
272+
default:
273+
throw new NotSupportedException();
274+
}
275+
}
276+
private static bool IsOpenApiSpecJson(OpenApiSpecFormat openApiSpecFormat)
277+
{
278+
switch (openApiSpecFormat)
279+
{
280+
case OpenApiSpecFormat.Swagger_Json:
281+
case OpenApiSpecFormat.OpenApi20_Json:
282+
case OpenApiSpecFormat.OpenApi30_Json:
283+
return true;
284+
285+
case OpenApiSpecFormat.OpenApi20_Yaml:
286+
case OpenApiSpecFormat.OpenApi30_Yaml:
287+
return false;
288+
289+
default:
290+
throw new NotSupportedException();
291+
}
292+
}
293+
294+
private static bool IsUri(APIConfig api, out Uri uriResult)
295+
{
296+
return
297+
Uri.TryCreate(api.openApiSpec, UriKind.Absolute, out uriResult) &&
298+
(uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps)
299+
;
300+
}
301+
237302
public static string MakeResourceName(APIConfig api)
238303
{
239304
return $"[concat(parameters('{ParameterNames.ApimServiceName}'), '/{api.name}')]";

0 commit comments

Comments
 (0)