Skip to content

Commit

Permalink
Fixing HTTP content negotiation for .NET
Browse files Browse the repository at this point in the history
  • Loading branch information
fabiocav committed Nov 10, 2016
1 parent 9f766c1 commit 96abcf5
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 18 deletions.
16 changes: 8 additions & 8 deletions src/WebJobs.Script/Binding/HttpBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -156,19 +156,20 @@ private static HttpContent CreateResultContent(object content, string mediaType)

private static HttpResponseMessage CreateNegotiatedResponse(HttpRequestMessage request, HttpStatusCode statusCode, object content)
{
HttpResponseMessage result = request.CreateResponse(statusCode);

if (content == null)
{
return request.CreateResponse(statusCode);
return result;
}

var configuration = request.GetConfiguration();
IContentNegotiator negotiator = configuration.Services.GetContentNegotiator();
var result = negotiator.Negotiate(content.GetType(), request, configuration.Formatters);
var negotiationResult = negotiator.Negotiate(content.GetType(), request, configuration.Formatters);

return new HttpResponseMessage(statusCode)
{
Content = new ObjectContent(content.GetType(), content, result.Formatter, result.MediaType)
};
result.Content = new ObjectContent(content.GetType(), content, negotiationResult.Formatter, negotiationResult.MediaType);

return result;
}

public void ProcessResult(IDictionary<string, object> functionArguments, object[] systemArguments, string triggerInputName, object result)
Expand All @@ -184,8 +185,7 @@ public void ProcessResult(IDictionary<string, object> functionArguments, object[
HttpResponseMessage response = result as HttpResponseMessage;
if (response == null)
{
response = request.CreateResponse(HttpStatusCode.OK);
response.Content = new ObjectContent(result.GetType(), result, new JsonMediaTypeFormatter());
response = CreateNegotiatedResponse(request, HttpStatusCode.OK, result);
}

request.Properties[ScriptConstants.AzureFunctionsHttpResponseKey] = response;
Expand Down
41 changes: 40 additions & 1 deletion test/WebJobs.Script.Tests/CSharpEndToEndTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,8 @@ public async Task HttpTrigger_Post_Dynamic()
Method = HttpMethod.Post,
Content = new StringContent(input.ToString())
};
request.SetConfiguration(new HttpConfiguration());
request.SetConfiguration(Fixture.RequestConfiguration);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain"));
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

Dictionary<string, object> arguments = new Dictionary<string, object>
Expand All @@ -283,6 +284,44 @@ public async Task HttpTrigger_Post_Dynamic()
Assert.Equal("Name: Mathew Charles, Location: Seattle", body);
}

[Theory]
[InlineData("application/json", "\"Name: Fabio Cavalcante, Location: Seattle\"")]
[InlineData("application/xml", "<string xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/\">Name: Fabio Cavalcante, Location: Seattle</string>")]
[InlineData("text/plain", "Name: Fabio Cavalcante, Location: Seattle")]
public async Task HttpTrigger_GetWithAccept_NegotiatesContent(string accept, string expectedBody)
{
var input = new JObject
{
{ "name", "Fabio Cavalcante" },
{ "location", "Seattle" }
};

HttpRequestMessage request = new HttpRequestMessage
{
RequestUri = new Uri(string.Format("http://localhost/api/httptrigger-dynamic")),
Method = HttpMethod.Post,
Content = new StringContent(input.ToString())
};
request.SetConfiguration(Fixture.RequestConfiguration);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(accept));
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

Dictionary<string, object> arguments = new Dictionary<string, object>
{
{ "input", request },
{ ScriptConstants.SystemTriggerParameterName, request }
};

await Fixture.Host.CallAsync("HttpTrigger-Dynamic", arguments);

HttpResponseMessage response = (HttpResponseMessage)request.Properties[ScriptConstants.AzureFunctionsHttpResponseKey];
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal(accept, response.Content.Headers.ContentType.MediaType);

string body = await response.Content.ReadAsStringAsync();
Assert.Equal(expectedBody, body);
}

public class TestFixture : EndToEndTestFixture
{
private const string ScriptRoot = @"TestScripts\CSharp";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
using System;
using System.Net;
using System.Net.Http;

public static HttpResponseMessage Run(dynamic input)
public static string Run(dynamic input)
{
return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent($"Name: {input.name}, Location: {input.location}")
};
return $"Name: {input.name}, Location: {input.location}";
}

0 comments on commit 96abcf5

Please sign in to comment.