Permalink
Browse files

Adding JSONP middleware

  • Loading branch information...
paulbellamy committed Jun 5, 2011
1 parent 4222439 commit ba6d7e6a2a41c68ca15dd5aa3afbe8156dd3e667
Showing with 167 additions and 0 deletions.
  1. +2 −0 Makefile
  2. +5 −0 README.markdown
  3. +26 −0 jsonp.go
  4. +134 −0 jsonp_test.go
View
@@ -10,10 +10,12 @@ GOFILES=\
sessions.go\
routing.go\
static.go\
jsonp.go\
include $(GOROOT)/src/Make.pkg
format:
${GOFMT} -w ${GOFILES}
${GOFMT} -w mango_test.go
${GOFMT} -w jsonp_test.go
${GOFMT} -w examples/*.go
View
@@ -58,6 +58,11 @@ Where:
Usage: Static(directory string)
Serves static files from the directory provided.
* JSONP
Usage: JSONP
Provides JSONP support. If a request has a 'callback' parameter, and your application responds with a Content-Type of "application/json", the JSONP middleware will wrap the response in the callback function and set the Content-Type to "application/javascript".
## Example App
package main
View
@@ -0,0 +1,26 @@
package mango
import (
"fmt"
"regexp"
"strings"
)
func JSONP(env Env, app App) (Status, Headers, Body) {
callback := env.Request().FormValue("callback")
if callback != "" {
if matched, err := regexp.MatchString("^[a-zA-Z_$][a-zA-Z_0-9$]*([.]?[a-zA-Z_$][a-zA-Z_0-9$]*)*$", callback); !matched || err != nil {
return 400, Headers{"Content-Type": []string{"text/plain"}}, "Bad Request"
}
}
status, headers, body := app(env)
if callback != "" && strings.Contains(headers.Get("Content-Type"), "application/json") {
headers.Set("Content-Type", strings.Replace(headers.Get("Content-Type"), "json", "javascript", -1))
body = Body(fmt.Sprintf("%s(%s)", callback, body))
}
return status, headers, body
}
View
@@ -0,0 +1,134 @@
package mango
import (
"http"
"testing"
"fmt"
"runtime"
)
func jsonServer(env Env) (Status, Headers, Body) {
return 200, Headers{"Content-Type": []string{"application/json"}}, Body("{\"foo\":\"bar\"}")
}
func nonJsonServer(env Env) (Status, Headers, Body) {
return 200, Headers{"Content-Type": []string{"text/html"}}, Body("<h1>Hello World!</h1>")
}
func init() {
runtime.GOMAXPROCS(4)
fmt.Println("Testing Mango-JSONP Version:", VersionString())
}
func TestJSONPSuccess(t *testing.T) {
// Compile the stack
jsonpStack := new(Stack)
jsonpStack.Middleware(JSONP)
jsonpApp := jsonpStack.Compile(jsonServer)
// Request against it
request, err := http.NewRequest("GET", "http://localhost:3000/?callback=parseResponse", nil)
status, headers, body := jsonpApp(Env{"mango.request": &Request{request}})
if err != nil {
t.Error(err)
}
if status != 200 {
t.Error("Expected status to equal 200, got:", status)
}
if headers.Get("Content-Type") != "application/javascript" {
t.Error("Expected Content-Type to equal \"application/javascript\", got:", headers.Get("Content-Type"))
}
expected := "parseResponse({\"foo\":\"bar\"})"
if string(body) != expected {
t.Error("Expected body:", string(body), "to equal:", expected)
}
}
func TestNonJSONPSuccess(t *testing.T) {
// Compile the stack
nonJsonpStack := new(Stack)
nonJsonpStack.Middleware(JSONP)
nonJsonpApp := nonJsonpStack.Compile(nonJsonServer)
// Request against it
request, err := http.NewRequest("GET", "http://localhost:3000/?callback=parseResponse", nil)
status, headers, body := nonJsonpApp(Env{"mango.request": &Request{request}})
if err != nil {
t.Error(err)
}
if status != 200 {
t.Error("Expected status to equal 200, got:", status)
}
if headers.Get("Content-Type") != "text/html" {
t.Error("Expected Content-Type to equal \"text/html\", got:", headers.Get("Content-Type"))
}
expected := "<h1>Hello World!</h1>"
if string(body) != expected {
t.Error("Expected body:", string(body), "to equal:", expected)
}
}
func TestJSONPNoCallback(t *testing.T) {
// Compile the stack
jsonpStack := new(Stack)
jsonpStack.Middleware(JSONP)
jsonpApp := jsonpStack.Compile(jsonServer)
// Request against it
request, err := http.NewRequest("GET", "http://localhost:3000/", nil)
status, headers, body := jsonpApp(Env{"mango.request": &Request{request}})
if err != nil {
t.Error(err)
}
if status != 200 {
t.Error("Expected status to equal 200, got:", status)
}
if headers.Get("Content-Type") != "application/json" {
t.Error("Expected Content-Type to equal \"application/json\", got:", headers.Get("Content-Type"))
}
expected := "{\"foo\":\"bar\"}"
if string(body) != expected {
t.Error("Expected body:", string(body), "to equal:", expected)
}
}
func TestJSONPInvalidCallback(t *testing.T) {
// Compile the stack
jsonpStack := new(Stack)
jsonpStack.Middleware(JSONP)
jsonpApp := jsonpStack.Compile(jsonServer)
// Request against it
request, err := http.NewRequest("GET", "http://localhost:3000/?callback=invalid(callback)", nil)
status, headers, body := jsonpApp(Env{"mango.request": &Request{request}})
if err != nil {
t.Error(err)
}
if status != 400 {
t.Error("Expected status to equal 400, got:", status)
}
if headers.Get("Content-Type") != "text/plain" {
t.Error("Expected Content-Type to equal \"text/plain\", got:", headers.Get("Content-Type"))
}
expected := "Bad Request"
if string(body) != expected {
t.Error("Expected body:", string(body), "to equal:", expected)
}
}

0 comments on commit ba6d7e6

Please sign in to comment.