Skip to content

Commit 3e36d70

Browse files
authored
Normalize charset in Content-Type Header (#3173)
1 parent 5f77d0a commit 3e36d70

File tree

3 files changed

+80
-0
lines changed

3 files changed

+80
-0
lines changed

src/WebJobs.Script.WebHost/Handlers/WebScriptHostHandler.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage
3939
await StandbyManager.WarmUp(request, scriptHostManager);
4040
}
4141

42+
// Workaround for .net framework bug https://github.com/dotnet/corefx/issues/5014
43+
request.NormalizeContentTypeCharsetHeader();
4244
return await base.SendAsync(request, cancellationToken);
4345
}
4446
}

src/WebJobs.Script/Extensions/HttpRequestMessageExtensions.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,19 @@ public static void SetProperty(this HttpRequestMessage request, string propertyN
3737
request.Properties[propertyName] = value;
3838
}
3939

40+
public static void NormalizeContentTypeCharsetHeader(this HttpRequestMessage request)
41+
{
42+
if (request.Content != null && request.Content.Headers.ContentLength > 0 && request.Content.Headers.ContentType != null)
43+
{
44+
var charSet = request.Content.Headers.ContentType.CharSet;
45+
if (!string.IsNullOrEmpty(charSet))
46+
{
47+
char[] trimQuotes = new[] { '\'', '\"' };
48+
request.Content.Headers.ContentType.CharSet = charSet.Trim(trimQuotes);
49+
}
50+
}
51+
}
52+
4053
public static T GetPropertyOrDefault<T>(this HttpRequestMessage request, string propertyName)
4154
{
4255
return request.GetRequestPropertyOrDefault<T>(propertyName);

test/WebJobs.Script.Tests/Extensions/HttpRequestMessageExtensions.cs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,61 @@ public void GetHeaderValueOrDefault_ReturnsExpectedResult()
4242
Assert.Equal("One", value);
4343
}
4444

45+
[Theory]
46+
[InlineData("\"UTF-8\"")]
47+
[InlineData("utf-8")]
48+
[InlineData("'Utf-8'")]
49+
[InlineData("'UTF-8'")]
50+
public void NormalizeContentTypeCharsetHeader_ContentTypeHeader_ValidCharSet(string charSet)
51+
{
52+
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://functions/{test:alpha}/test?name=Amy");
53+
string input = "{ name: 'body1', nestedObject: { name: 'body2' } }";
54+
request.Content = new StringContent(input);
55+
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
56+
request.Content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("charset", charSet));
57+
request.NormalizeContentTypeCharsetHeader();
58+
59+
string expectedHeader = GetExpectedContenTypeHeader(charSet);
60+
string actualHeader = request.Content.Headers.ContentType.ToString();
61+
Assert.Equal(expectedHeader, actualHeader);
62+
}
63+
64+
[Theory]
65+
[InlineData("")]
66+
[InlineData(null)]
67+
public void NormalizeContentTypeCharsetHeader_ContentTypeHeader_Set_CharSet_Empty(string charSet)
68+
{
69+
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://functions/{test:alpha}/test?name=Amy");
70+
string input = "{ name: 'body1', nestedObject: { name: 'body2' } }";
71+
request.Content = new StringContent(input);
72+
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
73+
request.Content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("charset", charSet));
74+
request.NormalizeContentTypeCharsetHeader();
75+
76+
string expectedHeader = GetExpectedContenTypeHeader(charSet);
77+
string actualHeader = request.Content.Headers.ContentType.ToString();
78+
Assert.Equal(expectedHeader, actualHeader);
79+
}
80+
81+
[Fact]
82+
public void NormalizeContentTypeCharsetHeader_ContentTypeHeader_Default()
83+
{
84+
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://functions/{test:alpha}/test?name=Amy");
85+
request.Content = new StringContent("test");
86+
request.NormalizeContentTypeCharsetHeader();
87+
string expectedHeader = "text/plain; charset=utf-8";
88+
string actualHeader = request.Content.Headers.ContentType.ToString();
89+
Assert.Equal(expectedHeader, actualHeader);
90+
}
91+
92+
[Fact]
93+
public void NormalizeContentTypeCharsetHeader_NoHeaders()
94+
{
95+
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "http://functions/{test:alpha}/test?name=Amy");
96+
request.NormalizeContentTypeCharsetHeader();
97+
Assert.Null(request.Content);
98+
}
99+
45100
[Fact]
46101
public void IsAntaresInternalRequest_ReturnsExpectedResult()
47102
{
@@ -171,5 +226,15 @@ public void HasAuthorizationLevel_ReturnsExpectedValue()
171226
request.SetProperty(ScriptConstants.AzureFunctionsHttpRequestAuthorizationDisabledKey, true);
172227
Assert.True(request.HasAuthorizationLevel(AuthorizationLevel.Admin));
173228
}
229+
230+
private static string GetExpectedContenTypeHeader(string charSet)
231+
{
232+
if (string.IsNullOrEmpty(charSet))
233+
{
234+
return "application/json; charset";
235+
}
236+
char[] trimQuotes = new[] { '\'', '\"' };
237+
return "application/json; charset=" + charSet.Trim(trimQuotes);
238+
}
174239
}
175240
}

0 commit comments

Comments
 (0)