Skip to content

Commit 658d4d0

Browse files
author
Matt Mason
committed
Add null body handling for content headers
1 parent 6f7f822 commit 658d4d0

File tree

3 files changed

+45
-14
lines changed

3 files changed

+45
-14
lines changed

src/WebJobs.Script/Binding/HttpBinding.cs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -289,57 +289,63 @@ internal static void AddResponseHeader(HttpResponseMessage response, KeyValuePai
289289
// content header collection
290290
case "content-type":
291291
MediaTypeHeaderValue mediaType = null;
292-
if (MediaTypeHeaderValue.TryParse(header.Value.ToString(), out mediaType))
292+
if (response.Content != null && MediaTypeHeaderValue.TryParse(header.Value.ToString(), out mediaType))
293293
{
294294
response.Content.Headers.ContentType = mediaType;
295295
}
296296
break;
297297
case "content-length":
298298
long contentLength;
299-
if (long.TryParse(header.Value.ToString(), out contentLength))
299+
if (response.Content != null && long.TryParse(header.Value.ToString(), out contentLength))
300300
{
301301
response.Content.Headers.ContentLength = contentLength;
302302
}
303303
break;
304304
case "content-disposition":
305305
ContentDispositionHeaderValue contentDisposition = null;
306-
if (ContentDispositionHeaderValue.TryParse(header.Value.ToString(), out contentDisposition))
306+
if (response.Content != null && ContentDispositionHeaderValue.TryParse(header.Value.ToString(), out contentDisposition))
307307
{
308308
response.Content.Headers.ContentDisposition = contentDisposition;
309309
}
310310
break;
311311
case "content-encoding":
312312
case "content-language":
313313
case "content-range":
314-
response.Content.Headers.Add(header.Key, header.Value.ToString());
314+
if (response.Content != null)
315+
{
316+
response.Content.Headers.Add(header.Key, header.Value.ToString());
317+
}
315318
break;
316319
case "content-location":
317320
Uri uri;
318-
if (Uri.TryCreate(header.Value.ToString(), UriKind.Absolute, out uri))
321+
if (response.Content != null && Uri.TryCreate(header.Value.ToString(), UriKind.Absolute, out uri))
319322
{
320323
response.Content.Headers.ContentLocation = uri;
321324
}
322325
break;
323326
case "content-md5":
324327
byte[] value;
325-
if (header.Value is string)
326-
{
327-
value = Convert.FromBase64String((string)header.Value);
328-
}
329-
else
328+
if (response.Content != null)
330329
{
331-
value = header.Value as byte[];
330+
if (header.Value is string)
331+
{
332+
value = Convert.FromBase64String((string)header.Value);
333+
}
334+
else
335+
{
336+
value = header.Value as byte[];
337+
}
338+
response.Content.Headers.ContentMD5 = value;
332339
}
333-
response.Content.Headers.ContentMD5 = value;
334340
break;
335341
case "expires":
336-
if (DateTimeOffset.TryParse(header.Value.ToString(), out dateTimeOffset))
342+
if (response.Content != null && DateTimeOffset.TryParse(header.Value.ToString(), out dateTimeOffset))
337343
{
338344
response.Content.Headers.Expires = dateTimeOffset;
339345
}
340346
break;
341347
case "last-modified":
342-
if (DateTimeOffset.TryParse(header.Value.ToString(), out dateTimeOffset))
348+
if (response.Content != null && DateTimeOffset.TryParse(header.Value.ToString(), out dateTimeOffset))
343349
{
344350
response.Content.Headers.LastModified = dateTimeOffset;
345351
}

test/WebJobs.Script.Tests.Integration/NodeEndToEndTests.cs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,27 @@ public async Task HttpTrigger_Scenarios_ResBinding()
605605
Assert.Equal("test", await response.Content.ReadAsAsync<string>());
606606
}
607607

608+
[Fact]
609+
public async Task HttpTrigger_Scenarios_NullBody()
610+
{
611+
HttpRequestMessage request = new HttpRequestMessage
612+
{
613+
RequestUri = new Uri(string.Format("http://localhost/api/httptrigger-scenarios")),
614+
Method = HttpMethod.Post,
615+
};
616+
request.SetConfiguration(new HttpConfiguration());
617+
request.Headers.Add("scenario", "nullbody");
618+
Dictionary<string, object> arguments = new Dictionary<string, object>
619+
{
620+
{ "req", request }
621+
};
622+
await Fixture.Host.CallAsync("HttpTrigger-Scenarios", arguments);
623+
624+
HttpResponseMessage response = (HttpResponseMessage)request.Properties[ScriptConstants.AzureFunctionsHttpResponseKey];
625+
Assert.Equal(HttpStatusCode.NoContent, response.StatusCode);
626+
Assert.Null(response.Content);
627+
}
628+
608629
[Fact]
609630
public async Task HttpTrigger_Scenarios_ScalarReturn_InBody()
610631
{

test/WebJobs.Script.Tests.Integration/TestScripts/Node/HttpTrigger-Scenarios/index.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ module.exports = function (context, req) {
4545
context.bindings.res = { status: 202, body: "test" };
4646
break;
4747

48+
case "nullbody":
49+
context.res = { status: 204, body: null, headers: { 'content-type': 'application/json' } };
50+
break;
51+
4852
default:
4953
context.res = {
5054
status: 400

0 commit comments

Comments
 (0)