github.com/titpetric/pendulum@v0.1.180207-1512.0.20180514135826-1f399445df57/cmd/pendulum/api.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "os" 6 "path" 7 "sort" 8 "time" 9 10 "encoding/json" 11 "io/ioutil" 12 "net/http" 13 ) 14 15 type Location struct { 16 Type string `json:"type"` 17 Path string `json:"path"` 18 Name string `json:"name"` 19 Dir string `json:"dir"` 20 LastModified string `json:"last_modified"` 21 } 22 23 type ListResponse struct { 24 Folder string `json:"folder"` 25 Files []Location `json:"files"` 26 } 27 28 type ByFolderAndName []Location 29 30 func (a ByFolderAndName) Len() int { 31 return len(a) 32 } 33 34 func (a ByFolderAndName) Swap(i, j int) { 35 a[i], a[j] = a[j], a[i] 36 } 37 38 func (a ByFolderAndName) Less(i, j int) bool { 39 if a[i].Type != a[j].Type { 40 if a[i].Type == "dir" { 41 return true 42 } 43 return false 44 } 45 return a[i].Name < a[j].Name 46 } 47 48 type ReadResponse struct { 49 Location 50 Contents string `json:"contents"` 51 } 52 53 type StoreResponse struct { 54 Status string `json:"status"` 55 Log string `json:"log"` 56 } 57 58 type API struct { 59 Path string 60 Assets http.HandlerFunc 61 Contents http.HandlerFunc 62 } 63 64 func (api *API) List(locationPath string) ([]Location, error) { 65 response := []Location{} 66 fullPath := path.Join(api.Path, locationPath) 67 info, err := os.Stat(fullPath) 68 if err != nil { 69 return response, err 70 } 71 if !info.IsDir() { 72 return response, fmt.Errorf("Path doesn't exist: %s", locationPath) 73 } 74 files, _ := ioutil.ReadDir(fullPath) 75 for _, f := range files { 76 name := f.Name() 77 if name[0:1] == "." { 78 continue 79 } 80 location := Location{ 81 Type: "file", 82 Path: path.Join(locationPath, name), 83 Name: name, 84 Dir: locationPath, 85 LastModified: f.ModTime().Format(time.UnixDate), 86 } 87 if !f.Mode().IsRegular() { 88 location.Type = "dir" 89 location.Path += "/" 90 } 91 response = append(response, location) 92 } 93 sort.Sort(ByFolderAndName(response)) 94 return response, nil 95 } 96 97 func (api *API) Read(filePath string) (ReadResponse, error) { 98 response := ReadResponse{ 99 Location: Location{ 100 Type: "file", 101 Path: filePath, 102 Name: path.Base(filePath), 103 Dir: path.Dir(filePath), 104 LastModified: time.Now().Format(time.UnixDate), 105 }, 106 } 107 fullPath := path.Join(api.Path, filePath) 108 info, err := os.Stat(fullPath) 109 if err != nil { 110 if os.IsNotExist(err) { 111 return response, nil 112 } 113 return response, err 114 } 115 if !info.Mode().IsRegular() { 116 return response, fmt.Errorf("Path is not a file: %s", filePath) 117 } 118 file, err := ioutil.ReadFile(fullPath) 119 if err != nil { 120 return response, err 121 } 122 response.LastModified = info.ModTime().Format(time.UnixDate) 123 response.Contents = string(file) 124 return response, nil 125 } 126 127 func (api *API) Store(filePath, contents string) (StoreResponse, error) { 128 response := StoreResponse{ 129 Status: "OK", 130 } 131 fullPath := path.Join(api.Path, filePath) 132 err := ioutil.WriteFile(fullPath, []byte(contents), 0644) 133 if err != nil { 134 return response, err 135 } 136 git := Git{ 137 Filename: fullPath, 138 } 139 response.Log, err = git.Commit() 140 return response, err 141 } 142 143 func (api *API) Error(err error) interface{} { 144 response := struct { 145 Error struct { 146 Message string `json:"message"` 147 } `json:"error"` 148 }{} 149 response.Error.Message = fmt.Sprintf("%s", err) 150 return response 151 } 152 153 func (api *API) ServeJSON(w http.ResponseWriter, r *http.Request, response interface{}) { 154 json, err := json.MarshalIndent(response, "", " ") 155 if err != nil { 156 http.Error(w, err.Error(), http.StatusInternalServerError) 157 return 158 } 159 160 w.Header().Set("Content-Type", "application/json") 161 w.Write(json) 162 }