/
server.go
148 lines (127 loc) · 4.03 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package main
import (
//"./dashboard" //REF1 //NOTE: This is to include bindata_assetfs.go for embedded ng-app.
"fmt"
"github.com/ant0ine/go-json-rest/rest"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
)
/* Editable structure */
type Editable struct {
FilePath string `json:"filepath"`
Content string `json:"content"`
Children []string `json:"children"`
}
func (e *Editable) FullPath() string {
return filepath.Join(projectDir, e.FilePath)
}
/* Project directory for editing */
var projectDir string = "/Users/ktt/w/webplug/project/"
/* List of Project files */
var projectFiles []Editable
/* Directory walking recursive function */
func collectProjectFiles(fp string, fi os.FileInfo, err error) error {
if err != nil {
log.Println(err.Error())
return nil // Can't walk here, move on
}
if !!fi.IsDir() {
return nil //not a file. Ignore.
}
matched, err := filepath.Match("*.*", fi.Name())
hmatched, _ := filepath.Match(".*", fi.Name())
if err != nil {
return err //malform pattern, failed.
}
if matched && !hmatched {
relPath, _ := filepath.Rel(projectDir, fp) // extract relative path
theEditable := Editable{relPath, "", []string{}}
projectFiles = append(projectFiles, theEditable) //collect
}
return nil
}
/* API: This returns the list of all files in project directory including files in
sub directory
> curl -i http://127.0.0.1:3000/api/files
*/
func FileTreeHandler(w rest.ResponseWriter, r *rest.Request) {
projectFiles = make([]Editable, 0)
filepath.Walk(projectDir, collectProjectFiles) // populate projectFiles
w.WriteJson(projectFiles)
}
/* API: This returns the file content of given file in project directory
> curl -i http://127.0.0.1:3000/api/files/open?t=
*/
func FileOpenHandler(w rest.ResponseWriter, r *rest.Request) {
r.ParseForm()
target := r.Form.Get("target")
if target == "" {
rest.Error(w, "Missing target file.", http.StatusBadRequest)
return
}
content, err := ioutil.ReadFile(projectDir + target)
if err != nil {
rest.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteJson(&Editable{target, fmt.Sprintf("%s", content), []string{}})
}
/* API: This write given content to given file in project directory */
func FileSaveHandler(w rest.ResponseWriter, r *rest.Request) {
// Get Payload
editable := Editable{}
err := r.DecodeJsonPayload(&editable)
if err != nil {
rest.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Create nested path incase missing
err = os.MkdirAll(filepath.Dir(editable.FullPath()), 0777)
if err != nil {
rest.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Write file and check error
log.Println(editable.FullPath())
err = ioutil.WriteFile(editable.FullPath(), []byte(editable.Content), 0644)
if err != nil {
rest.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusCreated)
}
func main() {
/* API Router setup */
api := rest.NewApi()
api.Use(&rest.AccessLogApacheMiddleware{})
api.Use(rest.DefaultCommonStack...)
api.Use(&rest.CorsMiddleware{ //TODO: To make origin configurable
RejectNonCorsRequests: false,
OriginValidator: func(origin string, request *rest.Request) bool {
return origin == "http://localhost:9000"
},
AllowedMethods: []string{"GET", "POST", "DELETE"},
AllowedHeaders: []string{
"Accept", "Content-Type", "X-Custom-Header", "Origin"},
AccessControlAllowCredentials: true,
AccessControlMaxAge: 3600,
})
apiRouter, _ := rest.MakeRouter(
rest.Get("/files", FileTreeHandler),
rest.Get("/files/open", FileOpenHandler),
rest.Post("/files/save", FileSaveHandler),
)
api.SetApp(apiRouter)
/* API endpoints */
http.Handle("/api/", http.StripPrefix("/api", api.MakeHandler()))
/* AngularJS App Distribution Directory
// NOTE: This requires import of ./dashboard and required dashboard/bindata_assetfs.go file.
// this is to embed front-end ng-app.
*/
//http.Handle("/", http.FileServer(dashboard.EassetFS())) // REF2, enable along with REF1
/* Now start the server */
log.Fatal(http.ListenAndServe(":3000", nil))
}