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:
devilreef 2026-01-23 01:36:43 +06:00
parent ce511e1a85
commit f8947fdcc4
5 changed files with 110 additions and 7 deletions

View file

@ -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
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
@ -49,6 +49,17 @@ Server requires these directories at runtime (relative to working directory):
- `assets/` - Character models (.blockymodel), textures
- `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
| 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/png` | POST | Character JSON + options → PNG image |
| `/render/gif` | POST | Character JSON + options → Animated GIF |
| `/render/mp4` | POST | Character JSON + options → MP4 video (requires FFmpeg) |
| `/docs` | GET | Swagger UI |
| `/openapi.json` | GET | OpenAPI spec |
| `/health` | GET | Health check |

View file

@ -4,7 +4,7 @@
> Not affiliated with Hypixel Studios.
> 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!
@ -14,6 +14,7 @@ Built on top of [blockymodel-merger](https://github.com/hytale-tools/blockymodel
- Export as GLB (glTF binary)
- Render to PNG with configurable rotation and background
- Render to animated rotating GIF
- Render to MP4 video (requires FFmpeg)
- Swagger UI documentation
## Requirements
@ -69,6 +70,24 @@ go build -o blockyserver.exe .
./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
### Using Docker Compose (recommended)
@ -99,6 +118,7 @@ docker run -d -p 8080:8080 \
| `/render/glb` | POST | Returns GLB binary |
| `/render/png` | POST | Returns PNG image |
| `/render/gif` | POST | Returns animated GIF |
| `/render/mp4` | POST | Returns MP4 video |
| `/docs` | GET | Swagger UI |
| `/openapi.json` | GET | OpenAPI specification |
| `/health` | GET | Health check |

View 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"),
}
}

View file

@ -4,6 +4,7 @@ import (
"net/http"
"time"
"blockyserver/internal/config"
"blockyserver/internal/service"
"github.com/go-chi/chi/v5"
@ -19,6 +20,10 @@ func NewServer(svc *service.MergeService) http.Handler {
r.Use(middleware.Recoverer)
r.Use(middleware.Timeout(60 * time.Second))
// Load endpoint config
cfg := config.LoadEndpointConfig()
guards := NewEndpointGuards(cfg)
// Create handlers
h := NewHandlers(svc)
@ -26,10 +31,10 @@ func NewServer(svc *service.MergeService) http.Handler {
r.Get("/health", h.HandleHealth)
r.Get("/openapi.json", h.HandleOpenAPISpec)
r.Get("/docs", h.HandleSwaggerUI)
r.Post("/render/glb", h.HandleGLB)
r.Post("/render/png", h.HandlePNG)
r.Post("/render/gif", h.HandleGIF)
r.Post("/render/mp4", h.HandleMP4)
r.With(guards["glb"]).Post("/render/glb", h.HandleGLB)
r.With(guards["png"]).Post("/render/png", h.HandlePNG)
r.With(guards["gif"]).Post("/render/gif", h.HandleGIF)
r.With(guards["mp4"]).Post("/render/mp4", h.HandleMP4)
return r
}

31
internal/config/config.go Normal file
View 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"
}