Skip to content

Instantly share code, notes, and snippets.

@kouphax
Created November 1, 2011 07:55
Show Gist options
  • Save kouphax/1330120 to your computer and use it in GitHub Desktop.
Save kouphax/1330120 to your computer and use it in GitHub Desktop.
using System;
using System.IO;
using Nancy.Bootstrapper;
namespace Nancy.Jsonp
{
public static class Hooks
{
/// <summary>
/// Enable JSONP support in the application
/// </summary>
/// <param name="pipeline">Application Pipeline to Hook into</param>
public static void Enable(IApplicationPipelines pipeline)
{
pipeline.AfterRequest.AddItemToEndOfPipeline(PrepareJsonp);
}
/// <summary>
/// Transmogrify original response and apply JSONP Padding
/// </summary>
/// <param name="context">Current Nancy Context</param>
private static void PrepareJsonp(NancyContext context)
{
string callback = null;
if (IsJsonp(context, out callback))
{
// grab original contents for running later
Action<Stream> original = context.Response.Contents;
// set content type to application/javascript so browsers can handle it by default
// http://stackoverflow.com/questions/111302/best-content-type-to-serve-jsonp
context.Response.ContentType = "application/javascript";
context.Response.Contents = stream =>
{
// stolen @grumpydev UnclosableStreamWrapper
using(Stream unclosable = new UnclosableStreamWrapper(stream))
using (StreamWriter writer = new StreamWriter(unclosable) { AutoFlush = true })
{
// apply padding
writer.Write("{0}(", callback);
original(stream);
writer.Write(");");
}
};
}
}
/// <summary>
/// Determine if current request is a JSONP request. Current rules
/// around this may need tweaked,
/// - Response is an application/json response
/// - Request includes a "callback" parameter
/// </summary>
/// <param name="context">The Nanacy context</param>
/// <param name="callbackName">Name of the callback the JSONP response should call</param>
/// <returns>True if the response is a JSONP response</returns>
private static bool IsJsonp(NancyContext context, out string callbackName)
{
bool isJson = context.Response.ContentType == "application/json";
bool hasCallback = context.Request.Query["callback"].HasValue;
callbackName = hasCallback ? context.Request.Query["callback"].Value : "";
return isJson && hasCallback;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment