代理与否可控
This commit is contained in:
@@ -16,6 +16,7 @@ type mapTileSourceRequest struct {
|
|||||||
MaxZoom int `json:"max_zoom"`
|
MaxZoom int `json:"max_zoom"`
|
||||||
Enabled bool `json:"enabled"`
|
Enabled bool `json:"enabled"`
|
||||||
IsDefault bool `json:"is_default"`
|
IsDefault bool `json:"is_default"`
|
||||||
|
ProxyEnabled bool `json:"proxy_enabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerMapSourceRoutes(r gin.IRouter, store *store) {
|
func registerMapSourceRoutes(r gin.IRouter, store *store) {
|
||||||
@@ -102,6 +103,7 @@ func mapTileSourceInputFromRequest(req mapTileSourceRequest) mapTileSourceInput
|
|||||||
MaxZoom: req.MaxZoom,
|
MaxZoom: req.MaxZoom,
|
||||||
Enabled: req.Enabled,
|
Enabled: req.Enabled,
|
||||||
IsDefault: req.IsDefault,
|
IsDefault: req.IsDefault,
|
||||||
|
ProxyEnabled: req.ProxyEnabled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,13 +153,17 @@ func writeMapTileSourceDeleteResponse(c *gin.Context, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func mapTileSourceDTO(row mapTileSourceRecord) gin.H {
|
func mapTileSourceDTO(row mapTileSourceRecord) gin.H {
|
||||||
return gin.H{"id": row.ID, "name": row.Name, "url_template": row.URLTemplate, "attribution": row.Attribution, "max_zoom": row.MaxZoom, "enabled": row.Enabled, "is_default": row.IsDefault, "created_at": row.CreatedAt, "updated_at": row.UpdatedAt}
|
return gin.H{"id": row.ID, "name": row.Name, "url_template": row.URLTemplate, "attribution": row.Attribution, "max_zoom": row.MaxZoom, "enabled": row.Enabled, "is_default": row.IsDefault, "proxy_enabled": row.ProxyEnabled, "created_at": row.CreatedAt, "updated_at": row.UpdatedAt}
|
||||||
}
|
}
|
||||||
|
|
||||||
func publicMapTileSourceDTO(row mapTileSourceRecord) gin.H {
|
func publicMapTileSourceDTO(row mapTileSourceRecord) gin.H {
|
||||||
|
urlTemplate := row.URLTemplate
|
||||||
|
if row.ProxyEnabled {
|
||||||
hash := row.URLTemplateHash
|
hash := row.URLTemplateHash
|
||||||
if hash == "" {
|
if hash == "" {
|
||||||
hash = mapTileSourceHash(row.URLTemplate)
|
hash = mapTileSourceHash(row.URLTemplate)
|
||||||
}
|
}
|
||||||
return gin.H{"id": row.ID, "name": row.Name, "url_template": "/api/map/" + hash + "?x={x}&y={y}&z={z}", "attribution": row.Attribution, "max_zoom": row.MaxZoom}
|
urlTemplate = "/api/map/" + hash + "?x={x}&y={y}&z={z}"
|
||||||
|
}
|
||||||
|
return gin.H{"id": row.ID, "name": row.Name, "url_template": urlTemplate, "attribution": row.Attribution, "max_zoom": row.MaxZoom}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ type mapTileSourceRecord struct {
|
|||||||
MaxZoom int `gorm:"column:max_zoom;not null"`
|
MaxZoom int `gorm:"column:max_zoom;not null"`
|
||||||
Enabled bool `gorm:"column:enabled;not null;index"`
|
Enabled bool `gorm:"column:enabled;not null;index"`
|
||||||
IsDefault bool `gorm:"column:is_default;not null;index"`
|
IsDefault bool `gorm:"column:is_default;not null;index"`
|
||||||
|
ProxyEnabled bool `gorm:"column:proxy_enabled;not null;index"`
|
||||||
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime"`
|
CreatedAt time.Time `gorm:"column:created_at;autoCreateTime"`
|
||||||
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime;index"`
|
UpdatedAt time.Time `gorm:"column:updated_at;autoUpdateTime;index"`
|
||||||
}
|
}
|
||||||
@@ -472,6 +473,15 @@ func (s *store) migrate() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func migrateMapTileSourceHash(tx *gorm.DB, migrator gorm.Migrator, driver string) error {
|
func migrateMapTileSourceHash(tx *gorm.DB, migrator gorm.Migrator, driver string) error {
|
||||||
|
if !migrator.HasColumn(&mapTileSourceRecord{}, "ProxyEnabled") {
|
||||||
|
if driver == databaseDriverSQLite {
|
||||||
|
if err := tx.Exec("ALTER TABLE map_tile_sources ADD COLUMN proxy_enabled numeric NOT NULL DEFAULT true").Error; err != nil {
|
||||||
|
return fmt.Errorf("migrate map_tile_sources proxy_enabled column: %w", err)
|
||||||
|
}
|
||||||
|
} else if err := migrator.AddColumn(&mapTileSourceRecord{}, "ProxyEnabled"); err != nil {
|
||||||
|
return fmt.Errorf("migrate map_tile_sources proxy_enabled column: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
if !migrator.HasColumn(&mapTileSourceRecord{}, "URLTemplateHash") {
|
if !migrator.HasColumn(&mapTileSourceRecord{}, "URLTemplateHash") {
|
||||||
if driver == databaseDriverSQLite {
|
if driver == databaseDriverSQLite {
|
||||||
if err := tx.Exec("ALTER TABLE map_tile_sources ADD COLUMN url_template_hash TEXT NOT NULL DEFAULT ''").Error; err != nil {
|
if err := tx.Exec("ALTER TABLE map_tile_sources ADD COLUMN url_template_hash TEXT NOT NULL DEFAULT ''").Error; err != nil {
|
||||||
|
|||||||
+5
-1
@@ -35,6 +35,7 @@ type mapTileSourceInput struct {
|
|||||||
MaxZoom int
|
MaxZoom int
|
||||||
Enabled bool
|
Enabled bool
|
||||||
IsDefault bool
|
IsDefault bool
|
||||||
|
ProxyEnabled bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *store) ListMapTileSources(opts listOptions) ([]mapTileSourceRecord, error) {
|
func (s *store) ListMapTileSources(opts listOptions) ([]mapTileSourceRecord, error) {
|
||||||
@@ -85,7 +86,7 @@ func (s *store) GetDefaultMapTileSource() (*mapTileSourceRecord, error) {
|
|||||||
|
|
||||||
func (s *store) GetEnabledMapTileSourceByHash(hash string) (*mapTileSourceRecord, error) {
|
func (s *store) GetEnabledMapTileSourceByHash(hash string) (*mapTileSourceRecord, error) {
|
||||||
var row mapTileSourceRecord
|
var row mapTileSourceRecord
|
||||||
if err := s.db.Where("enabled = ? AND url_template_hash = ?", true, hash).Take(&row).Error; err != nil {
|
if err := s.db.Where("enabled = ? AND proxy_enabled = ? AND url_template_hash = ?", true, true, hash).Take(&row).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &row, nil
|
return &row, nil
|
||||||
@@ -154,6 +155,7 @@ func (s *store) UpdateMapTileSource(id uint64, input mapTileSourceInput) (*mapTi
|
|||||||
"max_zoom": row.MaxZoom,
|
"max_zoom": row.MaxZoom,
|
||||||
"enabled": row.Enabled,
|
"enabled": row.Enabled,
|
||||||
"is_default": row.IsDefault,
|
"is_default": row.IsDefault,
|
||||||
|
"proxy_enabled": row.ProxyEnabled,
|
||||||
"updated_at": time.Now(),
|
"updated_at": time.Now(),
|
||||||
}
|
}
|
||||||
if err := tx.Model(&mapTileSourceRecord{}).Where("id = ?", id).Updates(updates).Error; err != nil {
|
if err := tx.Model(&mapTileSourceRecord{}).Where("id = ?", id).Updates(updates).Error; err != nil {
|
||||||
@@ -269,6 +271,7 @@ func defaultMapTileSourceRecord() mapTileSourceRecord {
|
|||||||
MaxZoom: defaultMapTileSourceMaxZoom,
|
MaxZoom: defaultMapTileSourceMaxZoom,
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
IsDefault: true,
|
IsDefault: true,
|
||||||
|
ProxyEnabled: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -296,6 +299,7 @@ func mapTileSourceFromInput(input mapTileSourceInput) (*mapTileSourceRecord, err
|
|||||||
MaxZoom: maxZoom,
|
MaxZoom: maxZoom,
|
||||||
Enabled: input.Enabled,
|
Enabled: input.Enabled,
|
||||||
IsDefault: input.IsDefault,
|
IsDefault: input.IsDefault,
|
||||||
|
ProxyEnabled: input.ProxyEnabled,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+47
-10
@@ -25,13 +25,13 @@ func TestCreateMapTileSourceValidation(t *testing.T) {
|
|||||||
st := openTestStore(t)
|
st := openTestStore(t)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "bad", URLTemplate: "https://tiles.example.com/{z}/{x}.png", MaxZoom: 19, Enabled: true}); err == nil {
|
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "bad", URLTemplate: "https://tiles.example.com/{z}/{x}.png", MaxZoom: 19, Enabled: true, ProxyEnabled: true}); err == nil {
|
||||||
t.Fatal("CreateMapTileSource() missing placeholder error = nil, want error")
|
t.Fatal("CreateMapTileSource() missing placeholder error = nil, want error")
|
||||||
}
|
}
|
||||||
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "bad", URLTemplate: "javascript:alert(1)/{z}/{x}/{y}", MaxZoom: 19, Enabled: true}); err == nil {
|
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "bad", URLTemplate: "javascript:alert(1)/{z}/{x}/{y}", MaxZoom: 19, Enabled: true, ProxyEnabled: true}); err == nil {
|
||||||
t.Fatal("CreateMapTileSource() invalid scheme error = nil, want error")
|
t.Fatal("CreateMapTileSource() invalid scheme error = nil, want error")
|
||||||
}
|
}
|
||||||
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "bad", URLTemplate: "https://user:pass@tiles.example.com/{z}/{x}/{y}.png", MaxZoom: 19, Enabled: true}); err == nil {
|
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "bad", URLTemplate: "https://user:pass@tiles.example.com/{z}/{x}/{y}.png", MaxZoom: 19, Enabled: true, ProxyEnabled: true}); err == nil {
|
||||||
t.Fatal("CreateMapTileSource() credentials error = nil, want error")
|
t.Fatal("CreateMapTileSource() credentials error = nil, want error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ func TestListEnabledMapTileSources(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CreateMapTileSource(disabled) error = %v", err)
|
t.Fatalf("CreateMapTileSource(disabled) error = %v", err)
|
||||||
}
|
}
|
||||||
custom, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Custom", URLTemplate: "https://custom.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true})
|
custom, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Custom", URLTemplate: "https://custom.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CreateMapTileSource(custom) error = %v", err)
|
t.Fatalf("CreateMapTileSource(custom) error = %v", err)
|
||||||
}
|
}
|
||||||
@@ -76,14 +76,14 @@ func TestMapTileSourceDuplicateAndDefaultRules(t *testing.T) {
|
|||||||
st := openTestStore(t)
|
st := openTestStore(t)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
first, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Custom", URLTemplate: "https://tiles.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true})
|
first, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Custom", URLTemplate: "https://tiles.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CreateMapTileSource() error = %v", err)
|
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||||
}
|
}
|
||||||
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Custom", URLTemplate: "https://tiles2.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true}); !errors.Is(err, errMapTileSourceAlreadyExists) {
|
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Custom", URLTemplate: "https://tiles2.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true}); !errors.Is(err, errMapTileSourceAlreadyExists) {
|
||||||
t.Fatalf("duplicate name error = %v, want errMapTileSourceAlreadyExists", err)
|
t.Fatalf("duplicate name error = %v, want errMapTileSourceAlreadyExists", err)
|
||||||
}
|
}
|
||||||
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Custom 2", URLTemplate: first.URLTemplate, MaxZoom: 18, Enabled: true}); !errors.Is(err, errMapTileSourceAlreadyExists) {
|
if _, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Custom 2", URLTemplate: first.URLTemplate, MaxZoom: 18, Enabled: true, ProxyEnabled: true}); !errors.Is(err, errMapTileSourceAlreadyExists) {
|
||||||
t.Fatalf("duplicate url error = %v, want errMapTileSourceAlreadyExists", err)
|
t.Fatalf("duplicate url error = %v, want errMapTileSourceAlreadyExists", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,7 +114,7 @@ func TestMapTileSourceHashIsSetOnCreate(t *testing.T) {
|
|||||||
st := openTestStore(t)
|
st := openTestStore(t)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Hashed", URLTemplate: "https://test.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true})
|
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Hashed", URLTemplate: "https://test.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CreateMapTileSource() error = %v", err)
|
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||||
}
|
}
|
||||||
@@ -122,6 +122,9 @@ func TestMapTileSourceHashIsSetOnCreate(t *testing.T) {
|
|||||||
if row.URLTemplateHash != want {
|
if row.URLTemplateHash != want {
|
||||||
t.Fatalf("URLTemplateHash = %q, want %q", row.URLTemplateHash, want)
|
t.Fatalf("URLTemplateHash = %q, want %q", row.URLTemplateHash, want)
|
||||||
}
|
}
|
||||||
|
if !row.ProxyEnabled {
|
||||||
|
t.Fatal("ProxyEnabled = false, want true")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMapTileSourceDefaultHasHash(t *testing.T) {
|
func TestMapTileSourceDefaultHasHash(t *testing.T) {
|
||||||
@@ -142,7 +145,7 @@ func TestGetEnabledMapTileSourceByHash(t *testing.T) {
|
|||||||
st := openTestStore(t)
|
st := openTestStore(t)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "HashLookup", URLTemplate: "https://lookup.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true})
|
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "HashLookup", URLTemplate: "https://lookup.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CreateMapTileSource() error = %v", err)
|
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||||
}
|
}
|
||||||
@@ -171,6 +174,21 @@ func TestGetEnabledMapTileSourceByHashDisabled(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetEnabledMapTileSourceByHashProxyDisabled(t *testing.T) {
|
||||||
|
st := openTestStore(t)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "ProxyDisabledHash", URLTemplate: "https://proxy-disabled.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: false})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = st.GetEnabledMapTileSourceByHash(row.URLTemplateHash)
|
||||||
|
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
t.Fatalf("GetEnabledMapTileSourceByHash(proxy disabled) = %v, want gorm.ErrRecordNotFound", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetEnabledMapTileSourceByHashUnknown(t *testing.T) {
|
func TestGetEnabledMapTileSourceByHashUnknown(t *testing.T) {
|
||||||
st := openTestStore(t)
|
st := openTestStore(t)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
@@ -185,7 +203,7 @@ func TestPublicMapTileSourceDTOProxyURL(t *testing.T) {
|
|||||||
st := openTestStore(t)
|
st := openTestStore(t)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "ProxyTest", URLTemplate: "https://proxy.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true})
|
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "ProxyTest", URLTemplate: "https://proxy.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CreateMapTileSource() error = %v", err)
|
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||||
}
|
}
|
||||||
@@ -204,6 +222,25 @@ func TestPublicMapTileSourceDTOProxyURL(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPublicMapTileSourceDTORawURLWhenProxyDisabled(t *testing.T) {
|
||||||
|
st := openTestStore(t)
|
||||||
|
defer st.Close()
|
||||||
|
|
||||||
|
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "RawTest", URLTemplate: "https://raw.example.com/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: false})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
dto := publicMapTileSourceDTO(*row)
|
||||||
|
urlTemplate, ok := dto["url_template"].(string)
|
||||||
|
if !ok {
|
||||||
|
t.Fatal("url_template is not a string")
|
||||||
|
}
|
||||||
|
if urlTemplate != row.URLTemplate {
|
||||||
|
t.Fatalf("url_template = %q, want raw %q", urlTemplate, row.URLTemplate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMapTileSourceHashFunction(t *testing.T) {
|
func TestMapTileSourceHashFunction(t *testing.T) {
|
||||||
hash1 := mapTileSourceHash("https://tile.openstreetmap.jp/{z}/{x}/{y}.png")
|
hash1 := mapTileSourceHash("https://tile.openstreetmap.jp/{z}/{x}/{y}.png")
|
||||||
hash2 := mapTileSourceHash("https://tile.openstreetmap.jp/{z}/{x}/{y}.png")
|
hash2 := mapTileSourceHash("https://tile.openstreetmap.jp/{z}/{x}/{y}.png")
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func TestMapTileProxyFetchesAndCaches(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
defer upstream.Close()
|
defer upstream.Close()
|
||||||
|
|
||||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Tiles", URLTemplate: upstream.URL + "/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true})
|
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Tiles", URLTemplate: upstream.URL + "/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CreateMapTileSource() error = %v", err)
|
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ func TestMapTileProxyRejectsInvalidCoordinates(t *testing.T) {
|
|||||||
st := openTestStore(t)
|
st := openTestStore(t)
|
||||||
defer st.Close()
|
defer st.Close()
|
||||||
|
|
||||||
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Tiles", URLTemplate: "https://tiles.example.com/{z}/{x}/{y}.png", MaxZoom: 3, Enabled: true})
|
row, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Tiles", URLTemplate: "https://tiles.example.com/{z}/{x}/{y}.png", MaxZoom: 3, Enabled: true, ProxyEnabled: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CreateMapTileSource() error = %v", err)
|
t.Fatalf("CreateMapTileSource() error = %v", err)
|
||||||
}
|
}
|
||||||
@@ -91,7 +91,11 @@ func TestMapTileProxyUnknownAndDisabledSource(t *testing.T) {
|
|||||||
|
|
||||||
disabled, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Disabled", URLTemplate: "https://disabled.example.com/{z}/{x}/{y}.png", MaxZoom: 3, Enabled: false})
|
disabled, err := st.CreateMapTileSource(mapTileSourceInput{Name: "Disabled", URLTemplate: "https://disabled.example.com/{z}/{x}/{y}.png", MaxZoom: 3, Enabled: false})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CreateMapTileSource() error = %v", err)
|
t.Fatalf("CreateMapTileSource(disabled) error = %v", err)
|
||||||
|
}
|
||||||
|
proxyDisabled, err := st.CreateMapTileSource(mapTileSourceInput{Name: "ProxyDisabled", URLTemplate: "https://proxy-disabled.example.com/{z}/{x}/{y}.png", MaxZoom: 3, Enabled: true, ProxyEnabled: false})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("CreateMapTileSource(proxy disabled) error = %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
router := newRouter(webConfig{StaticDir: t.TempDir(), MapTileCacheDir: t.TempDir()}, st, nil, nil, nil, nil, nil)
|
router := newRouter(webConfig{StaticDir: t.TempDir(), MapTileCacheDir: t.TempDir()}, st, nil, nil, nil, nil, nil)
|
||||||
@@ -100,8 +104,9 @@ func TestMapTileProxyUnknownAndDisabledSource(t *testing.T) {
|
|||||||
"/api/map/not-a-hash?x=0&y=0&z=0",
|
"/api/map/not-a-hash?x=0&y=0&z=0",
|
||||||
"/api/map/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?x=0&y=0&z=0",
|
"/api/map/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?x=0&y=0&z=0",
|
||||||
"/api/map/" + disabled.URLTemplateHash + "?x=0&y=0&z=0",
|
"/api/map/" + disabled.URLTemplateHash + "?x=0&y=0&z=0",
|
||||||
|
"/api/map/" + proxyDisabled.URLTemplateHash + "?x=0&y=0&z=0",
|
||||||
}
|
}
|
||||||
wantStatus := []int{http.StatusBadRequest, http.StatusNotFound, http.StatusNotFound}
|
wantStatus := []int{http.StatusBadRequest, http.StatusNotFound, http.StatusNotFound, http.StatusNotFound}
|
||||||
for i, url := range cases {
|
for i, url := range cases {
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
req := httptest.NewRequest(http.MethodGet, url, nil)
|
req := httptest.NewRequest(http.MethodGet, url, nil)
|
||||||
@@ -125,11 +130,11 @@ func TestMapTileProxyUpstreamStatus(t *testing.T) {
|
|||||||
}))
|
}))
|
||||||
defer upstream.Close()
|
defer upstream.Close()
|
||||||
|
|
||||||
row404, err := st.CreateMapTileSource(mapTileSourceInput{Name: "NotFoundTiles", URLTemplate: upstream.URL + "/404/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true})
|
row404, err := st.CreateMapTileSource(mapTileSourceInput{Name: "NotFoundTiles", URLTemplate: upstream.URL + "/404/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CreateMapTileSource(404) error = %v", err)
|
t.Fatalf("CreateMapTileSource(404) error = %v", err)
|
||||||
}
|
}
|
||||||
row500, err := st.CreateMapTileSource(mapTileSourceInput{Name: "StatusTiles", URLTemplate: upstream.URL + "/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true})
|
row500, err := st.CreateMapTileSource(mapTileSourceInput{Name: "StatusTiles", URLTemplate: upstream.URL + "/{z}/{x}/{y}.png", MaxZoom: 18, Enabled: true, ProxyEnabled: true})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("CreateMapTileSource(500) error = %v", err)
|
t.Fatalf("CreateMapTileSource(500) error = %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ const newSource = ref<MapTileSourcePayload>({
|
|||||||
max_zoom: 19,
|
max_zoom: 19,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
is_default: false,
|
is_default: false,
|
||||||
|
proxy_enabled: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
const canPrev = () => page.value > 1
|
const canPrev = () => page.value > 1
|
||||||
@@ -32,6 +33,7 @@ function editableCopy(item: MapTileSource): MapTileSourcePayload {
|
|||||||
max_zoom: item.max_zoom,
|
max_zoom: item.max_zoom,
|
||||||
enabled: item.enabled,
|
enabled: item.enabled,
|
||||||
is_default: item.is_default,
|
is_default: item.is_default,
|
||||||
|
proxy_enabled: item.proxy_enabled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,6 +47,7 @@ function resetNewSource() {
|
|||||||
max_zoom: 19,
|
max_zoom: 19,
|
||||||
enabled: true,
|
enabled: true,
|
||||||
is_default: false,
|
is_default: false,
|
||||||
|
proxy_enabled: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,6 +217,7 @@ onMounted(refreshItems)
|
|||||||
<label class="field zoom-field">最大缩放<input v-model.number="newSource.max_zoom" type="number" min="1" max="30" /></label>
|
<label class="field zoom-field">最大缩放<input v-model.number="newSource.max_zoom" type="number" min="1" max="30" /></label>
|
||||||
<label class="switch-card"><input v-model="newSource.enabled" type="checkbox" /> <span>启用</span></label>
|
<label class="switch-card"><input v-model="newSource.enabled" type="checkbox" /> <span>启用</span></label>
|
||||||
<label class="switch-card"><input v-model="newSource.is_default" type="checkbox" /> <span>设为默认</span></label>
|
<label class="switch-card"><input v-model="newSource.is_default" type="checkbox" /> <span>设为默认</span></label>
|
||||||
|
<label class="switch-card"><input v-model="newSource.proxy_enabled" type="checkbox" /> <span>是否代理</span></label>
|
||||||
<div class="form-actions">
|
<div class="form-actions">
|
||||||
<button class="admin-button" type="submit" :disabled="loading">添加图源</button>
|
<button class="admin-button" type="submit" :disabled="loading">添加图源</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -254,6 +258,7 @@ onMounted(refreshItems)
|
|||||||
<label class="field attribution-field">Attribution<input v-model="drafts[item.id].attribution" /></label>
|
<label class="field attribution-field">Attribution<input v-model="drafts[item.id].attribution" /></label>
|
||||||
<label class="field zoom-field">最大缩放<input v-model.number="drafts[item.id].max_zoom" type="number" min="1" max="30" /></label>
|
<label class="field zoom-field">最大缩放<input v-model.number="drafts[item.id].max_zoom" type="number" min="1" max="30" /></label>
|
||||||
<label class="switch-card"><input v-model="drafts[item.id].enabled" type="checkbox" :disabled="item.is_default" /> <span>启用图源</span></label>
|
<label class="switch-card"><input v-model="drafts[item.id].enabled" type="checkbox" :disabled="item.is_default" /> <span>启用图源</span></label>
|
||||||
|
<label class="switch-card"><input v-model="drafts[item.id].proxy_enabled" type="checkbox" /> <span>是否代理</span></label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="source-meta">
|
<div class="source-meta">
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ export interface PublicMapTileSource {
|
|||||||
export interface MapTileSource extends PublicMapTileSource {
|
export interface MapTileSource extends PublicMapTileSource {
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
is_default: boolean
|
is_default: boolean
|
||||||
|
proxy_enabled: boolean
|
||||||
created_at: string
|
created_at: string
|
||||||
updated_at: string
|
updated_at: string
|
||||||
}
|
}
|
||||||
@@ -98,6 +99,7 @@ export interface MapTileSourcePayload {
|
|||||||
max_zoom: number
|
max_zoom: number
|
||||||
enabled: boolean
|
enabled: boolean
|
||||||
is_default: boolean
|
is_default: boolean
|
||||||
|
proxy_enabled: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MapTileSourceResponse {
|
export interface MapTileSourceResponse {
|
||||||
|
|||||||
Reference in New Issue
Block a user