Skip to content

Commit

Permalink
Default Content-Type to application/json for JSON responses
Browse files Browse the repository at this point in the history
  • Loading branch information
mathewc committed Mar 29, 2016
1 parent ea27cc0 commit 807cf0b
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 15 deletions.
7 changes: 6 additions & 1 deletion sample/WebHook-Generic-CSharp/run.csx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ using System;
using System.Net;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public static async Task<object> Run(HttpRequestMessage req, TraceWriter log)
{
string json = await req.Content.ReadAsStringAsync();
Payload payload = JsonConvert.DeserializeObject<Payload>(json);

return req.CreateResponse(HttpStatusCode.OK, $"Value: {payload.Value}");
JObject body = new JObject()
{
{ "result", $"Value: {payload.Value}" }
};
return req.CreateResponse(HttpStatusCode.OK, body, "application/json");
}

public class Payload
Expand Down
4 changes: 3 additions & 1 deletion sample/WebHook-Generic/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
module.exports = function (context, data) {
context.log('Webhook was triggered!');
context.res = {
body: 'WebHook processed successfully! ' + data.a
body: {
result: 'Value: ' + data.value
}
};
context.done();
}
8 changes: 8 additions & 0 deletions src/WebJobs.Script/Binding/HttpBinding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,14 @@ public override async Task BindAsync(BindingContext context)
response = new HttpResponseMessage(statusCode);
response.Content = new StringContent(body);

// we default the Content-Type here, but we override below with any
// Content-Type header the user might have set themselves
if (Utility.IsJson(body))
{
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
}

// apply any user specified headers
JObject headers = (JObject)jsonObject["headers"];
if (headers != null)
{
Expand Down
2 changes: 1 addition & 1 deletion src/WebJobs.Script/Description/NodeFunctionInvoker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -395,7 +395,7 @@ private bool TryDeserializeJsonObject(string json, out Dictionary<string, object
{
result = null;

if (!IsJson(json))
if (!Utility.IsJson(json))
{
return false;
}
Expand Down
9 changes: 1 addition & 8 deletions src/WebJobs.Script/Description/ScriptFunctionInvokerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ protected static Dictionary<string, string> GetBindingData(object value, IBinder
// if the input value is a JSON string, extract additional
// binding data from it
string json = value as string;
if (!string.IsNullOrEmpty(json) && IsJson(json))
if (!string.IsNullOrEmpty(json) && Utility.IsJson(json))
{
// parse the object skipping any nested objects (binding data
// only includes top level properties)
Expand Down Expand Up @@ -155,13 +155,6 @@ protected static void ApplyAmbientBindingData(IBinderEx binder, IDictionary<stri
}
}

protected static bool IsJson(string input)
{
input = input.Trim();
return (input.StartsWith("{", StringComparison.OrdinalIgnoreCase) && input.EndsWith("}", StringComparison.OrdinalIgnoreCase))
|| (input.StartsWith("[", StringComparison.OrdinalIgnoreCase) && input.EndsWith("]", StringComparison.OrdinalIgnoreCase));
}

protected virtual void Dispose(bool disposing)
{
if (!_disposed)
Expand Down
7 changes: 7 additions & 0 deletions src/WebJobs.Script/Utility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,12 @@ public static string GetAppSettingOrEnvironmentValue(string name)

return null;
}

public static bool IsJson(string input)
{
input = input.Trim();
return (input.StartsWith("{", StringComparison.OrdinalIgnoreCase) && input.EndsWith("}", StringComparison.OrdinalIgnoreCase))
|| (input.StartsWith("[", StringComparison.OrdinalIgnoreCase) && input.EndsWith("]", StringComparison.OrdinalIgnoreCase));
}
}
}
30 changes: 26 additions & 4 deletions test/WebJobs.Script.Tests/SamplesEndToEndTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ public async Task HttpTrigger_Get_Succeeds()
HttpResponseMessage response = await this._fixture.HttpClient.SendAsync(request);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
string body = await response.Content.ReadAsStringAsync();
Assert.Equal("text/plain", response.Content.Headers.ContentType.MediaType);
Assert.Equal("Hello Mathew", body);
}

Expand All @@ -93,18 +94,36 @@ public async Task HttpTrigger_Disabled_SucceedsWithAdminKey()
Assert.Equal("Hello World!", body);
}

[Fact]
public async Task GenericWebHook_CSharp_Post_Succeeds()
{
string uri = "api/webhook-generic-csharp?code=827bdzxhqy3xc62cxa2hmfsh6gxzhg30s5pi64tu";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
request.Content = new StringContent("{ 'Value': 'Foobar' }");
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

HttpResponseMessage response = await this._fixture.HttpClient.SendAsync(request);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType);
string body = await response.Content.ReadAsStringAsync();
JObject jsonObject = JObject.Parse(body);
Assert.Equal("Value: Foobar", jsonObject["result"]);
}

[Fact]
public async Task GenericWebHook_Post_Succeeds()
{
string uri = "api/webhook-generic?code=1388a6b0d05eca2237f10e4a4641260b0a08f3a5";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
request.Content = new StringContent("{ 'a': 'Foobar' }");
request.Content = new StringContent("{ 'value': 'Foobar' }");
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

HttpResponseMessage response = await this._fixture.HttpClient.SendAsync(request);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType);
string body = await response.Content.ReadAsStringAsync();
Assert.Equal("WebHook processed successfully! Foobar", body);
JObject jsonObject = JObject.Parse(body);
Assert.Equal("Value: Foobar", jsonObject["result"]);
}

[Fact]
Expand All @@ -113,14 +132,17 @@ public async Task GenericWebHook_Post_AdminKey_Succeeds()
// Verify that sending the admin key bypasses WebHook auth
string uri = "api/webhook-generic?code=t8laajal0a1ajkgzoqlfv5gxr4ebhqozebw4qzdy";
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
request.Content = new StringContent("{ 'a': 'Foobar' }");
request.Content = new StringContent("{ 'value': 'Foobar' }");
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

HttpResponseMessage response = await this._fixture.HttpClient.SendAsync(request);
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType);
string body = await response.Content.ReadAsStringAsync();
Assert.Equal("WebHook processed successfully! Foobar", body);
JObject jsonObject = JObject.Parse(body);
Assert.Equal("Value: Foobar", jsonObject["result"]);
}

[Fact]
public async Task QueueTriggerBatch_Succeeds()
{
Expand Down

0 comments on commit 807cf0b

Please sign in to comment.