1
0
mirror of https://github.com/labstack/echo.git synced 2025-03-25 21:38:56 +02:00

Added JSONP API in Context

Signed-off-by: Vishal Rana <vr@labstack.com>
This commit is contained in:
Will Fitzgerald 2015-07-24 15:28:35 -04:00 committed by Vishal Rana
parent 96e5761b75
commit 9257875cb7
5 changed files with 151 additions and 21 deletions

View File

@ -101,8 +101,8 @@ func (c *Context) Set(key string, val interface{}) {
c.store[key] = val c.store[key] = val
} }
// Bind binds the request body into specified type v. Default binder does it // Bind binds the request body into specified type v. Default binder does it based
// based on Content-Type header. // on Content-Type header.
func (c *Context) Bind(i interface{}) error { func (c *Context) Bind(i interface{}) error {
return c.echo.binder(c.request, i) return c.echo.binder(c.request, i)
} }
@ -121,7 +121,7 @@ func (c *Context) Render(code int, name string, data interface{}) (err error) {
return return
} }
// HTML formats according to a format specifier and sends text/html response with // HTML formats according to a format specifier and sends HTML response with
// status code. // status code.
func (c *Context) HTML(code int, format string, a ...interface{}) (err error) { func (c *Context) HTML(code int, format string, a ...interface{}) (err error) {
c.response.Header().Set(ContentType, TextHTMLCharsetUTF8) c.response.Header().Set(ContentType, TextHTMLCharsetUTF8)
@ -132,8 +132,8 @@ func (c *Context) HTML(code int, format string, a ...interface{}) (err error) {
return return
} }
// String formats according to a format specifier and sends text/plain response // String formats according to a format specifier and sends text response with status
// with status code. // code.
func (c *Context) String(code int, format string, a ...interface{}) (err error) { func (c *Context) String(code int, format string, a ...interface{}) (err error) {
c.response.Header().Set(ContentType, TextPlain) c.response.Header().Set(ContentType, TextPlain)
c.response.WriteHeader(code) c.response.WriteHeader(code)
@ -143,7 +143,7 @@ func (c *Context) String(code int, format string, a ...interface{}) (err error)
return return
} }
// JSON sends an application/json response with status code. // JSON sends a JSON response with status code.
func (c *Context) JSON(code int, i interface{}) (err error) { func (c *Context) JSON(code int, i interface{}) (err error) {
c.response.Header().Set(ContentType, ApplicationJSONCharsetUTF8) c.response.Header().Set(ContentType, ApplicationJSONCharsetUTF8)
c.response.WriteHeader(code) c.response.WriteHeader(code)
@ -153,7 +153,21 @@ func (c *Context) JSON(code int, i interface{}) (err error) {
return return
} }
// XML sends an application/xml response with status code. // JSONP sends a JSONP response with status code. It uses `callback` to construct
// the JSONP payload.
func (c *Context) JSONP(code int, callback string, i interface{}) (err error) {
c.response.Header().Set(ContentType, ApplicationJavaScriptCharsetUTF8)
c.response.WriteHeader(code)
c.response.Write([]byte(callback + "("))
if err = json.NewEncoder(c.response).Encode(i); err != nil {
c.response.clear()
} else {
c.response.Write([]byte(");"))
}
return
}
// XML sends an XML response with status code.
func (c *Context) XML(code int, i interface{}) (err error) { func (c *Context) XML(code int, i interface{}) (err error) {
c.response.Header().Set(ContentType, ApplicationXMLCharsetUTF8) c.response.Header().Set(ContentType, ApplicationXMLCharsetUTF8)
c.response.WriteHeader(code) c.response.WriteHeader(code)

View File

@ -11,8 +11,9 @@ import (
"strings" "strings"
"encoding/xml" "encoding/xml"
"github.com/stretchr/testify/assert"
"net/url" "net/url"
"github.com/stretchr/testify/assert"
) )
type ( type (
@ -94,7 +95,19 @@ func TestContext(t *testing.T) {
if assert.NoError(t, err) { if assert.NoError(t, err) {
assert.Equal(t, http.StatusOK, rec.Code) assert.Equal(t, http.StatusOK, rec.Code)
assert.Equal(t, ApplicationJSONCharsetUTF8, rec.Header().Get(ContentType)) assert.Equal(t, ApplicationJSONCharsetUTF8, rec.Header().Get(ContentType))
assert.Equal(t, userJSON, strings.TrimSpace(rec.Body.String())) assert.Equal(t, userJSON+"\n", rec.Body.String())
}
// JSONP
req.Header.Set(Accept, ApplicationJavaScript)
rec = httptest.NewRecorder()
c = NewContext(req, NewResponse(rec), New())
callback := "callback"
err = c.JSONP(http.StatusOK, callback, user{"1", "Joe"})
if assert.NoError(t, err) {
assert.Equal(t, http.StatusOK, rec.Code)
assert.Equal(t, ApplicationJavaScriptCharsetUTF8, rec.Header().Get(ContentType))
assert.Equal(t, callback+"("+userJSON+"\n);", rec.Body.String())
} }
// XML // XML

26
echo.go
View File

@ -91,18 +91,20 @@ const (
// Media types // Media types
//------------- //-------------
ApplicationJSON = "application/json" ApplicationJSON = "application/json"
ApplicationJSONCharsetUTF8 = ApplicationJSON + "; " + CharsetUTF8 ApplicationJSONCharsetUTF8 = ApplicationJSON + "; " + CharsetUTF8
ApplicationXML = "application/xml" ApplicationJavaScript = "application/javascript"
ApplicationXMLCharsetUTF8 = ApplicationXML + "; " + CharsetUTF8 ApplicationJavaScriptCharsetUTF8 = ApplicationJavaScript + "; " + CharsetUTF8
ApplicationForm = "application/x-www-form-urlencoded" ApplicationXML = "application/xml"
ApplicationProtobuf = "application/protobuf" ApplicationXMLCharsetUTF8 = ApplicationXML + "; " + CharsetUTF8
ApplicationMsgpack = "application/msgpack" ApplicationForm = "application/x-www-form-urlencoded"
TextHTML = "text/html" ApplicationProtobuf = "application/protobuf"
TextHTMLCharsetUTF8 = TextHTML + "; " + CharsetUTF8 ApplicationMsgpack = "application/msgpack"
TextPlain = "text/plain" TextHTML = "text/html"
TextPlainCharsetUTF8 = TextPlain + "; " + CharsetUTF8 TextHTMLCharsetUTF8 = TextHTML + "; " + CharsetUTF8
MultipartForm = "multipart/form-data" TextPlain = "text/plain"
TextPlainCharsetUTF8 = TextPlain + "; " + CharsetUTF8
MultipartForm = "multipart/form-data"
//--------- //---------
// Charset // Charset

View File

@ -0,0 +1,70 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<title>JSONP example</title>
<script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script type="text/javascript">
var host_prefix = 'http://localhost:3999';
$(document).ready(function() {
// JSONP version - add 'callback=?' to the URL - fetch the JSONP response to the request
$("#jsonp-button").click(function(e) {
e.preventDefault();
// The only difference on the client end is the addition of 'callback=?' to the URL
var url = host_prefix + '/jsonp?callback=?';
$.getJSON(url, function(jsonp) {
console.log(jsonp);
$("#jsonp-response").html(JSON.stringify(jsonp, null, 2));
});
});
});
</script>
</head>
<body>
<div class="container">
<h1>JSONP Example</h1>
JSONP is a method that allows cross-domain server calls. You can read more about
it at the <a href="http://json-jsonp-tutorial.craic.com/index.html">JSON versus JSONP Tutorial</a>.
To see this live, run the server locally and open <a href="http://localhost:3999/index.html">http://localhost:3999/index.html</a> (That is, this page.)
<p>
Server:
<pre>
e.Get("/jsonp", func(c *echo.Context) error {
callback := c.Query("callback")
var content struct {
Response string `json:"response"`
Timestamp time.Time `json:"timestamp"`
Random int `json:"random"`
}
content.Response = "Sent via JSONP"
content.Timestamp = time.Now().UTC()
content.Random = rand.Intn(1000)
return c.JSONP(http.StatusOK, callback, &content)
})
</pre>
</p>
<p>
Client:
<pre>
var url = host_prefix + <span class="highlight">'/jsonp?callback=?';</span>
$.getJSON(url, function(jsonp){
$("#jsonp-response").html(JSON.stringify(jsonp, null, 2));
});
</pre>
<input type="button" class="btn btn-primary btn-lg" id="jsonp-button" value="Get JSONP response">
<pre id='jsonp-response'></pre>
</p>
</div>
</body>
</html>

31
recipes/jsonp/server.go Normal file
View File

@ -0,0 +1,31 @@
package main
import (
"math/rand"
"net/http"
"time"
"github.com/labstack/echo"
)
func main() {
// Setup
e := echo.New()
e.ServeDir("/", "public")
e.Get("/jsonp", func(c *echo.Context) error {
callback := c.Query("callback")
var content struct {
Response string `json:"response"`
Timestamp time.Time `json:"timestamp"`
Random int `json:"random"`
}
content.Response = "Sent via JSONP"
content.Timestamp = time.Now().UTC()
content.Random = rand.Intn(1000)
return c.JSONP(http.StatusOK, callback, &content)
})
// Start server
e.Run(":3999")
}