A web API for returning Bible references and whole Bibles
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

146 lines
2.8 KiB

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "io/ioutil"
  6. "log"
  7. "net/http"
  8. "path"
  9. "strconv"
  10. "strings"
  11. "github.com/pelletier/go-toml"
  12. "code.heb12.com/heb12/bibleget/download"
  13. "code.heb12.com/heb12/bibleget/text"
  14. )
  15. const configFile = "config.toml"
  16. // Config is configuration for bibleget from the configFile
  17. type Config struct {
  18. Server server
  19. Bible bible
  20. }
  21. type server struct {
  22. Port int
  23. }
  24. type bible struct {
  25. Version string
  26. Dir string
  27. }
  28. // Response is the data that is returned to the user on any request to bibleget
  29. type Response struct {
  30. Errors []string `json:"errors"`
  31. Data map[string]interface{} `json:"data"`
  32. }
  33. // Handler is the http.ResponseWriter and http.Requst data for the rest of the program
  34. type Handler struct {
  35. w http.ResponseWriter
  36. r *http.Request
  37. }
  38. func shiftPath(p string) (head, tail string) {
  39. p = path.Clean("/" + p)
  40. i := strings.Index(p[1:], "/") + 1
  41. if i <= 0 {
  42. return p[1:], "/"
  43. }
  44. return p[1:i], p[i:]
  45. }
  46. func handler(w http.ResponseWriter, r *http.Request) {
  47. config, err := readConfig()
  48. if err != nil {
  49. log.Fatal(err)
  50. }
  51. var head string
  52. head, r.URL.Path = shiftPath(r.URL.Path)
  53. var b []byte
  54. errs := []string{}
  55. var response Response
  56. response.Data = make(map[string]interface{})
  57. err = r.ParseForm()
  58. if err != nil {
  59. log.Print(err)
  60. errs = append(errs, err.Error())
  61. }
  62. var version string
  63. if len(r.Form["version"]) != 0 {
  64. version = r.Form["version"][0]
  65. } else {
  66. version = config.Bible.Version
  67. }
  68. switch head {
  69. case "get":
  70. var tmpText []text.Text
  71. if len(r.Form["reference"]) == 0 {
  72. errs = append(errs, "No reference provided")
  73. } else {
  74. tmpText, err = text.GetText(config.Bible.Dir, r.Form["reference"][0], version)
  75. if err != nil {
  76. log.Print(err)
  77. errs = append(errs, err.Error())
  78. }
  79. }
  80. response.Data["text"] = tmpText
  81. case "download":
  82. fmt.Println(config.Bible.Dir)
  83. bibleTar, err := download.GetFile(config.Bible.Dir, version)
  84. if err != nil {
  85. errs = append(errs, "Failed to find tar file for "+version)
  86. } else {
  87. http.ServeFile(w, r, bibleTar)
  88. }
  89. default:
  90. }
  91. response.Errors = errs
  92. b, err = json.MarshalIndent(response, "", " ")
  93. if err != nil {
  94. log.Fatal(err)
  95. }
  96. w.Header().Add("Content-Type", "application/json")
  97. fmt.Fprintf(w, "%v", string(b))
  98. }
  99. func main() {
  100. config, err := readConfig()
  101. if err != nil {
  102. log.Fatal(err) // since with a faulty configuration, it can't get the text
  103. }
  104. http.HandleFunc("/", handler)
  105. log.Println("Running on port", config.Server.Port)
  106. log.Fatal(http.ListenAndServe(":"+strconv.Itoa(config.Server.Port), nil))
  107. }
  108. func readConfig() (Config, error) {
  109. bytes, err := ioutil.ReadFile(configFile)
  110. if err != nil {
  111. log.Fatalf("Failed to read config file %s, due to error: %v", configFile, err)
  112. }
  113. var config Config
  114. toml.Unmarshal(bytes, &config)
  115. return config, nil
  116. }