aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjason2016-04-18 01:42:32 +0000
committerjason2016-04-18 01:42:32 +0000
commit5f953277f8b141819f8c85ad829fe367b98ac6e5 (patch)
tree9dd71e938901b96cfb6c96f37ec609c21128a89f
parent380a772e585fdf116c846f77d28a6fa5f4ed51ec (diff)
parent17bff1d0204a766d07ab127152fd006bc302138c (diff)
downloadtorpedo-master.tar.gz
torpedo-master.zip
Merge branch 'xml-api' into 'master' HEADmaster
add initial server with ping.view endpoint Issue #1 See merge request !1
-rw-r--r--README.md10
-rw-r--r--cmd/main.go51
-rw-r--r--cmd/ping.go31
-rw-r--r--torpedo.go88
4 files changed, 179 insertions, 1 deletions
diff --git a/README.md b/README.md
index b82d4d4..2bf167b 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,9 @@
1Implementation details can be found here: http://www.subsonic.org/pages/api.jsp \ No newline at end of file 1Implementation details can be found here: http://www.subsonic.org/pages/api.jsp
2
3To start dev clone this repo into $GOPATH/src/codesaloon.com/torpedo
4
5and start the server with:
6
7cd cmd
8go build -o serve
9./serve \ No newline at end of file
diff --git a/cmd/main.go b/cmd/main.go
new file mode 100644
index 0000000..074a4f3
--- /dev/null
+++ b/cmd/main.go
@@ -0,0 +1,51 @@
1package main
2
3import (
4 "bytes"
5 "codesaloon.com/torpedo"
6 "encoding/xml"
7 "flag"
8 "fmt"
9 "net/url"
10)
11
12type subsonicresponse struct {
13 XMLName xml.Name `xml:"subsonic-response"`
14 Xmlns string `xml:"xmlns,attr"`
15 Status string `xml:"status,attr"`
16 Version string `xml:"version,attr"`
17}
18
19type ping struct {
20 torpedo.PostNotSupported
21 torpedo.PutNotSupported
22 torpedo.DeleteNotSupported
23}
24
25func (ping) Get(values url.Values) (int, string) {
26
27 data := &subsonicresponse{Version: "1.1.1", Status: "ok", Xmlns: "http://subsonic.org/restapi"}
28
29 buf := new(bytes.Buffer)
30 enc := xml.NewEncoder(buf)
31
32 if err := enc.Encode(data); err != nil {
33 fmt.Printf("error: %v\n", err)
34 } else {
35 fmt.Println(buf.String())
36 }
37
38 return 200, buf.String()
39}
40
41func main() {
42 var port = flag.Int("port", 8000, "Port number to listen on")
43 flag.Parse()
44
45 ping := new(ping)
46
47 var api = new(torpedo.API)
48 api.AddResource(ping, "/rest/ping.view")
49 api.Start(*port)
50
51}
diff --git a/cmd/ping.go b/cmd/ping.go
new file mode 100644
index 0000000..a046cb0
--- /dev/null
+++ b/cmd/ping.go
@@ -0,0 +1,31 @@
1package main
2
3import (
4 "bytes"
5 "codesaloon.com/torpedo"
6 "encoding/xml"
7 "fmt"
8 "net/url"
9)
10
11type ping struct {
12 torpedo.PostNotSupported
13 torpedo.PutNotSupported
14 torpedo.DeleteNotSupported
15}
16
17func (ping) Get(values url.Values) (int, string) {
18
19 data := &subsonicresponse{Version: "1.1.1", Status: "ok", Xmlns: "http://subsonic.org/restapi"}
20
21 buf := new(bytes.Buffer)
22 enc := xml.NewEncoder(buf)
23
24 if err := enc.Encode(data); err != nil {
25 fmt.Printf("error: %v\n", err)
26 } else {
27 fmt.Println(buf.String())
28 }
29
30 return 200, buf.String()
31}
diff --git a/torpedo.go b/torpedo.go
new file mode 100644
index 0000000..e0c1b99
--- /dev/null
+++ b/torpedo.go
@@ -0,0 +1,88 @@
1package torpedo
2
3import (
4 "fmt"
5 "net/http"
6 "net/url"
7)
8
9const (
10 GET = "GET"
11 POST = "POST"
12 PUT = "PUT"
13 DELETE = "DELETE"
14)
15
16type Resource interface {
17 Get(values url.Values) (int, string)
18 Post(values url.Values) (int, string)
19 Put(values url.Values) (int, string)
20 Delete(values url.Values) (int, string)
21}
22
23type (
24 GetNotSupported struct{}
25 PostNotSupported struct{}
26 PutNotSupported struct{}
27 DeleteNotSupported struct{}
28)
29
30func (GetNotSupported) Get(values url.Values) (int, string) {
31 return 405, ""
32}
33
34func (PostNotSupported) Post(values url.Values) (int, string) {
35 return 405, ""
36}
37
38func (PutNotSupported) Put(values url.Values) (int, string) {
39 return 405, ""
40}
41
42func (DeleteNotSupported) Delete(values url.Values) (int, string) {
43 return 405, ""
44}
45
46type API struct{}
47
48func (api *API) Abort(rw http.ResponseWriter, statusCode int) {
49 rw.WriteHeader(statusCode)
50}
51
52func (api *API) requestHandler(resource Resource) http.HandlerFunc {
53 return func(rw http.ResponseWriter, request *http.Request) {
54
55 var data string
56 var code int
57
58 request.ParseForm()
59 method := request.Method
60 values := request.Form
61
62 switch method {
63 case GET:
64 code, data = resource.Get(values)
65 case POST:
66 code, data = resource.Post(values)
67 case PUT:
68 code, data = resource.Put(values)
69 case DELETE:
70 code, data = resource.Delete(values)
71 default:
72 api.Abort(rw, 405)
73 return
74 }
75
76 rw.WriteHeader(code)
77 rw.Write([]byte(data))
78 }
79}
80
81func (api *API) AddResource(resource Resource, path string) {
82 http.HandleFunc(path, api.requestHandler(resource))
83}
84
85func (api *API) Start(port int) {
86 portString := fmt.Sprintf(":%d", port)
87 http.ListenAndServe(portString, nil)
88}