Skip to content

Instantly share code, notes, and snippets.

@ullmark
Created March 25, 2013 13:03
Show Gist options
  • Save ullmark/5236952 to your computer and use it in GitHub Desktop.
Save ullmark/5236952 to your computer and use it in GitHub Desktop.
Supporting method override for JSONP (like x-http-method-override) in a NancyFx APi
public static class NancyContextExtensions
{
private static readonly string[] AllowedOverrides = new [] { "POST", "PUT", "DELETE", "PATCH" };
private static readonly string[] OverrideTriggers = new [] { "_method", "callback" };
/// <summary>
/// This method checks for JSONP override
/// in the contexts Request item. Useful for handling unsupported verbs
/// from a javascript client.
///
/// If it contains '_method' and a 'callback' the request
/// is changes the request to match the method. It also transfers
/// query parameters to instead be form parameters. (expect the 'callback')
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
public static Response OverrideJsonpMethod(this NancyContext context)
{
if (context.Request.Method != "GET" || context.Request.Query._method == null || context.Request.Query.callback == null)
return null;
string method = ((string)context.Request.Query._method).ToUpper();
if (!AllowedOverrides.Contains(method))
return null;
// grab the headers.
var headers = context.Request.Headers.ToDictionary(x => x.Key, x => x.Value);
headers["Content-Type"] = new [] { "application/x-www-form-urlencoded" };
var url = context.Request.Url;
// transfer the parameters in the query to the form.
DynamicDictionary query = context.Request.Query;
var data = string.Join("&",
query.Keys
.Where(key => !OverrideTriggers.Contains(key))
.Select(key => string.Format("{0}={1}", key, query[key]))
);
// Keep only the callback in the URL
url.Query = string.Concat("callback=", query["callback"]);
var bytes = Encoding.UTF8.GetBytes(data);
var stream = new MemoryStream(bytes);
stream.Position = 0;
// Create a new body.
var body = RequestStream.FromStream(stream);
// create our new request altered request.
var rewrittenRequest = new Request(
method,
url,
body,
headers,
context.Request.UserHostAddress
);
// and replace the current.
context.Request = rewrittenRequest;
return null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment