@@ -940,3 +940,151 @@ func (h *Handler) GetAmpForceModelMappings(c *gin.Context) {
940940func (h * Handler ) PutAmpForceModelMappings (c * gin.Context ) {
941941 h .updateBoolField (c , func (v bool ) { h .cfg .AmpCode .ForceModelMappings = v })
942942}
943+
944+ // GetAmpUpstreamAPIKeys returns the ampcode upstream API keys mapping.
945+ func (h * Handler ) GetAmpUpstreamAPIKeys (c * gin.Context ) {
946+ if h == nil || h .cfg == nil {
947+ c .JSON (200 , gin.H {"upstream-api-keys" : []config.AmpUpstreamAPIKeyEntry {}})
948+ return
949+ }
950+ c .JSON (200 , gin.H {"upstream-api-keys" : h .cfg .AmpCode .UpstreamAPIKeys })
951+ }
952+
953+ // PutAmpUpstreamAPIKeys replaces all ampcode upstream API keys mappings.
954+ func (h * Handler ) PutAmpUpstreamAPIKeys (c * gin.Context ) {
955+ var body struct {
956+ Value []config.AmpUpstreamAPIKeyEntry `json:"value"`
957+ }
958+ if err := c .ShouldBindJSON (& body ); err != nil {
959+ c .JSON (400 , gin.H {"error" : "invalid body" })
960+ return
961+ }
962+ // Normalize entries: trim whitespace, filter empty
963+ normalized := normalizeAmpUpstreamAPIKeyEntries (body .Value )
964+ h .cfg .AmpCode .UpstreamAPIKeys = normalized
965+ h .persist (c )
966+ }
967+
968+ // PatchAmpUpstreamAPIKeys adds or updates upstream API keys entries.
969+ // Matching is done by upstream-api-key value.
970+ func (h * Handler ) PatchAmpUpstreamAPIKeys (c * gin.Context ) {
971+ var body struct {
972+ Value []config.AmpUpstreamAPIKeyEntry `json:"value"`
973+ }
974+ if err := c .ShouldBindJSON (& body ); err != nil {
975+ c .JSON (400 , gin.H {"error" : "invalid body" })
976+ return
977+ }
978+
979+ existing := make (map [string ]int )
980+ for i , entry := range h .cfg .AmpCode .UpstreamAPIKeys {
981+ existing [strings .TrimSpace (entry .UpstreamAPIKey )] = i
982+ }
983+
984+ for _ , newEntry := range body .Value {
985+ upstreamKey := strings .TrimSpace (newEntry .UpstreamAPIKey )
986+ if upstreamKey == "" {
987+ continue
988+ }
989+ normalizedEntry := config.AmpUpstreamAPIKeyEntry {
990+ UpstreamAPIKey : upstreamKey ,
991+ APIKeys : normalizeAPIKeysList (newEntry .APIKeys ),
992+ }
993+ if idx , ok := existing [upstreamKey ]; ok {
994+ h .cfg .AmpCode .UpstreamAPIKeys [idx ] = normalizedEntry
995+ } else {
996+ h .cfg .AmpCode .UpstreamAPIKeys = append (h .cfg .AmpCode .UpstreamAPIKeys , normalizedEntry )
997+ existing [upstreamKey ] = len (h .cfg .AmpCode .UpstreamAPIKeys ) - 1
998+ }
999+ }
1000+ h .persist (c )
1001+ }
1002+
1003+ // DeleteAmpUpstreamAPIKeys removes specified upstream API keys entries.
1004+ // Body must be JSON: {"value": ["<upstream-api-key>", ...]}.
1005+ // If "value" is an empty array, clears all entries.
1006+ // If JSON is invalid or "value" is missing/null, returns 400 and does not persist any change.
1007+ func (h * Handler ) DeleteAmpUpstreamAPIKeys (c * gin.Context ) {
1008+ var body struct {
1009+ Value []string `json:"value"`
1010+ }
1011+ if err := c .ShouldBindJSON (& body ); err != nil {
1012+ c .JSON (400 , gin.H {"error" : "invalid body" })
1013+ return
1014+ }
1015+
1016+ if body .Value == nil {
1017+ c .JSON (400 , gin.H {"error" : "missing value" })
1018+ return
1019+ }
1020+
1021+ // Empty array means clear all
1022+ if len (body .Value ) == 0 {
1023+ h .cfg .AmpCode .UpstreamAPIKeys = nil
1024+ h .persist (c )
1025+ return
1026+ }
1027+
1028+ toRemove := make (map [string ]bool )
1029+ for _ , key := range body .Value {
1030+ trimmed := strings .TrimSpace (key )
1031+ if trimmed == "" {
1032+ continue
1033+ }
1034+ toRemove [trimmed ] = true
1035+ }
1036+ if len (toRemove ) == 0 {
1037+ c .JSON (400 , gin.H {"error" : "empty value" })
1038+ return
1039+ }
1040+
1041+ newEntries := make ([]config.AmpUpstreamAPIKeyEntry , 0 , len (h .cfg .AmpCode .UpstreamAPIKeys ))
1042+ for _ , entry := range h .cfg .AmpCode .UpstreamAPIKeys {
1043+ if ! toRemove [strings .TrimSpace (entry .UpstreamAPIKey )] {
1044+ newEntries = append (newEntries , entry )
1045+ }
1046+ }
1047+ h .cfg .AmpCode .UpstreamAPIKeys = newEntries
1048+ h .persist (c )
1049+ }
1050+
1051+ // normalizeAmpUpstreamAPIKeyEntries normalizes a list of upstream API key entries.
1052+ func normalizeAmpUpstreamAPIKeyEntries (entries []config.AmpUpstreamAPIKeyEntry ) []config.AmpUpstreamAPIKeyEntry {
1053+ if len (entries ) == 0 {
1054+ return nil
1055+ }
1056+ out := make ([]config.AmpUpstreamAPIKeyEntry , 0 , len (entries ))
1057+ for _ , entry := range entries {
1058+ upstreamKey := strings .TrimSpace (entry .UpstreamAPIKey )
1059+ if upstreamKey == "" {
1060+ continue
1061+ }
1062+ apiKeys := normalizeAPIKeysList (entry .APIKeys )
1063+ out = append (out , config.AmpUpstreamAPIKeyEntry {
1064+ UpstreamAPIKey : upstreamKey ,
1065+ APIKeys : apiKeys ,
1066+ })
1067+ }
1068+ if len (out ) == 0 {
1069+ return nil
1070+ }
1071+ return out
1072+ }
1073+
1074+ // normalizeAPIKeysList trims and filters empty strings from a list of API keys.
1075+ func normalizeAPIKeysList (keys []string ) []string {
1076+ if len (keys ) == 0 {
1077+ return nil
1078+ }
1079+ out := make ([]string , 0 , len (keys ))
1080+ for _ , k := range keys {
1081+ trimmed := strings .TrimSpace (k )
1082+ if trimmed != "" {
1083+ out = append (out , trimmed )
1084+ }
1085+ }
1086+ if len (out ) == 0 {
1087+ return nil
1088+ }
1089+ return out
1090+ }
0 commit comments