Skip to content

Commit a589416

Browse files
'produces' at operation level must override one specified at global level
1 parent 578e587 commit a589416

File tree

7 files changed

+192
-67
lines changed

7 files changed

+192
-67
lines changed

src/Microsoft.OpenApi.Readers/ParsingContext.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ public string GetLocation()
146146
/// <summary>
147147
/// Gets the value from the temporary storage matching the given key.
148148
/// </summary>
149-
public T GetFromTempStorage<T>(string key, object scope = null) where T : class
149+
public T GetFromTempStorage<T>(string key, object scope = null)
150150
{
151151
Dictionary<string, object> storage;
152152

@@ -156,10 +156,10 @@ public T GetFromTempStorage<T>(string key, object scope = null) where T : class
156156
}
157157
else if (!_scopedTempStorage.TryGetValue(scope, out storage))
158158
{
159-
return null;
159+
return default(T);
160160
}
161161

162-
return storage.TryGetValue(key, out var value) ? (T)value : null;
162+
return storage.TryGetValue(key, out var value) ? (T)value : default(T);
163163
}
164164

165165
/// <summary>

src/Microsoft.OpenApi.Readers/V2/OpenApiResponseDeserializer.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,18 @@ internal static partial class OpenApiV2Deserializer
6262

6363
private static void ProcessProduces(MapNode mapNode, OpenApiResponse response, ParsingContext context)
6464
{
65-
var produces = context.GetFromTempStorage<List<string>>(TempStorageKeys.OperationProduces) ??
66-
context.GetFromTempStorage<List<string>>(TempStorageKeys.GlobalProduces);
67-
6865
if (response.Content == null)
6966
{
7067
response.Content = new Dictionary<string, OpenApiMediaType>();
7168
}
69+
else if (context.GetFromTempStorage<bool>(TempStorageKeys.ResponseProducesSet, response))
70+
{
71+
// Process "produces" only once since once specified at operation level it cannot be overriden.
72+
return;
73+
}
7274

75+
var produces = context.GetFromTempStorage<List<string>>(TempStorageKeys.OperationProduces)
76+
?? context.GetFromTempStorage<List<string>>(TempStorageKeys.GlobalProduces);
7377
if (produces != null)
7478
{
7579
foreach (var produce in produces)
@@ -96,6 +100,7 @@ private static void ProcessProduces(MapNode mapNode, OpenApiResponse response, P
96100
}
97101

98102
context.SetTempStorage(TempStorageKeys.ResponseSchema, null, response);
103+
context.SetTempStorage(TempStorageKeys.ResponseProducesSet, true, response);
99104
}
100105
}
101106

@@ -124,7 +129,10 @@ private static void LoadExample(OpenApiResponse response, string mediaType, Pars
124129
}
125130
else
126131
{
127-
mediaTypeObject = new OpenApiMediaType();
132+
mediaTypeObject = new OpenApiMediaType
133+
{
134+
Schema = node.Context.GetFromTempStorage<OpenApiSchema>(TempStorageKeys.ResponseSchema, response)
135+
};
128136
response.Content.Add(mediaType, mediaTypeObject);
129137
}
130138

src/Microsoft.OpenApi.Readers/V2/TempStorageKeys.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ internal static class TempStorageKeys
1212
public const string BodyParameter = "bodyParameter";
1313
public const string FormParameters = "formParameters";
1414
public const string OperationProduces = "operationProduces";
15+
public const string ResponseProducesSet = "responseProducesSet";
1516
public const string OperationConsumes = "operationConsumes";
1617
public const string GlobalConsumes = "globalConsumes";
1718
public const string GlobalProduces = "globalProduces";

test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiDocumentTests.cs

Lines changed: 162 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -155,23 +155,25 @@ public void ShouldParseProducesInAnyOrder()
155155
var reader = new OpenApiStreamReader();
156156
var doc = reader.Read(stream, out var diagnostic);
157157

158-
Assert.NotNull(doc.Paths["/items"]);
159-
Assert.Equal(3, doc.Paths["/items"].Operations.Count);
160-
161158
var successSchema = new OpenApiSchema()
162159
{
163160
Type = "array",
161+
Reference = new OpenApiReference
162+
{
163+
Type = ReferenceType.Schema,
164+
Id = "Item"
165+
},
164166
Items = new OpenApiSchema()
165167
{
166-
Properties = new Dictionary<string, OpenApiSchema>()
167-
{
168-
{ "id", new OpenApiSchema()
169-
{
170-
Type = "string",
171-
Description = "Item identifier."
172-
}
173-
}
174-
},
168+
//Properties = new Dictionary<string, OpenApiSchema>()
169+
// {
170+
// { "id", new OpenApiSchema()
171+
// {
172+
// Type = "string",
173+
// Description = "Item identifier."
174+
// }
175+
// }
176+
// },
175177
Reference = new OpenApiReference()
176178
{
177179
Type = ReferenceType.Schema,
@@ -180,67 +182,168 @@ public void ShouldParseProducesInAnyOrder()
180182
}
181183
};
182184

183-
var errorSchema = new OpenApiSchema()
185+
var okSchema = new OpenApiSchema()
184186
{
187+
Reference = new OpenApiReference
188+
{
189+
Type = ReferenceType.Schema,
190+
Id = "Item"
191+
},
185192
Properties = new Dictionary<string, OpenApiSchema>()
186-
{
187-
{ "code", new OpenApiSchema()
188-
{
189-
Type = "integer",
190-
Format = "int32"
191-
}
192-
},
193-
{ "message", new OpenApiSchema()
194-
{
195-
Type = "string"
196-
}
197-
},
198-
{ "fields", new OpenApiSchema()
199-
{
200-
Type = "string"
201-
}
202-
}
203-
},
204-
Reference = new OpenApiReference()
193+
{
194+
{ "id", new OpenApiSchema()
195+
{
196+
Type = "string",
197+
Description = "Item identifier."
198+
}
199+
}
200+
}
201+
};
202+
203+
var errorSchema = new OpenApiSchema()
204+
{
205+
Reference = new OpenApiReference
205206
{
206207
Type = ReferenceType.Schema,
207208
Id = "Error"
208-
}
209+
},
210+
Properties = new Dictionary<string, OpenApiSchema>()
211+
{
212+
{ "code", new OpenApiSchema()
213+
{
214+
Type = "integer",
215+
Format = "int32"
216+
}
217+
},
218+
{ "message", new OpenApiSchema()
219+
{
220+
Type = "string"
221+
}
222+
},
223+
{ "fields", new OpenApiSchema()
224+
{
225+
Type = "string"
226+
}
227+
}
228+
}
209229
};
210230

211-
foreach (var operation in doc.Paths["/items"].Operations)
231+
var okMediaType = new OpenApiMediaType
212232
{
213-
Assert.Equal(2, operation.Value.Responses.Count);
214-
215-
var okResponse = operation.Value.Responses["200"];
216-
okResponse.ShouldBeEquivalentTo(
217-
new OpenApiResponse()
218-
{
219-
Description = "An OK response",
220-
Content = GetMediaTypes(successSchema, operation.Key != OperationType.Post)
221-
});
233+
Schema = new OpenApiSchema
234+
{
235+
Type = "array",
236+
Items = okSchema
237+
}
238+
};
222239

223-
var errorResponse = operation.Value.Responses["default"];
224-
errorResponse.ShouldBeEquivalentTo(
225-
new OpenApiResponse()
226-
{
227-
Description = "An error response",
228-
Content = GetMediaTypes(errorSchema, operation.Key != OperationType.Post)
229-
});
230-
}
240+
var errorMediaType = new OpenApiMediaType
241+
{
242+
Schema = errorSchema
243+
};
231244

232-
IDictionary<string, OpenApiMediaType> GetMediaTypes(OpenApiSchema schema, bool includeXml)
245+
doc.ShouldBeEquivalentTo(new OpenApiDocument
233246
{
234-
var mediaTypes = new Dictionary<string, OpenApiMediaType>
247+
Info = new OpenApiInfo
235248
{
236-
["application/json"] = new OpenApiMediaType() { Schema = schema }
237-
};
238-
if (includeXml)
249+
Title = "Two responses",
250+
Version = "1.0.0"
251+
},
252+
Servers =
239253
{
240-
mediaTypes["application/xml"] = new OpenApiMediaType() { Schema = schema };
254+
new OpenApiServer
255+
{
256+
Url = "https://"
257+
}
258+
},
259+
Paths = new OpenApiPaths
260+
{
261+
["/items"] = new OpenApiPathItem
262+
{
263+
Operations =
264+
{
265+
[OperationType.Get] = new OpenApiOperation
266+
{
267+
Responses =
268+
{
269+
["200"] = new OpenApiResponse
270+
{
271+
Description = "An OK response",
272+
Content =
273+
{
274+
["application/json"] = okMediaType,
275+
["application/xml"] = okMediaType,
276+
}
277+
},
278+
["default"] = new OpenApiResponse
279+
{
280+
Description = "An error response",
281+
Content =
282+
{
283+
["application/json"] = errorMediaType,
284+
["application/xml"] = errorMediaType
285+
}
286+
}
287+
}
288+
},
289+
[OperationType.Post] = new OpenApiOperation
290+
{
291+
Responses =
292+
{
293+
["200"] = new OpenApiResponse
294+
{
295+
Description = "An OK response",
296+
Content =
297+
{
298+
["html/text"] = okMediaType
299+
}
300+
},
301+
["default"] = new OpenApiResponse
302+
{
303+
Description = "An error response",
304+
Content =
305+
{
306+
["html/text"] = errorMediaType
307+
}
308+
}
309+
}
310+
},
311+
[OperationType.Patch] = new OpenApiOperation
312+
{
313+
Responses =
314+
{
315+
["200"] = new OpenApiResponse
316+
{
317+
Description = "An OK response",
318+
Content =
319+
{
320+
["application/json"] = okMediaType,
321+
["application/xml"] = okMediaType,
322+
}
323+
},
324+
["default"] = new OpenApiResponse
325+
{
326+
Description = "An error response",
327+
Content =
328+
{
329+
["application/json"] = errorMediaType,
330+
["application/xml"] = errorMediaType
331+
}
332+
}
333+
}
334+
}
335+
}
336+
}
337+
},
338+
Components = new OpenApiComponents
339+
{
340+
Schemas =
341+
{
342+
["Item"] = okSchema,
343+
["Error"] = errorSchema
344+
}
241345
}
242-
return mediaTypes;
243-
}
346+
});
244347
}
245348
}
246349

test/Microsoft.OpenApi.Readers.Tests/V2Tests/OpenApiOperationTests.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,18 @@ public void ParseOperationWithResponseExamplesShouldSucceed()
352352
new OpenApiFloat(6),
353353
new OpenApiFloat(7),
354354
}
355+
},
356+
["application/xml"] = new OpenApiMediaType()
357+
{
358+
Schema = new OpenApiSchema()
359+
{
360+
Type = "array",
361+
Items = new OpenApiSchema()
362+
{
363+
Type = "number",
364+
Format = "float"
365+
}
366+
}
355367
}
356368
}
357369
}}

test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/OpenApiOperation/operationWithResponseExamples.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
produces:
22
- application/json
3+
- application/xml
34
responses:
45
200:
56
description: An array of float response

test/Microsoft.OpenApi.Readers.Tests/V2Tests/Samples/twoResponses.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878
}
7979
},
8080
"produces": [
81-
"application/json"
81+
"html/text"
8282
],
8383
"definitions": {
8484
"Item": {

0 commit comments

Comments
 (0)