@@ -8,98 +8,11 @@ import (
88 "io/ioutil"
99 "net/http"
1010 "net/http/httptest"
11- "reflect"
12- "regexp"
13- "strconv"
1411 "time"
1512
1613 "github.com/google/jsonapi"
1714)
1815
19- func createBlog (w http.ResponseWriter , r * http.Request ) {
20- jsonapiRuntime := jsonapi .NewRuntime ().Instrument ("blogs.create" )
21-
22- blog := new (Blog )
23-
24- if err := jsonapiRuntime .UnmarshalPayload (r .Body , blog ); err != nil {
25- http .Error (w , err .Error (), http .StatusInternalServerError )
26- return
27- }
28-
29- // ...do stuff with your blog...
30-
31- w .WriteHeader (http .StatusCreated )
32- w .Header ().Set ("Content-Type" , jsonapi .MediaType )
33-
34- if err := jsonapiRuntime .MarshalOnePayload (w , blog ); err != nil {
35- http .Error (w , err .Error (), http .StatusInternalServerError )
36- }
37- }
38-
39- func listBlogs (w http.ResponseWriter , r * http.Request ) {
40- jsonapiRuntime := jsonapi .NewRuntime ().Instrument ("blogs.list" )
41- // ...fetch your blogs, filter, offset, limit, etc...
42-
43- // but, for now
44- blogs := testBlogsForList ()
45-
46- w .WriteHeader (http .StatusOK )
47- w .Header ().Set ("Content-Type" , jsonapi .MediaType )
48- if err := jsonapiRuntime .MarshalManyPayload (w , blogs ); err != nil {
49- http .Error (w , err .Error (), http .StatusInternalServerError )
50- }
51- }
52-
53- func showBlog (w http.ResponseWriter , r * http.Request ) {
54- id := r .FormValue ("id" )
55-
56- // ...fetch your blog...
57-
58- intID , err := strconv .Atoi (id )
59- if err != nil {
60- http .Error (w , err .Error (), http .StatusInternalServerError )
61- return
62- }
63-
64- jsonapiRuntime := jsonapi .NewRuntime ().Instrument ("blogs.show" )
65-
66- // but, for now
67- blog := testBlogForCreate (intID )
68- w .WriteHeader (http .StatusOK )
69-
70- w .Header ().Set ("Content-Type" , jsonapi .MediaType )
71- if err := jsonapiRuntime .MarshalOnePayload (w , blog ); err != nil {
72- http .Error (w , err .Error (), http .StatusInternalServerError )
73- }
74- }
75-
76- func echoBlogs (w http.ResponseWriter , r * http.Request ) {
77- jsonapiRuntime := jsonapi .NewRuntime ().Instrument ("blogs.echo" )
78-
79- // Fetch the blogs from the HTTP request body
80- data , err := jsonapiRuntime .UnmarshalManyPayload (r .Body , reflect .TypeOf (new (Blog )))
81- if err != nil {
82- http .Error (w , err .Error (), http .StatusInternalServerError )
83- }
84-
85- // Type assert the []interface{} to []*Blog
86- blogs := []* Blog {}
87- for _ , b := range data {
88- blog , ok := b .(* Blog )
89- if ! ok {
90- http .Error (w , "Unexpected type" , http .StatusInternalServerError )
91- }
92- blogs = append (blogs , blog )
93- }
94-
95- // Echo the blogs to the response body
96- w .WriteHeader (http .StatusOK )
97- w .Header ().Set ("Content-Type" , jsonapi .MediaType )
98- if err := jsonapiRuntime .MarshalManyPayload (w , blogs ); err != nil {
99- http .Error (w , err .Error (), http .StatusInternalServerError )
100- }
101- }
102-
10316func main () {
10417 jsonapi .Instrumentation = func (r * jsonapi.Runtime , eventType jsonapi.Event , callGUID string , dur time.Duration ) {
10518 metricPrefix := r .Value ("instrument" ).(string )
@@ -121,91 +34,11 @@ func main() {
12134 }
12235 }
12336
124- http .HandleFunc ("/blogs" , func (w http.ResponseWriter , r * http.Request ) {
125- if ! regexp .MustCompile (`application/vnd\.api\+json` ).Match ([]byte (r .Header .Get ("Accept" ))) {
126- http .Error (w , "Unsupported Media Type" , http .StatusUnsupportedMediaType )
127- return
128- }
129-
130- if r .Method == http .MethodPost {
131- createBlog (w , r )
132- } else if r .Method == http .MethodPut {
133- echoBlogs (w , r )
134- } else if r .FormValue ("id" ) != "" {
135- showBlog (w , r )
136- } else {
137- listBlogs (w , r )
138- }
139- })
140-
37+ exampleHandler := & ExampleHandler {}
38+ http .HandleFunc ("/blogs" , exampleHandler .ServeHTTP )
14139 exerciseHandler ()
14240}
14341
144- func testBlogForCreate (i int ) * Blog {
145- return & Blog {
146- ID : 1 * i ,
147- Title : "Title 1" ,
148- CreatedAt : time .Now (),
149- Posts : []* Post {
150- & Post {
151- ID : 1 * i ,
152- Title : "Foo" ,
153- Body : "Bar" ,
154- Comments : []* Comment {
155- & Comment {
156- ID : 1 * i ,
157- Body : "foo" ,
158- },
159- & Comment {
160- ID : 2 * i ,
161- Body : "bar" ,
162- },
163- },
164- },
165- & Post {
166- ID : 2 * i ,
167- Title : "Fuubar" ,
168- Body : "Bas" ,
169- Comments : []* Comment {
170- & Comment {
171- ID : 1 * i ,
172- Body : "foo" ,
173- },
174- & Comment {
175- ID : 3 * i ,
176- Body : "bas" ,
177- },
178- },
179- },
180- },
181- CurrentPost : & Post {
182- ID : 1 * i ,
183- Title : "Foo" ,
184- Body : "Bar" ,
185- Comments : []* Comment {
186- & Comment {
187- ID : 1 * i ,
188- Body : "foo" ,
189- },
190- & Comment {
191- ID : 2 * i ,
192- Body : "bar" ,
193- },
194- },
195- },
196- }
197- }
198-
199- func testBlogsForList () []interface {} {
200- blogs := make ([]interface {}, 0 , 10 )
201-
202- for i := 0 ; i < 10 ; i ++ {
203- blogs = append (blogs , testBlogForCreate (i ))
204- }
205-
206- return blogs
207- }
208-
20942func exerciseHandler () {
21043 // list
21144 req , _ := http .NewRequest (http .MethodGet , "/blogs" , nil )
@@ -242,7 +75,7 @@ func exerciseHandler() {
24275 fmt .Println ("============== end raw jsonapi from show =============" )
24376
24477 // create
245- blog := testBlogForCreate (1 )
78+ blog := fixtureBlogCreate (1 )
24679 in := bytes .NewBuffer (nil )
24780 jsonapi .MarshalOnePayloadEmbedded (in , blog )
24881
@@ -265,9 +98,9 @@ func exerciseHandler() {
26598
26699 // echo
267100 blogs := []interface {}{
268- testBlogForCreate (1 ),
269- testBlogForCreate (2 ),
270- testBlogForCreate (3 ),
101+ fixtureBlogCreate (1 ),
102+ fixtureBlogCreate (2 ),
103+ fixtureBlogCreate (3 ),
271104 }
272105 in = bytes .NewBuffer (nil )
273106 jsonapi .MarshalManyPayload (in , blogs )
@@ -300,48 +133,3 @@ func exerciseHandler() {
300133 fmt .Println (string (out .Bytes ()))
301134 fmt .Println ("================ end marshal materialized Blog struct =================" )
302135}
303-
304- type Blog struct {
305- ID int `jsonapi:"primary,blogs"`
306- Title string `jsonapi:"attr,title"`
307- Posts []* Post `jsonapi:"relation,posts"`
308- CurrentPost * Post `jsonapi:"relation,current_post"`
309- CurrentPostID int `jsonapi:"attr,current_post_id"`
310- CreatedAt time.Time `jsonapi:"attr,created_at"`
311- ViewCount int `jsonapi:"attr,view_count"`
312- }
313-
314- type Post struct {
315- ID int `jsonapi:"primary,posts"`
316- BlogID int `jsonapi:"attr,blog_id"`
317- Title string `jsonapi:"attr,title"`
318- Body string `jsonapi:"attr,body"`
319- Comments []* Comment `jsonapi:"relation,comments"`
320- }
321-
322- type Comment struct {
323- ID int `jsonapi:"primary,comments"`
324- PostID int `jsonapi:"attr,post_id"`
325- Body string `jsonapi:"attr,body"`
326- }
327-
328- // Blog Links
329- func (blog Blog ) JSONAPILinks () * map [string ]interface {} {
330- return & map [string ]interface {}{
331- "self" : fmt .Sprintf ("https://example.com/blogs/%d" , blog .ID ),
332- }
333- }
334-
335- func (blog Blog ) JSONAPIRelationshipLinks (relation string ) * map [string ]interface {} {
336- if relation == "posts" {
337- return & map [string ]interface {}{
338- "related" : fmt .Sprintf ("https://example.com/blogs/%d/posts" , blog .ID ),
339- }
340- }
341- if relation == "current_post" {
342- return & map [string ]interface {}{
343- "related" : fmt .Sprintf ("https://example.com/blogs/%d/current_post" , blog .ID ),
344- }
345- }
346- return nil
347- }
0 commit comments