rentease/internal/server/handle_api_sync.go
Ruidy fe6beeded5
Some checks failed
CI / checks (push) Has been cancelled
feat(api): include booking URL in sync response
Enhance the booking sync API to return the full booking URL in the
response.
The URL is constructed based on the request's scheme and host,
supporting
both HTTP and HTTPS, and uses the X-Forwarded-Proto header if present.
This provides clients with a direct link to the created booking
resource.
2026-01-01 17:40:57 -04:00

95 lines
2.7 KiB
Go

package server
import (
"encoding/json"
"fmt"
"io"
"log/slog"
"net/http"
"strings"
"github.com/rjNemo/rentease/internal/constant"
"github.com/rjNemo/rentease/internal/service/booking"
)
func handleSync(bs *booking.Service) http.HandlerFunc {
type BookingInfo struct {
Content string `json:"content"`
}
return func(w http.ResponseWriter, r *http.Request) {
slog.Info("received booking sync request from booking")
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer r.Body.Close()
bookingInfo := new(BookingInfo)
if err := json.Unmarshal(body, bookingInfo); err != nil {
http.Error(w, fmt.Sprintf("error unmarshalling JSON: %s", err), http.StatusInternalServerError)
return
}
b, err := bs.ParseFromAPI(bookingInfo.Content)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
slog.Info("created booking from API", slog.String("name", b.Name), slog.String("platform", string(b.Platform)))
scheme := "http"
if proto := r.Header.Get("X-Forwarded-Proto"); proto != "" {
scheme = strings.TrimSpace(strings.Split(proto, ",")[0])
} else if r.TLS != nil {
scheme = "https"
}
bookingURL := fmt.Sprintf("%s://%s%s/%d", scheme, r.Host, constant.RouteBooking, b.ID)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
if err := json.NewEncoder(w).Encode(fmt.Sprintf("👍 %s", bookingURL)); err != nil {
slog.Error("failed to write response", slog.Any("error", err))
}
}
}
func handleCreateBooking(bs *booking.Service) http.HandlerFunc {
type BookingInfo struct {
Content string `json:"content"`
}
return func(w http.ResponseWriter, r *http.Request) {
slog.Info("received booking sync request from booking")
body, err := io.ReadAll(r.Body)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer r.Body.Close()
slog.Info("request body", slog.String("body", string(body)))
bookingInfo := new(BookingInfo)
if err := json.Unmarshal(body, bookingInfo); err != nil {
http.Error(w, fmt.Sprintf("error unmarshalling JSON: %s", err), http.StatusInternalServerError)
return
}
b, err := bs.ParseFromAPI(bookingInfo.Content)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
slog.Info("created booking from API", slog.String("name", b.Name), slog.String("platform", string(b.Platform)))
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
if err := json.NewEncoder(w).Encode("👍"); err != nil {
slog.Error("failed to write response", slog.Any("error", err))
}
}
}