Skip to content

Commit 807cf0b

Browse files
committed
Default Content-Type to application/json for JSON responses
1 parent ea27cc0 commit 807cf0b

File tree

7 files changed

+52
-15
lines changed

7 files changed

+52
-15
lines changed

sample/WebHook-Generic-CSharp/run.csx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,18 @@ using System;
44
using System.Net;
55
using System.Threading.Tasks;
66
using Newtonsoft.Json;
7+
using Newtonsoft.Json.Linq;
78

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

13-
return req.CreateResponse(HttpStatusCode.OK, $"Value: {payload.Value}");
14+
JObject body = new JObject()
15+
{
16+
{ "result", $"Value: {payload.Value}" }
17+
};
18+
return req.CreateResponse(HttpStatusCode.OK, body, "application/json");
1419
}
1520

1621
public class Payload

sample/WebHook-Generic/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
module.exports = function (context, data) {
22
context.log('Webhook was triggered!');
33
context.res = {
4-
body: 'WebHook processed successfully! ' + data.a
4+
body: {
5+
result: 'Value: ' + data.value
6+
}
57
};
68
context.done();
79
}

src/WebJobs.Script/Binding/HttpBinding.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ public override async Task BindAsync(BindingContext context)
7070
response = new HttpResponseMessage(statusCode);
7171
response.Content = new StringContent(body);
7272

73+
// we default the Content-Type here, but we override below with any
74+
// Content-Type header the user might have set themselves
75+
if (Utility.IsJson(body))
76+
{
77+
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
78+
}
79+
80+
// apply any user specified headers
7381
JObject headers = (JObject)jsonObject["headers"];
7482
if (headers != null)
7583
{

src/WebJobs.Script/Description/NodeFunctionInvoker.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ private bool TryDeserializeJsonObject(string json, out Dictionary<string, object
395395
{
396396
result = null;
397397

398-
if (!IsJson(json))
398+
if (!Utility.IsJson(json))
399399
{
400400
return false;
401401
}

src/WebJobs.Script/Description/ScriptFunctionInvokerBase.cs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ protected static Dictionary<string, string> GetBindingData(object value, IBinder
9999
// if the input value is a JSON string, extract additional
100100
// binding data from it
101101
string json = value as string;
102-
if (!string.IsNullOrEmpty(json) && IsJson(json))
102+
if (!string.IsNullOrEmpty(json) && Utility.IsJson(json))
103103
{
104104
// parse the object skipping any nested objects (binding data
105105
// only includes top level properties)
@@ -155,13 +155,6 @@ protected static void ApplyAmbientBindingData(IBinderEx binder, IDictionary<stri
155155
}
156156
}
157157

158-
protected static bool IsJson(string input)
159-
{
160-
input = input.Trim();
161-
return (input.StartsWith("{", StringComparison.OrdinalIgnoreCase) && input.EndsWith("}", StringComparison.OrdinalIgnoreCase))
162-
|| (input.StartsWith("[", StringComparison.OrdinalIgnoreCase) && input.EndsWith("]", StringComparison.OrdinalIgnoreCase));
163-
}
164-
165158
protected virtual void Dispose(bool disposing)
166159
{
167160
if (!_disposed)

src/WebJobs.Script/Utility.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,5 +83,12 @@ public static string GetAppSettingOrEnvironmentValue(string name)
8383

8484
return null;
8585
}
86+
87+
public static bool IsJson(string input)
88+
{
89+
input = input.Trim();
90+
return (input.StartsWith("{", StringComparison.OrdinalIgnoreCase) && input.EndsWith("}", StringComparison.OrdinalIgnoreCase))
91+
|| (input.StartsWith("[", StringComparison.OrdinalIgnoreCase) && input.EndsWith("]", StringComparison.OrdinalIgnoreCase));
92+
}
8693
}
8794
}

test/WebJobs.Script.Tests/SamplesEndToEndTests.cs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ public async Task HttpTrigger_Get_Succeeds()
7272
HttpResponseMessage response = await this._fixture.HttpClient.SendAsync(request);
7373
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
7474
string body = await response.Content.ReadAsStringAsync();
75+
Assert.Equal("text/plain", response.Content.Headers.ContentType.MediaType);
7576
Assert.Equal("Hello Mathew", body);
7677
}
7778

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

97+
[Fact]
98+
public async Task GenericWebHook_CSharp_Post_Succeeds()
99+
{
100+
string uri = "api/webhook-generic-csharp?code=827bdzxhqy3xc62cxa2hmfsh6gxzhg30s5pi64tu";
101+
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
102+
request.Content = new StringContent("{ 'Value': 'Foobar' }");
103+
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
104+
105+
HttpResponseMessage response = await this._fixture.HttpClient.SendAsync(request);
106+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
107+
Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType);
108+
string body = await response.Content.ReadAsStringAsync();
109+
JObject jsonObject = JObject.Parse(body);
110+
Assert.Equal("Value: Foobar", jsonObject["result"]);
111+
}
112+
96113
[Fact]
97114
public async Task GenericWebHook_Post_Succeeds()
98115
{
99116
string uri = "api/webhook-generic?code=1388a6b0d05eca2237f10e4a4641260b0a08f3a5";
100117
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
101-
request.Content = new StringContent("{ 'a': 'Foobar' }");
118+
request.Content = new StringContent("{ 'value': 'Foobar' }");
102119
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
103120

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

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

119138
HttpResponseMessage response = await this._fixture.HttpClient.SendAsync(request);
120139
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
140+
Assert.Equal("application/json", response.Content.Headers.ContentType.MediaType);
121141
string body = await response.Content.ReadAsStringAsync();
122-
Assert.Equal("WebHook processed successfully! Foobar", body);
142+
JObject jsonObject = JObject.Parse(body);
143+
Assert.Equal("Value: Foobar", jsonObject["result"]);
123144
}
145+
124146
[Fact]
125147
public async Task QueueTriggerBatch_Succeeds()
126148
{

0 commit comments

Comments
 (0)