Skip to content

Commit f8947fd

Browse files
committed
feat: add env vars to disable render endpoints
BLOCKY_DISABLE_GLB/PNG/GIF/MP4 return 403 when set to true
1 parent ce511e1 commit f8947fd

5 files changed

Lines changed: 110 additions & 7 deletions

File tree

CLAUDE.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ BlockyServer is an HTTP API for rendering Hytale character models. It wraps the
2525
```
2626
HTTP Request → api.Handlers → service.MergeService → blockymodel-merger pkg
2727
28-
render.RenderPNG/GIF (for image endpoints)
28+
render.RenderPNG/GIF/MP4 (for image/video endpoints)
2929
30-
HTTP Response (GLB/PNG/GIF)
30+
HTTP Response (GLB/PNG/GIF/MP4)
3131
```
3232

3333
### Package Structure
@@ -49,13 +49,25 @@ Server requires these directories at runtime (relative to working directory):
4949
- `assets/` - Character models (.blockymodel), textures
5050
- `data/` - JSON registry files (accessories, colors, gradients)
5151

52+
### Environment Variables
53+
54+
| Variable | Default | Description |
55+
|----------|---------|-------------|
56+
| `BLOCKY_DISABLE_GLB` | `false` | Disable `/render/glb` endpoint (returns 403) |
57+
| `BLOCKY_DISABLE_PNG` | `false` | Disable `/render/png` endpoint (returns 403) |
58+
| `BLOCKY_DISABLE_GIF` | `false` | Disable `/render/gif` endpoint (returns 403) |
59+
| `BLOCKY_DISABLE_MP4` | `false` | Disable `/render/mp4` endpoint (returns 403) |
60+
61+
Set to `true`, `1`, or `yes` to disable an endpoint.
62+
5263
### API Endpoints
5364

5465
| Endpoint | Method | Description |
5566
|----------|--------|-------------|
5667
| `/render/glb` | POST | Character JSON → GLB binary |
5768
| `/render/png` | POST | Character JSON + options → PNG image |
5869
| `/render/gif` | POST | Character JSON + options → Animated GIF |
70+
| `/render/mp4` | POST | Character JSON + options → MP4 video (requires FFmpeg) |
5971
| `/docs` | GET | Swagger UI |
6072
| `/openapi.json` | GET | OpenAPI spec |
6173
| `/health` | GET | Health check |

README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
> Not affiliated with Hypixel Studios.
55
> All trademarks and assets are property of their respective owners.
66
7-
HTTP API for rendering Hytale character models as GLB, PNG, or animated GIF.
7+
HTTP API for rendering Hytale character models as GLB, PNG, animated GIF, or MP4 video.
88

99
Built on top of [blockymodel-merger](https://github.com/hytale-tools/blockymodel-merger) by [JackGamesFTW](https://github.com/JackGamesFTW), special thanks to him!
1010

@@ -14,6 +14,7 @@ Built on top of [blockymodel-merger](https://github.com/hytale-tools/blockymodel
1414
- Export as GLB (glTF binary)
1515
- Render to PNG with configurable rotation and background
1616
- Render to animated rotating GIF
17+
- Render to MP4 video (requires FFmpeg)
1718
- Swagger UI documentation
1819

1920
## Requirements
@@ -69,6 +70,24 @@ go build -o blockyserver.exe .
6970
./blockyserver.exe -port 3000
7071
```
7172

73+
## Configuration
74+
75+
### Environment Variables
76+
77+
| Variable | Default | Description |
78+
|----------|---------|-------------|
79+
| `BLOCKY_DISABLE_GLB` | `false` | Disable `/render/glb` endpoint |
80+
| `BLOCKY_DISABLE_PNG` | `false` | Disable `/render/png` endpoint |
81+
| `BLOCKY_DISABLE_GIF` | `false` | Disable `/render/gif` endpoint |
82+
| `BLOCKY_DISABLE_MP4` | `false` | Disable `/render/mp4` endpoint |
83+
84+
Set to `true`, `1`, or `yes` to disable. Disabled endpoints return `403 Forbidden`.
85+
86+
```bash
87+
# Example: disable GIF and MP4 endpoints
88+
BLOCKY_DISABLE_GIF=true BLOCKY_DISABLE_MP4=true ./blockyserver.exe
89+
```
90+
7291
## Docker
7392

7493
### Using Docker Compose (recommended)
@@ -99,6 +118,7 @@ docker run -d -p 8080:8080 \
99118
| `/render/glb` | POST | Returns GLB binary |
100119
| `/render/png` | POST | Returns PNG image |
101120
| `/render/gif` | POST | Returns animated GIF |
121+
| `/render/mp4` | POST | Returns MP4 video |
102122
| `/docs` | GET | Swagger UI |
103123
| `/openapi.json` | GET | OpenAPI specification |
104124
| `/health` | GET | Health check |

internal/api/middleware.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package api
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
7+
"blockyserver/internal/config"
8+
)
9+
10+
// EndpointGuard creates middleware that returns 403 if endpoint is disabled
11+
func EndpointGuard(enabled bool, endpointName string) func(http.Handler) http.Handler {
12+
return func(next http.Handler) http.Handler {
13+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
14+
if !enabled {
15+
w.Header().Set("Content-Type", "application/json")
16+
w.WriteHeader(http.StatusForbidden)
17+
json.NewEncoder(w).Encode(ErrorResponse{
18+
Error: endpointName + " endpoint is disabled",
19+
})
20+
return
21+
}
22+
next.ServeHTTP(w, r)
23+
})
24+
}
25+
}
26+
27+
// NewEndpointGuards creates guards for all render endpoints based on config
28+
func NewEndpointGuards(cfg *config.EndpointConfig) map[string]func(http.Handler) http.Handler {
29+
return map[string]func(http.Handler) http.Handler{
30+
"glb": EndpointGuard(cfg.GLBEnabled, "/render/glb"),
31+
"png": EndpointGuard(cfg.PNGEnabled, "/render/png"),
32+
"gif": EndpointGuard(cfg.GIFEnabled, "/render/gif"),
33+
"mp4": EndpointGuard(cfg.MP4Enabled, "/render/mp4"),
34+
}
35+
}

internal/api/server.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"net/http"
55
"time"
66

7+
"blockyserver/internal/config"
78
"blockyserver/internal/service"
89

910
"github.com/go-chi/chi/v5"
@@ -19,17 +20,21 @@ func NewServer(svc *service.MergeService) http.Handler {
1920
r.Use(middleware.Recoverer)
2021
r.Use(middleware.Timeout(60 * time.Second))
2122

23+
// Load endpoint config
24+
cfg := config.LoadEndpointConfig()
25+
guards := NewEndpointGuards(cfg)
26+
2227
// Create handlers
2328
h := NewHandlers(svc)
2429

2530
// Routes
2631
r.Get("/health", h.HandleHealth)
2732
r.Get("/openapi.json", h.HandleOpenAPISpec)
2833
r.Get("/docs", h.HandleSwaggerUI)
29-
r.Post("/render/glb", h.HandleGLB)
30-
r.Post("/render/png", h.HandlePNG)
31-
r.Post("/render/gif", h.HandleGIF)
32-
r.Post("/render/mp4", h.HandleMP4)
34+
r.With(guards["glb"]).Post("/render/glb", h.HandleGLB)
35+
r.With(guards["png"]).Post("/render/png", h.HandlePNG)
36+
r.With(guards["gif"]).Post("/render/gif", h.HandleGIF)
37+
r.With(guards["mp4"]).Post("/render/mp4", h.HandleMP4)
3338

3439
return r
3540
}

internal/config/config.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package config
2+
3+
import (
4+
"os"
5+
"strings"
6+
)
7+
8+
// EndpointConfig holds enable/disable flags for render endpoints
9+
type EndpointConfig struct {
10+
GLBEnabled bool
11+
PNGEnabled bool
12+
GIFEnabled bool
13+
MP4Enabled bool
14+
}
15+
16+
// LoadEndpointConfig reads endpoint configuration from environment variables.
17+
// All endpoints are enabled by default.
18+
// Set BLOCKY_DISABLE_GLB=true, BLOCKY_DISABLE_PNG=true, etc. to disable.
19+
func LoadEndpointConfig() *EndpointConfig {
20+
return &EndpointConfig{
21+
GLBEnabled: !isDisabled("BLOCKY_DISABLE_GLB"),
22+
PNGEnabled: !isDisabled("BLOCKY_DISABLE_PNG"),
23+
GIFEnabled: !isDisabled("BLOCKY_DISABLE_GIF"),
24+
MP4Enabled: !isDisabled("BLOCKY_DISABLE_MP4"),
25+
}
26+
}
27+
28+
func isDisabled(envVar string) bool {
29+
val := strings.ToLower(os.Getenv(envVar))
30+
return val == "true" || val == "1" || val == "yes"
31+
}

0 commit comments

Comments
 (0)