mirror of
https://github.com/KevinMidboe/planetposen-mail.git
synced 2025-10-29 09:40:32 +00:00
Mail api for sending order confirmation to planetposen customers
This commit is contained in:
55
server/handler/confirmation.go
Normal file
55
server/handler/confirmation.go
Normal file
@@ -0,0 +1,55 @@
|
||||
// Package handler contains handlers for events.
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/kevinmidboe/planetposen-mail/client/sendgrid"
|
||||
"github.com/kevinmidboe/planetposen-mail/mail"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func SendOrderConfirmation(s *sendgrid.Client) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
payload, err := getOrderConfirmationPayload(r)
|
||||
|
||||
if err != nil {
|
||||
handleError(w, err, "unable to parse order payload", http.StatusBadRequest, true)
|
||||
return
|
||||
}
|
||||
mailData, err := mail.OrderConfirmation(*payload)
|
||||
|
||||
err = s.SendOrderConfirmation(ctx, *mailData)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
handleError(w, err, "error from sendgrid ", http.StatusInternalServerError, true)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
responseJSON, _ := json.Marshal(struct {
|
||||
Message string `json:"message"`
|
||||
OrderId string `json:"orderId"`
|
||||
Recipient string `json:"recipient"`
|
||||
}{
|
||||
Message: "Successfully sent email",
|
||||
OrderId: payload.OrderId,
|
||||
Recipient: payload.Email,
|
||||
})
|
||||
w.Write(responseJSON)
|
||||
}
|
||||
}
|
||||
|
||||
func getOrderConfirmationPayload(r *http.Request) (*mail.OrderConfirmationData, error) {
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
|
||||
var payload mail.OrderConfirmationData
|
||||
err := decoder.Decode(&payload)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decode: %w", err)
|
||||
}
|
||||
|
||||
return &payload, nil
|
||||
}
|
||||
24
server/handler/error.go
Normal file
24
server/handler/error.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// handleError - Logs the error (if shouldLog is true), and outputs the error message (msg)
|
||||
func handleError(w http.ResponseWriter, err error, msg string, statusCode int, shouldLog bool) {
|
||||
if shouldLog {
|
||||
log.WithField("err", err).Error(msg)
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(statusCode)
|
||||
errorJSON, _ := json.Marshal(struct {
|
||||
Error string `json:"error"`
|
||||
}{
|
||||
Error: msg,
|
||||
})
|
||||
w.Write(errorJSON)
|
||||
}
|
||||
11
server/handler/healthz.go
Normal file
11
server/handler/healthz.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package handler
|
||||
|
||||
import "net/http"
|
||||
|
||||
// Healthz is used for our readiness and liveness probes.
|
||||
// GET /_healthz
|
||||
// Responds: 200
|
||||
func Healthz(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(http.StatusText(http.StatusOK)))
|
||||
}
|
||||
14
server/router.go
Normal file
14
server/router.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"github.com/kevinmidboe/planetposen-mail/server/handler"
|
||||
)
|
||||
|
||||
const v1API string = "/api/v1/"
|
||||
|
||||
func (s *Server) setupRoutes() {
|
||||
s.Router.HandleFunc("/_healthz", handler.Healthz).Methods("GET").Name("Health")
|
||||
|
||||
api := s.Router.PathPrefix(v1API).Subrouter()
|
||||
api.HandleFunc("/send-confirmation", handler.SendOrderConfirmation(s.SendGrid)).Methods("POST").Name("SendOrderConfirmation")
|
||||
}
|
||||
85
server/server.go
Normal file
85
server/server.go
Normal file
@@ -0,0 +1,85 @@
|
||||
// Package server provides functionality to easily set up an HTTTP server.
|
||||
//
|
||||
// Clients:
|
||||
// Database
|
||||
package server
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/kevinmidboe/planetposen-mail/client/sendgrid"
|
||||
"github.com/kevinmidboe/planetposen-mail/config"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Server holds the HTTP server, router, config and all clients.
|
||||
type Server struct {
|
||||
Config *config.Config
|
||||
HTTP *http.Server
|
||||
Router *mux.Router
|
||||
SendGrid *sendgrid.Client
|
||||
}
|
||||
|
||||
// Create sets up the HTTP server, router and all clients.
|
||||
// Returns an error if an error occurs.
|
||||
func (s *Server) Create(ctx context.Context, config *config.Config) error {
|
||||
// metrics.RegisterPrometheusCollectors()
|
||||
|
||||
s.Config = config
|
||||
s.Router = mux.NewRouter()
|
||||
s.HTTP = &http.Server{
|
||||
Addr: fmt.Sprintf(":%s", s.Config.Port),
|
||||
Handler: s.Router,
|
||||
}
|
||||
|
||||
var sendGridClient sendgrid.Client
|
||||
if err := sendGridClient.Init(config); err != nil {
|
||||
return fmt.Errorf("error initializing sendgrid client: %w", err)
|
||||
}
|
||||
|
||||
s.SendGrid = &sendGridClient
|
||||
|
||||
s.setupRoutes()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Serve tells the server to start listening and serve HTTP requests.
|
||||
// It also makes sure that the server gracefully shuts down on exit.
|
||||
// Returns an error if an error occurs.
|
||||
func (s *Server) Serve(ctx context.Context) error {
|
||||
// closer, err := trace.InitGlobalTracer(s.Config)
|
||||
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
|
||||
// defer closer.Close()
|
||||
|
||||
go func(ctx context.Context, s *Server) {
|
||||
stop := make(chan os.Signal, 1)
|
||||
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
<-stop
|
||||
|
||||
log.Info("Shutdown signal received")
|
||||
|
||||
if err := s.HTTP.Shutdown(ctx); err != nil {
|
||||
log.Error(err.Error())
|
||||
}
|
||||
}(ctx, s)
|
||||
|
||||
log.Infof("Ready at: %s", s.Config.Port)
|
||||
|
||||
if err := s.HTTP.ListenAndServe(); err != http.ErrServerClosed {
|
||||
log.Fatalf(err.Error())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user