package http import ( "context" "errors" "net/http" "strings" "primaya-api/cpone-middleware/internal/databaseconfig" "primaya-api/cpone-middleware/internal/repository" ) type selectedRepositoryKey struct{} type DatabaseResolver interface { Resolve(ctx context.Context, code string) (repository.MySQLLayananRepository, error) } func BearerAuth(staticToken string, next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if bearerToken(r.Header.Get("Authorization")) != staticToken { WriteJSON(w, http.StatusUnauthorized, Response{ Success: false, Message: "Unauthenticated.", Data: nil, }) return } next.ServeHTTP(w, r) }) } func SelectDatabase(resolver DatabaseResolver, next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { code := strings.TrimSpace(r.Header.Get("X-RS-Code")) if code == "" { code = strings.TrimSpace(r.URL.Query().Get("kode_rs")) } if code == "" { WriteJSON(w, http.StatusUnprocessableEntity, Response{Success: false, Message: "Kode RS wajib diisi melalui header X-RS-Code atau parameter kode_rs", Data: nil}) return } code = databaseconfig.NormalizeRSCode(code) repo, err := resolver.Resolve(r.Context(), code) if err != nil { if errors.Is(err, databaseconfig.ErrRSCodeMismatch) { WriteJSON(w, http.StatusForbidden, Response{Success: false, Message: "X-RS-Code tidak sesuai dengan instance CPONE", Data: nil}) return } WriteJSON(w, http.StatusServiceUnavailable, Response{Success: false, Message: "Database HIS tidak dapat diakses", Data: nil}) return } w.Header().Set("X-RS-Code", code) ctx := context.WithValue(r.Context(), selectedRepositoryKey{}, repo) next.ServeHTTP(w, r.WithContext(ctx)) }) } func selectedRepository(ctx context.Context) (repository.MySQLLayananRepository, bool) { repo, ok := ctx.Value(selectedRepositoryKey{}).(repository.MySQLLayananRepository) return repo, ok } func bearerToken(header string) string { const prefix = "Bearer " if !strings.HasPrefix(header, prefix) { return "" } return strings.TrimSpace(strings.TrimPrefix(header, prefix)) }