app.tmpl 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. package main
  2. import (
  3. "context"
  4. "encoding/json"
  5. "fmt"
  6. "io/ioutil"
  7. "net/http"
  8. "os"
  9. "os/signal"
  10. "strconv"
  11. "strings"
  12. "syscall"
  13. "time"
  14. "{{.URL}}/{{.Name}}/data"
  15. _ "github.com/lib/pq"
  16. "github.com/nats-io/go-nats"
  17. )
  18. type AppError struct {
  19. error
  20. Action string
  21. Data string
  22. }
  23. type EventMessage struct {
  24. Status string
  25. DataType string
  26. Data interface{}
  27. }
  28. type response struct {
  29. Message string `json:"message"`
  30. }
  31. func initializeNats() (*nats.EncodedConn, error) {
  32. nc, err := nats.Connect(nats.DefaultURL)
  33. if err != nil {
  34. return nil, err
  35. }
  36. c, err := nats.NewEncodedConn(nc, nats.JSON_ENCODER)
  37. if err != nil {
  38. return nil, err
  39. }
  40. return c, nil
  41. }
  42. func contextualize(timeout time.Duration) func(next http.Handler) http.Handler {
  43. return func(next http.Handler) http.Handler {
  44. fn := func(w http.ResponseWriter, r *http.Request) {
  45. ctx, cancel := context.WithTimeout(r.Context(), timeout)
  46. defer func() {
  47. cancel()
  48. if ctx.Err() == context.DeadlineExceeded {
  49. w.WriteHeader(http.StatusGatewayTimeout)
  50. }
  51. }()
  52. r = r.WithContext(ctx)
  53. next.ServeHTTP(w, r)
  54. }
  55. return http.HandlerFunc(fn)
  56. }
  57. }
  58. type chanRet struct {
  59. result []byte
  60. err error
  61. status int
  62. }
  63. func (app *application) runner(w http.ResponseWriter, r *http.Request, task func() *chanRet) {
  64. fin := make(chan *chanRet, 1)
  65. go func() {
  66. fin <- task()
  67. }()
  68. select {
  69. case <-r.Context().Done():
  70. close(fin)
  71. return
  72. case res := <-fin:
  73. if res.err != nil {
  74. fmt.Fprint(os.Stderr, res.err)
  75. app.Publish("error", res.err)
  76. }
  77. w.WriteHeader(res.status)
  78. w.Write(res.result)
  79. }
  80. }
  81. type application struct {
  82. db *db.DB
  83. events *nats.EncodedConn
  84. }
  85. func (a *application) Publish(action string, v interface{}) {
  86. subject := strings.ToLower("{{.Name}}.") + action + "." + strconv.Itoa(int(time.Now().Unix()))
  87. a.events.Flush()
  88. a.events.Publish(subject, v)
  89. }
  90. func execByVerb(r *http.Request, post func(body []byte) ([]byte, error), get func(key string) ([]byte, error), delete func(key string) error) *chanRet {
  91. var result []byte
  92. var err error
  93. switch r.Method {
  94. case http.MethodGet:
  95. key := r.URL.Query().Get("key")
  96. result, err = get(key)
  97. case http.MethodPut:
  98. case http.MethodPost:
  99. defer r.Body.Close()
  100. body, bodyReadErr := ioutil.ReadAll(r.Body)
  101. if bodyReadErr != nil {
  102. err = bodyReadErr
  103. } else {
  104. result, err = post(body)
  105. }
  106. case http.MethodDelete:
  107. key := r.URL.Query().Get("key")
  108. err = delete(key)
  109. result = []byte{'o', 'k'}
  110. }
  111. status := http.StatusOK
  112. if err != nil {
  113. status = http.StatusInternalServerError
  114. } else if err == nil && result == nil {
  115. status = http.StatusNotFound
  116. }
  117. return &chanRet{result, err, status}
  118. }
  119. func (app *application) root(w http.ResponseWriter, r *http.Request) {
  120. app.runner(w, r, func() *chanRet {
  121. return execByVerb(r,
  122. func(body []byte) ([]byte, error) {
  123. return nil, nil
  124. },
  125. func(key string) ([]byte, error) {
  126. return json.Marshal(&response{Message: "{{.Name}}"})
  127. },
  128. func(key string) error {
  129. return nil
  130. })
  131. })
  132. }
  133. {{.GetRoutes}}
  134. func main() {
  135. newDb, err := db.NewDB()
  136. if err != nil {
  137. panic(err)
  138. }
  139. nEvents, err := initializeNats()
  140. if err != nil {
  141. panic(err)
  142. }
  143. app := &application{
  144. db: newDb,
  145. events: nEvents,
  146. }
  147. mux := http.NewServeMux()
  148. mux.Handle("/", contextualize(time.Second*1)(http.HandlerFunc(app.root)))
  149. {{.MuxHandlers}}
  150. server := &http.Server{
  151. Addr: fmt.Sprintf(
  152. "%s:%d",
  153. "0.0.0.0",
  154. 9111,
  155. ),
  156. Handler: mux,
  157. }
  158. serverStartup := make(chan error, 1)
  159. go func() {
  160. serverStartup <- server.ListenAndServe()
  161. }()
  162. osSignals := make(chan os.Signal, 1)
  163. signal.Notify(
  164. osSignals,
  165. syscall.SIGINT,
  166. syscall.SIGTERM,
  167. syscall.SIGKILL,
  168. syscall.SIGQUIT,
  169. )
  170. select {
  171. case sig := <-osSignals:
  172. fmt.Printf(sig.String())
  173. case err := <-serverStartup:
  174. fmt.Printf(err.Error())
  175. }
  176. fmt.Printf("\n\nADIOS! TOT ZIENS! HASTA LUEGO!\n")
  177. }