Skip to content
This repository has been archived by the owner on Oct 19, 2022. It is now read-only.

Commit

Permalink
Merge pull request #18 from stormpath/fix-post-content-type
Browse files Browse the repository at this point in the history
Version 0.1.2
  • Loading branch information
nbarbettini committed May 3, 2016
2 parents 88c9d83 + 80fbe79 commit 57b32bf
Show file tree
Hide file tree
Showing 38 changed files with 421 additions and 206 deletions.
5 changes: 5 additions & 0 deletions src/Stormpath.Owin.Abstractions/DefaultOwinResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ public string ReasonPhrase
set { environment.SetOrRemove(OwinKeys.ResponseReasonPhrase, value); }
}

public Action<Action<object>, object> OnSendingHeaders
{
get { return environment.Get<Action<Action<object>, object>>(OwinKeys.OnSendingHeaders); }
}

public object this[string key]
{
get { return environment.Get(key); }
Expand Down
3 changes: 3 additions & 0 deletions src/Stormpath.Owin.Abstractions/IOwinResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.
// </copyright>

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
Expand All @@ -28,6 +29,8 @@ public interface IOwinResponse
IDictionary<string, string[]> Headers { get; }
string ReasonPhrase { set; }
int StatusCode { set; }
Action<Action<object>, object> OnSendingHeaders { get; }

object this[string key] { get; set; }

Task WriteAsync(string text, Encoding encoding, CancellationToken cancellationToken = default(CancellationToken));
Expand Down
2 changes: 2 additions & 0 deletions src/Stormpath.Owin.Abstractions/OwinKeys.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ public static class OwinKeys

public static readonly string CallCancelled = "owin.CallCancelled";

public static readonly string OnSendingHeaders = "server.OnSendingHeaders";

public static readonly string StormpathClient = "Stormpath.RequestClient";

public static readonly string StormpathUser = "Stormpath.RequestUser";
Expand Down
2 changes: 1 addition & 1 deletion src/Stormpath.Owin.Abstractions/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@
"tooling": {
"defaultNamespace": "Stormpath.Owin.Abstractions"
},
"version": "0.1.0",
"version": "0.1.2",
"xmlDoc": true
}
32 changes: 32 additions & 0 deletions src/Stormpath.Owin.Middleware/Internal/Caching.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// <copyright file="Caching.cs" company="Stormpath, Inc.">
// Copyright (c) 2016 Stormpath, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using Stormpath.Owin.Abstractions;

namespace Stormpath.Owin.Middleware.Internal
{
public static class Caching
{
public static void AddDoNotCacheHeaders(IOwinEnvironment context)
{
context.Response.OnSendingHeaders(state =>
{
context.Response.Headers.SetString("Cache-Control", "no-cache, no-store");
context.Response.Headers.SetString("Pragma", "no-cache");
}, null);
}
}
}
16 changes: 12 additions & 4 deletions src/Stormpath.Owin.Middleware/Internal/ContentNegotiation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace Stormpath.Owin.Middleware.Internal
{
public static class ContentNegotiation
{
public static ContentNegotiationResult Negotiate(string acceptHeader, IEnumerable<string> producesList)
public static ContentNegotiationResult NegotiateAcceptHeader(string acceptHeader, IEnumerable<string> producesList)
{
if (string.IsNullOrEmpty(acceptHeader))
{
Expand All @@ -37,21 +37,29 @@ public static ContentNegotiationResult Negotiate(string acceptHeader, IEnumerabl
{
return new ContentNegotiationResult(
success: true,
prefers: ContentType.Parse(producesList.First()));
contentType: ContentType.Parse(producesList.First()));
}

if (producesList.Contains(potentialContentType))
{
return new ContentNegotiationResult(
success: true,
prefers: ContentType.Parse(potentialContentType));
contentType: ContentType.Parse(potentialContentType));
}
}

// Negotiation failed
return new ContentNegotiationResult(
success: false,
prefers: ContentType.Parse(sortedAccept.First()));
contentType: ContentType.Parse(sortedAccept.First()));
}

public static ContentNegotiationResult DetectBodyType(string bodyContentType)
{
var parsed = ContentType.Parse(bodyContentType);
var isValid = parsed == ContentType.FormUrlEncoded || parsed == ContentType.Json;

return new ContentNegotiationResult(isValid, parsed);
}

private static string[] ParseAndSortHeader(string acceptHeader)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ namespace Stormpath.Owin.Middleware.Internal
{
public struct ContentNegotiationResult
{
public ContentNegotiationResult(bool success, ContentType prefers)
public ContentNegotiationResult(bool success, ContentType contentType)
{
this.Preferred = prefers;
this.ContentType = contentType;
this.Success = success;
}

public ContentType Preferred { get; private set; }
public ContentType ContentType { get; private set; }

public bool Success { get; private set; }
}
Expand Down
13 changes: 11 additions & 2 deletions src/Stormpath.Owin.Middleware/Internal/ContentType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,37 @@ public sealed class ContentType

public static readonly ContentType Html = new ContentType("text/html");

public static readonly ContentType FormUrlEncoded = new ContentType("application/x-www-form-urlencoded");

private ContentType(string contentType)
{
this.value = contentType;
}

public static ContentType Parse(string contentType)
{
contentType = contentType.Split(';')?[0];

if (contentType.Equals(Any))
{
return Any;
}

if (contentType.Equals(Json, StringComparison.OrdinalIgnoreCase))
if (contentType.Equals(Json, StringComparison.Ordinal))
{
return Json;
}

if (contentType.Equals(Html, StringComparison.OrdinalIgnoreCase))
if (contentType.Equals(Html, StringComparison.Ordinal))
{
return Html;
}

if (contentType.Equals(FormUrlEncoded, StringComparison.Ordinal))
{
return FormUrlEncoded;
}

return new ContentType(contentType);
}

Expand Down
3 changes: 2 additions & 1 deletion src/Stormpath.Owin.Middleware/Internal/FormContentParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
// limitations under the License.
// </copyright>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
Expand Down Expand Up @@ -45,7 +46,7 @@ public static IDictionary<string, string[]> Parse(string formData)
temporaryDictionary[key].Add(value);
}

return temporaryDictionary.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.ToArray());
return temporaryDictionary.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.ToArray(), StringComparer.OrdinalIgnoreCase);
}
}
}
52 changes: 52 additions & 0 deletions src/Stormpath.Owin.Middleware/Internal/PocoBinder{T}.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// <copyright file="PocoBinder{T}.cs" company="Stormpath, Inc.">
// Copyright (c) 2016 Stormpath, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;

namespace Stormpath.Owin.Middleware.Internal
{
public class PocoBinder<T>
where T : new()
{
private readonly Func<string, string> valueFunc;

public PocoBinder(Func<string, string> valueFunc)
{
this.valueFunc = valueFunc;
}

public T Bind()
{
var result = new T();

foreach (var property in typeof(T).GetTypeInfo().DeclaredProperties)
{
if (property.PropertyType != typeof(string))
{
throw new Exception($"Unsupported target property type {property.PropertyType.Name}.");
}

property.SetValue(result, this.valueFunc(property.Name));
}

return result;
}
}
}
52 changes: 52 additions & 0 deletions src/Stormpath.Owin.Middleware/Internal/PostBodyParser{T}.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// <copyright file="PostBodyParser{T}.cs" company="Stormpath, Inc.">
// Copyright (c) 2016 Stormpath, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// </copyright>

using System;
using System.Threading;
using System.Threading.Tasks;
using Stormpath.Owin.Abstractions;

namespace Stormpath.Owin.Middleware.Internal
{
public static class PostBodyParser
{
public static async Task<T> ToModel<T>(IOwinEnvironment context, ContentType bodyContentType, CancellationToken cancellationToken)
where T : new()
{
var bodyString = await context.Request.GetBodyAsStringAsync(cancellationToken);

return ToModel<T>(bodyString, bodyContentType);
}

public static T ToModel<T>(string body, ContentType bodyContentType)
where T : new()
{
if (bodyContentType == ContentType.Json)
{
return Serializer.Deserialize<T>(body);
}

if (bodyContentType == ContentType.FormUrlEncoded)
{
var formDictionary = FormContentParser.Parse(body);
return new PocoBinder<T>(key => formDictionary.GetString(key)).Bind();
}

// This should never happen. The logic in AbstractRoute should throw first if the Content-Type is unsupported.
throw new Exception($"Unsupported Content-Type {bodyContentType.ToString()}");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,7 @@ public class ChangePasswordPostModel
public string SpToken { get; set; }

public string Password { get; set; }

public string ConfirmPassword { get; set; }
}
}
4 changes: 0 additions & 4 deletions src/Stormpath.Owin.Middleware/Model/RegisterPostModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,5 @@ public class RegisterPostModel
public string Surname { get; set; }

public string Username { get; set; }

public List<string> AllNonEmptyFieldNames { get; set; }

public Dictionary<string, object> CustomFields { get; set; }
}
}
Loading

0 comments on commit 57b32bf

Please sign in to comment.