Andrea Fazzi 6 жил өмнө
parent
commit
e99c9893e4

+ 39 - 1
handlers/handlers_test.go

@@ -57,7 +57,7 @@ func (t *testSuite) BeforeAll() {
 	orm.Use(db)
 	orm.AutoMigrate()
 
-	// Load the templates
+	// Initialize the renderers
 
 	htmlRenderer, err := renderer.NewHTMLRenderer("./testdata/templates/")
 	if err != nil {
@@ -69,6 +69,11 @@ func (t *testSuite) BeforeAll() {
 		panic(err)
 	}
 
+	csvRenderer, err := renderer.NewCSVRenderer()
+	if err != nil {
+		panic(err)
+	}
+
 	renderer.Render = make(map[string]func(http.ResponseWriter, *http.Request, interface{}, ...url.Values))
 
 	renderer.Render["html"] = func(w http.ResponseWriter, r *http.Request, data interface{}, options ...url.Values) {
@@ -79,6 +84,10 @@ func (t *testSuite) BeforeAll() {
 		jsonRenderer.Render(w, r, data, options...)
 	}
 
+	renderer.Render["csv"] = func(w http.ResponseWriter, r *http.Request, data interface{}, options ...url.Values) {
+		csvRenderer.Render(w, r, data, options...)
+	}
+
 	// Load the configuration
 
 	err = config.ReadFile("testdata/config.yaml", config.Config)
@@ -168,6 +177,35 @@ func (t *testSuite) TestGetTeachersJSON() {
 
 }
 
+func (t *testSuite) TestGetTeachersCSV() {
+	var response renderer.JsonResponse
+
+	req, err := http.NewRequest("GET", "/api/teachers?format=csv", nil)
+	if err != nil {
+		panic(err)
+	}
+
+	pattern := PathPattern{
+		"/api/%s",
+		"/%s/%d?format=csv",
+		[]string{"GET"},
+	}
+
+	rr := httptest.NewRecorder()
+	modelHandler("teachers", pattern).ServeHTTP(rr, req)
+
+	t.Equal(http.StatusOK, rr.Code)
+
+	if !t.Failed() {
+		err := json.Unmarshal(rr.Body.Bytes(), &response)
+		t.Nil(err)
+		if !t.Failed() {
+			t.True(strings.Contains(string(response.Result), "AGOSTINO"))
+		}
+	}
+
+}
+
 func (t *testSuite) TestGetErrorJSON() {
 	var (
 		response renderer.JsonResponse

+ 40 - 0
renderer/renderer.go

@@ -12,6 +12,7 @@ import (
 	"reflect"
 	"strings"
 
+	"github.com/gocarina/gocsv"
 	"github.com/gorilla/schema"
 )
 
@@ -20,6 +21,7 @@ type Renderer interface {
 }
 
 type JSONRenderer struct{}
+type CSVRenderer struct{}
 
 type htmlTemplateData struct {
 	Data    interface{}
@@ -51,6 +53,11 @@ func init() {
 		panic(err)
 	}
 
+	csvRenderer, err := NewCSVRenderer()
+	if err != nil {
+		panic(err)
+	}
+
 	Render = make(map[string]func(http.ResponseWriter, *http.Request, interface{}, ...url.Values))
 
 	Render["html"] = func(w http.ResponseWriter, r *http.Request, data interface{}, options ...url.Values) {
@@ -61,6 +68,10 @@ func init() {
 		jsonRenderer.Render(w, r, data, options...)
 	}
 
+	Render["csv"] = func(w http.ResponseWriter, r *http.Request, data interface{}, options ...url.Values) {
+		csvRenderer.Render(w, r, data, options...)
+	}
+
 }
 
 func query(values ...string) template.URL {
@@ -108,6 +119,35 @@ func (rend *JSONRenderer) Render(w http.ResponseWriter, r *http.Request, data in
 	return nil
 }
 
+func NewCSVRenderer() (*CSVRenderer, error) {
+	return &CSVRenderer{}, nil
+}
+
+func (rend *CSVRenderer) Render(w http.ResponseWriter, r *http.Request, data interface{}, options ...url.Values) error {
+	w.Header().Set("Content-Type", "text/csv; charset=utf-8")
+	if isErrorType(data) {
+		j, err := json.Marshal(JsonResponse{nil, []byte(data.(error).Error())})
+		if err != nil {
+			return err
+		}
+		w.WriteHeader(http.StatusInternalServerError)
+		w.Write(j)
+	} else {
+
+		result, err := gocsv.MarshalString(data)
+		if err != nil {
+			return err
+		}
+
+		response, err := json.Marshal(JsonResponse{[]byte(result), nil})
+		if err != nil {
+			return err
+		}
+		w.Write(response)
+	}
+	return nil
+}
+
 type HTMLRenderer struct {
 	TemplatePath string