feat: add env vars to disable render endpoints
BLOCKY_DISABLE_GLB/PNG/GIF/MP4 return 403 when set to true
This commit is contained in:
parent
ce511e1a85
commit
f8947fdcc4
5 changed files with 110 additions and 7 deletions
16
CLAUDE.md
16
CLAUDE.md
|
|
@ -25,9 +25,9 @@ BlockyServer is an HTTP API for rendering Hytale character models. It wraps the
|
||||||
```
|
```
|
||||||
HTTP Request → api.Handlers → service.MergeService → blockymodel-merger pkg
|
HTTP Request → api.Handlers → service.MergeService → blockymodel-merger pkg
|
||||||
↓
|
↓
|
||||||
render.RenderPNG/GIF (for image endpoints)
|
render.RenderPNG/GIF/MP4 (for image/video endpoints)
|
||||||
↓
|
↓
|
||||||
HTTP Response (GLB/PNG/GIF)
|
HTTP Response (GLB/PNG/GIF/MP4)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Package Structure
|
### Package Structure
|
||||||
|
|
@ -49,6 +49,17 @@ Server requires these directories at runtime (relative to working directory):
|
||||||
- `assets/` - Character models (.blockymodel), textures
|
- `assets/` - Character models (.blockymodel), textures
|
||||||
- `data/` - JSON registry files (accessories, colors, gradients)
|
- `data/` - JSON registry files (accessories, colors, gradients)
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| `BLOCKY_DISABLE_GLB` | `false` | Disable `/render/glb` endpoint (returns 403) |
|
||||||
|
| `BLOCKY_DISABLE_PNG` | `false` | Disable `/render/png` endpoint (returns 403) |
|
||||||
|
| `BLOCKY_DISABLE_GIF` | `false` | Disable `/render/gif` endpoint (returns 403) |
|
||||||
|
| `BLOCKY_DISABLE_MP4` | `false` | Disable `/render/mp4` endpoint (returns 403) |
|
||||||
|
|
||||||
|
Set to `true`, `1`, or `yes` to disable an endpoint.
|
||||||
|
|
||||||
### API Endpoints
|
### API Endpoints
|
||||||
|
|
||||||
| Endpoint | Method | Description |
|
| Endpoint | Method | Description |
|
||||||
|
|
@ -56,6 +67,7 @@ Server requires these directories at runtime (relative to working directory):
|
||||||
| `/render/glb` | POST | Character JSON → GLB binary |
|
| `/render/glb` | POST | Character JSON → GLB binary |
|
||||||
| `/render/png` | POST | Character JSON + options → PNG image |
|
| `/render/png` | POST | Character JSON + options → PNG image |
|
||||||
| `/render/gif` | POST | Character JSON + options → Animated GIF |
|
| `/render/gif` | POST | Character JSON + options → Animated GIF |
|
||||||
|
| `/render/mp4` | POST | Character JSON + options → MP4 video (requires FFmpeg) |
|
||||||
| `/docs` | GET | Swagger UI |
|
| `/docs` | GET | Swagger UI |
|
||||||
| `/openapi.json` | GET | OpenAPI spec |
|
| `/openapi.json` | GET | OpenAPI spec |
|
||||||
| `/health` | GET | Health check |
|
| `/health` | GET | Health check |
|
||||||
|
|
|
||||||
22
README.md
22
README.md
|
|
@ -4,7 +4,7 @@
|
||||||
> Not affiliated with Hypixel Studios.
|
> Not affiliated with Hypixel Studios.
|
||||||
> All trademarks and assets are property of their respective owners.
|
> All trademarks and assets are property of their respective owners.
|
||||||
|
|
||||||
HTTP API for rendering Hytale character models as GLB, PNG, or animated GIF.
|
HTTP API for rendering Hytale character models as GLB, PNG, animated GIF, or MP4 video.
|
||||||
|
|
||||||
Built on top of [blockymodel-merger](https://github.com/hytale-tools/blockymodel-merger) by [JackGamesFTW](https://github.com/JackGamesFTW), special thanks to him!
|
Built on top of [blockymodel-merger](https://github.com/hytale-tools/blockymodel-merger) by [JackGamesFTW](https://github.com/JackGamesFTW), special thanks to him!
|
||||||
|
|
||||||
|
|
@ -14,6 +14,7 @@ Built on top of [blockymodel-merger](https://github.com/hytale-tools/blockymodel
|
||||||
- Export as GLB (glTF binary)
|
- Export as GLB (glTF binary)
|
||||||
- Render to PNG with configurable rotation and background
|
- Render to PNG with configurable rotation and background
|
||||||
- Render to animated rotating GIF
|
- Render to animated rotating GIF
|
||||||
|
- Render to MP4 video (requires FFmpeg)
|
||||||
- Swagger UI documentation
|
- Swagger UI documentation
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
@ -69,6 +70,24 @@ go build -o blockyserver.exe .
|
||||||
./blockyserver.exe -port 3000
|
./blockyserver.exe -port 3000
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
| Variable | Default | Description |
|
||||||
|
|----------|---------|-------------|
|
||||||
|
| `BLOCKY_DISABLE_GLB` | `false` | Disable `/render/glb` endpoint |
|
||||||
|
| `BLOCKY_DISABLE_PNG` | `false` | Disable `/render/png` endpoint |
|
||||||
|
| `BLOCKY_DISABLE_GIF` | `false` | Disable `/render/gif` endpoint |
|
||||||
|
| `BLOCKY_DISABLE_MP4` | `false` | Disable `/render/mp4` endpoint |
|
||||||
|
|
||||||
|
Set to `true`, `1`, or `yes` to disable. Disabled endpoints return `403 Forbidden`.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Example: disable GIF and MP4 endpoints
|
||||||
|
BLOCKY_DISABLE_GIF=true BLOCKY_DISABLE_MP4=true ./blockyserver.exe
|
||||||
|
```
|
||||||
|
|
||||||
## Docker
|
## Docker
|
||||||
|
|
||||||
### Using Docker Compose (recommended)
|
### Using Docker Compose (recommended)
|
||||||
|
|
@ -99,6 +118,7 @@ docker run -d -p 8080:8080 \
|
||||||
| `/render/glb` | POST | Returns GLB binary |
|
| `/render/glb` | POST | Returns GLB binary |
|
||||||
| `/render/png` | POST | Returns PNG image |
|
| `/render/png` | POST | Returns PNG image |
|
||||||
| `/render/gif` | POST | Returns animated GIF |
|
| `/render/gif` | POST | Returns animated GIF |
|
||||||
|
| `/render/mp4` | POST | Returns MP4 video |
|
||||||
| `/docs` | GET | Swagger UI |
|
| `/docs` | GET | Swagger UI |
|
||||||
| `/openapi.json` | GET | OpenAPI specification |
|
| `/openapi.json` | GET | OpenAPI specification |
|
||||||
| `/health` | GET | Health check |
|
| `/health` | GET | Health check |
|
||||||
|
|
|
||||||
35
internal/api/middleware.go
Normal file
35
internal/api/middleware.go
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"blockyserver/internal/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EndpointGuard creates middleware that returns 403 if endpoint is disabled
|
||||||
|
func EndpointGuard(enabled bool, endpointName string) func(http.Handler) http.Handler {
|
||||||
|
return func(next http.Handler) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if !enabled {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(http.StatusForbidden)
|
||||||
|
json.NewEncoder(w).Encode(ErrorResponse{
|
||||||
|
Error: endpointName + " endpoint is disabled",
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
next.ServeHTTP(w, r)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEndpointGuards creates guards for all render endpoints based on config
|
||||||
|
func NewEndpointGuards(cfg *config.EndpointConfig) map[string]func(http.Handler) http.Handler {
|
||||||
|
return map[string]func(http.Handler) http.Handler{
|
||||||
|
"glb": EndpointGuard(cfg.GLBEnabled, "/render/glb"),
|
||||||
|
"png": EndpointGuard(cfg.PNGEnabled, "/render/png"),
|
||||||
|
"gif": EndpointGuard(cfg.GIFEnabled, "/render/gif"),
|
||||||
|
"mp4": EndpointGuard(cfg.MP4Enabled, "/render/mp4"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"blockyserver/internal/config"
|
||||||
"blockyserver/internal/service"
|
"blockyserver/internal/service"
|
||||||
|
|
||||||
"github.com/go-chi/chi/v5"
|
"github.com/go-chi/chi/v5"
|
||||||
|
|
@ -19,6 +20,10 @@ func NewServer(svc *service.MergeService) http.Handler {
|
||||||
r.Use(middleware.Recoverer)
|
r.Use(middleware.Recoverer)
|
||||||
r.Use(middleware.Timeout(60 * time.Second))
|
r.Use(middleware.Timeout(60 * time.Second))
|
||||||
|
|
||||||
|
// Load endpoint config
|
||||||
|
cfg := config.LoadEndpointConfig()
|
||||||
|
guards := NewEndpointGuards(cfg)
|
||||||
|
|
||||||
// Create handlers
|
// Create handlers
|
||||||
h := NewHandlers(svc)
|
h := NewHandlers(svc)
|
||||||
|
|
||||||
|
|
@ -26,10 +31,10 @@ func NewServer(svc *service.MergeService) http.Handler {
|
||||||
r.Get("/health", h.HandleHealth)
|
r.Get("/health", h.HandleHealth)
|
||||||
r.Get("/openapi.json", h.HandleOpenAPISpec)
|
r.Get("/openapi.json", h.HandleOpenAPISpec)
|
||||||
r.Get("/docs", h.HandleSwaggerUI)
|
r.Get("/docs", h.HandleSwaggerUI)
|
||||||
r.Post("/render/glb", h.HandleGLB)
|
r.With(guards["glb"]).Post("/render/glb", h.HandleGLB)
|
||||||
r.Post("/render/png", h.HandlePNG)
|
r.With(guards["png"]).Post("/render/png", h.HandlePNG)
|
||||||
r.Post("/render/gif", h.HandleGIF)
|
r.With(guards["gif"]).Post("/render/gif", h.HandleGIF)
|
||||||
r.Post("/render/mp4", h.HandleMP4)
|
r.With(guards["mp4"]).Post("/render/mp4", h.HandleMP4)
|
||||||
|
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
|
||||||
31
internal/config/config.go
Normal file
31
internal/config/config.go
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EndpointConfig holds enable/disable flags for render endpoints
|
||||||
|
type EndpointConfig struct {
|
||||||
|
GLBEnabled bool
|
||||||
|
PNGEnabled bool
|
||||||
|
GIFEnabled bool
|
||||||
|
MP4Enabled bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadEndpointConfig reads endpoint configuration from environment variables.
|
||||||
|
// All endpoints are enabled by default.
|
||||||
|
// Set BLOCKY_DISABLE_GLB=true, BLOCKY_DISABLE_PNG=true, etc. to disable.
|
||||||
|
func LoadEndpointConfig() *EndpointConfig {
|
||||||
|
return &EndpointConfig{
|
||||||
|
GLBEnabled: !isDisabled("BLOCKY_DISABLE_GLB"),
|
||||||
|
PNGEnabled: !isDisabled("BLOCKY_DISABLE_PNG"),
|
||||||
|
GIFEnabled: !isDisabled("BLOCKY_DISABLE_GIF"),
|
||||||
|
MP4Enabled: !isDisabled("BLOCKY_DISABLE_MP4"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func isDisabled(envVar string) bool {
|
||||||
|
val := strings.ToLower(os.Getenv(envVar))
|
||||||
|
return val == "true" || val == "1" || val == "yes"
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue