dir.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * Rufs - Remote Union File System
  3. *
  4. * Copyright 2017 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the MIT
  7. * License, If a copy of the MIT License was not distributed with this
  8. * file, You can obtain one at https://opensource.org/licenses/MIT.
  9. */
  10. package v1
  11. import (
  12. "encoding/json"
  13. "fmt"
  14. "net/http"
  15. "os"
  16. "path"
  17. "strconv"
  18. "devt.de/krotik/common/stringutil"
  19. "devt.de/krotik/rufs"
  20. "devt.de/krotik/rufs/api"
  21. )
  22. /*
  23. EndpointDir is the dir endpoint URL (rooted). Handles everything
  24. under dir/...
  25. */
  26. const EndpointDir = api.APIRoot + APIv1 + "/dir/"
  27. /*
  28. DirEndpointInst creates a new endpoint handler.
  29. */
  30. func DirEndpointInst() api.RestEndpointHandler {
  31. return &dirEndpoint{}
  32. }
  33. /*
  34. Handler object for dir operations.
  35. */
  36. type dirEndpoint struct {
  37. *api.DefaultEndpointHandler
  38. }
  39. /*
  40. HandleGET handles a dir query REST call.
  41. */
  42. func (d *dirEndpoint) HandleGET(w http.ResponseWriter, r *http.Request, resources []string) {
  43. var tree *rufs.Tree
  44. var ok, checksums bool
  45. var err error
  46. var dirs []string
  47. var fis [][]os.FileInfo
  48. if len(resources) == 0 {
  49. http.Error(w, "Need at least a tree name",
  50. http.StatusBadRequest)
  51. return
  52. }
  53. if tree, ok, err = api.GetTree(resources[0]); err == nil && !ok {
  54. err = fmt.Errorf("Unknown tree: %v", resources[0])
  55. }
  56. if err == nil {
  57. var rex string
  58. glob := r.URL.Query().Get("glob")
  59. recursive, _ := strconv.ParseBool(r.URL.Query().Get("recursive"))
  60. checksums, _ = strconv.ParseBool(r.URL.Query().Get("checksums"))
  61. if rex, err = stringutil.GlobToRegex(glob); err == nil {
  62. dirs, fis, err = tree.Dir(path.Join(resources[1:]...), rex, recursive, checksums)
  63. }
  64. }
  65. if err != nil {
  66. http.Error(w, err.Error(), http.StatusBadRequest)
  67. return
  68. }
  69. data := make(map[string]interface{})
  70. for i, d := range dirs {
  71. var flist []map[string]interface{}
  72. fi := fis[i]
  73. for _, f := range fi {
  74. toAdd := map[string]interface{}{
  75. "name": f.Name(),
  76. "size": f.Size(),
  77. "isdir": f.IsDir(),
  78. }
  79. if checksums {
  80. toAdd["checksum"] = f.(*rufs.FileInfo).Checksum()
  81. }
  82. flist = append(flist, toAdd)
  83. }
  84. data[d] = flist
  85. }
  86. // Write data
  87. w.Header().Set("content-type", "application/json; charset=utf-8")
  88. json.NewEncoder(w).Encode(data)
  89. }
  90. /*
  91. SwaggerDefs is used to describe the endpoint in swagger.
  92. */
  93. func (d *dirEndpoint) SwaggerDefs(s map[string]interface{}) {
  94. s["paths"].(map[string]interface{})["/v1/dir/{tree}/{path}"] = map[string]interface{}{
  95. "get": map[string]interface{}{
  96. "summary": "Read a directory.",
  97. "description": "List the contents of a directory.",
  98. "produces": []string{
  99. "text/plain",
  100. "application/json",
  101. },
  102. "parameters": []map[string]interface{}{
  103. {
  104. "name": "tree",
  105. "in": "path",
  106. "description": "Name of the tree.",
  107. "required": true,
  108. "type": "string",
  109. },
  110. {
  111. "name": "path",
  112. "in": "path",
  113. "description": "Directory path.",
  114. "required": true,
  115. "type": "string",
  116. },
  117. {
  118. "name": "recursive",
  119. "in": "query",
  120. "description": "Add listings of subdirectories.",
  121. "required": false,
  122. "type": "boolean",
  123. },
  124. {
  125. "name": "checksums",
  126. "in": "query",
  127. "description": "Include file checksums.",
  128. "required": false,
  129. "type": "boolean",
  130. },
  131. },
  132. "responses": map[string]interface{}{
  133. "200": map[string]interface{}{
  134. "description": "Returns a map of directories with a list of files as values.",
  135. },
  136. "default": map[string]interface{}{
  137. "description": "Error response",
  138. "schema": map[string]interface{}{
  139. "$ref": "#/definitions/Error",
  140. },
  141. },
  142. },
  143. },
  144. }
  145. // Add generic error object to definition
  146. s["definitions"].(map[string]interface{})["Error"] = map[string]interface{}{
  147. "description": "A human readable error mesage.",
  148. "type": "string",
  149. }
  150. }