@rip-lang/server 1.3.126 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/{docs/READ_VALIDATORS.md → API.md} +41 -119
  2. package/CONFIG.md +408 -0
  3. package/README.md +246 -1109
  4. package/acme/crypto.rip +0 -2
  5. package/browse.rip +62 -0
  6. package/control/cli.rip +89 -34
  7. package/control/lifecycle.rip +67 -1
  8. package/control/manager.rip +250 -0
  9. package/control/mdns.rip +3 -0
  10. package/middleware.rip +1 -1
  11. package/package.json +14 -11
  12. package/server.rip +189 -673
  13. package/serving/config.rip +766 -0
  14. package/{edge → serving}/forwarding.rip +2 -2
  15. package/serving/logging.rip +101 -0
  16. package/{edge → serving}/metrics.rip +29 -1
  17. package/serving/proxy.rip +99 -0
  18. package/{edge → serving}/queue.rip +1 -1
  19. package/{edge → serving}/ratelimit.rip +1 -1
  20. package/{edge → serving}/realtime.rip +71 -2
  21. package/{edge → serving}/registry.rip +1 -1
  22. package/{edge → serving}/router.rip +3 -3
  23. package/{edge → serving}/runtime.rip +18 -16
  24. package/{edge → serving}/security.rip +1 -1
  25. package/serving/static.rip +393 -0
  26. package/{edge → serving}/tls.rip +3 -7
  27. package/{edge → serving}/upstream.rip +4 -4
  28. package/{edge → serving}/verify.rip +16 -16
  29. package/streams/{tls_clienthello.rip → clienthello.rip} +1 -1
  30. package/streams/config.rip +8 -8
  31. package/streams/index.rip +5 -5
  32. package/streams/router.rip +2 -2
  33. package/tests/acme.rip +1 -1
  34. package/tests/config.rip +215 -0
  35. package/tests/control.rip +1 -1
  36. package/tests/{runtime_entrypoints.rip → entrypoints.rip} +11 -7
  37. package/tests/extracted.rip +118 -0
  38. package/tests/helpers.rip +4 -4
  39. package/tests/metrics.rip +3 -3
  40. package/tests/proxy.rip +9 -8
  41. package/tests/read.rip +1 -1
  42. package/tests/realtime.rip +3 -3
  43. package/tests/registry.rip +4 -4
  44. package/tests/router.rip +27 -27
  45. package/tests/runner.rip +70 -0
  46. package/tests/security.rip +4 -4
  47. package/tests/servers.rip +102 -136
  48. package/tests/static.rip +2 -2
  49. package/tests/streams_clienthello.rip +2 -2
  50. package/tests/streams_index.rip +4 -4
  51. package/tests/streams_pipe.rip +1 -1
  52. package/tests/streams_router.rip +10 -10
  53. package/tests/streams_runtime.rip +4 -4
  54. package/tests/streams_upstream.rip +1 -1
  55. package/tests/upstream.rip +2 -2
  56. package/tests/verify.rip +18 -18
  57. package/tests/watchers.rip +4 -4
  58. package/default.rip +0 -435
  59. package/docs/edge/CONFIG_LIFECYCLE.md +0 -111
  60. package/docs/edge/CONTRACTS.md +0 -137
  61. package/docs/edge/EDGEFILE_CONTRACT.md +0 -282
  62. package/docs/edge/M0B_REVIEW_NOTES.md +0 -102
  63. package/docs/edge/SCHEDULER.md +0 -46
  64. package/docs/logo.png +0 -0
  65. package/docs/logo.svg +0 -13
  66. package/docs/social.png +0 -0
  67. package/edge/config.rip +0 -607
  68. package/edge/static.rip +0 -69
  69. package/tests/edgefile.rip +0 -165
@@ -1,10 +1,10 @@
1
1
  # ==============================================================================
2
- # edge/forwarding.rip — helpers, responses, forwarding, and proxy
2
+ # serving/forwarding.rip — helpers, responses, forwarding, and proxy
3
3
  # ==============================================================================
4
4
 
5
5
  import { randomBytes } from 'node:crypto'
6
6
 
7
- # --- Edge utilities ---
7
+ # --- Serving utilities ---
8
8
 
9
9
  export generateRequestId = ->
10
10
  "req-#{randomBytes(6).toString('hex')}"
@@ -0,0 +1,101 @@
1
+ # ==============================================================================
2
+ # serving/logging.rip — access logging, formatting, and server utilities
3
+ # ==============================================================================
4
+
5
+ export nowMs = -> Date.now()
6
+
7
+ _envOverride = null
8
+ _debugMode = false
9
+
10
+ export isDev = ->
11
+ env = (_envOverride or process.env.NODE_ENV or '').toLowerCase()
12
+ env in ['development', 'dev', '']
13
+
14
+ export isDebug = -> _debugMode or process.env.RIP_DEBUG?
15
+
16
+ export applyFlagSideEffects = (flags) ->
17
+ _envOverride = flags.envOverride if flags.envOverride
18
+ _debugMode = flags.debug is true
19
+ process.env.RIP_DEBUG = '1' if _debugMode
20
+
21
+ export formatTimestamp = ->
22
+ now = new Date()
23
+ pad = (n, w = 2) -> String(n).padStart(w, '0')
24
+ timestamp = "#{now.getFullYear()}-#{pad(now.getMonth() + 1)}-#{pad(now.getDate())} #{pad(now.getHours())}:#{pad(now.getMinutes())}:#{pad(now.getSeconds())}.#{String(now.getMilliseconds()).padStart(3, '0')}"
25
+ tzMin = now.getTimezoneOffset()
26
+ tzSign = if tzMin <= 0 then '+' else '-'
27
+ tzAbs = Math.abs(tzMin)
28
+ timezone = "#{tzSign}#{String(Math.floor(tzAbs / 60)).padStart(2, '0')}#{String(tzAbs % 60).padStart(2, '0')}"
29
+ { timestamp, timezone }
30
+
31
+ export scale = (value, unit, pad = true) ->
32
+ if value > 0 and Number.isFinite(value)
33
+ span = ['T', 'G', 'M', 'k', (if pad then ' ' else ''), 'm', 'µ', 'n', 'p']
34
+ base = 4
35
+ minSlot = 0
36
+ maxSlot = span.length - 1
37
+ slot = base
38
+
39
+ while value < 0.995 and slot <= maxSlot
40
+ value *= 1000
41
+ slot++
42
+ while value >= 999.5 and slot >= minSlot
43
+ value /= 1000
44
+ slot--
45
+
46
+ if slot >= minSlot and slot <= maxSlot
47
+ tens = Math.round(value * 10) / 10
48
+ if tens >= 99.5
49
+ nums = Math.round(value).toString()
50
+ else if tens >= 10
51
+ nums = Math.round(value).toString()
52
+ else
53
+ nums = tens.toFixed(1)
54
+ nums = nums.padStart(3, ' ') if pad
55
+ return "#{nums}#{span[slot]}#{unit}"
56
+
57
+ return (if pad then ' 0 ' else '0') + unit if value is 0
58
+ '???' + (if pad then ' ' else '') + unit
59
+
60
+ export logAccessJson = (app, req, res, totalSeconds, workerSeconds) ->
61
+ url = new URL(req.url)
62
+ len = res.headers.get('content-length')
63
+ type = (res.headers.get('content-type') or '').split(';')[0] or undefined
64
+ p JSON.stringify
65
+ t: new Date().toISOString()
66
+ app: app
67
+ method: req.method or 'GET'
68
+ path: url.pathname
69
+ status: res.status
70
+ totalSeconds: totalSeconds
71
+ workerSeconds: workerSeconds
72
+ type: type
73
+ length: if len then Number(len) else undefined
74
+
75
+ typeAbbrev =
76
+ html: 'html', css: 'css', javascript: 'js', json: 'json', plain: 'text'
77
+ png: 'png', jpeg: 'jpg', gif: 'gif', webp: 'webp', svg: 'svg'
78
+ 'svg+xml': 'svg', 'x-icon': 'ico', 'octet-stream': 'bin', 'x-rip': 'rip'
79
+
80
+ export logAccessHuman = (app, req, res, totalSeconds, workerSeconds) ->
81
+ { timestamp, timezone } = formatTimestamp()
82
+ dur = scale(totalSeconds, 's')
83
+ method = req.method or 'GET'
84
+ url = new URL(req.url)
85
+ path = url.pathname
86
+ status = res.status
87
+ bytes = Number(res.headers.get('content-length') or 0)
88
+ size = scale(bytes, 'B')
89
+ contentType = (res.headers.get('content-type') or '').split(';')[0] or ''
90
+ sub = if contentType.includes('/') then contentType.split('/')[1] else contentType
91
+ type = (typeAbbrev[sub] or sub or '').padEnd(4)
92
+ p "#{timestamp} #{timezone} #{dur} │ #{status} #{type} #{size} │ #{method} #{path}"
93
+
94
+ INTERNAL_HEADERS = new Set(['rip-worker-busy', 'rip-worker-id', 'rip-no-log'])
95
+
96
+ export stripInternalHeaders = (h) ->
97
+ out = new Headers()
98
+ for [k, v] as h.entries()
99
+ continue if INTERNAL_HEADERS.has(k.toLowerCase())
100
+ out.append(k, v)
101
+ out
@@ -1,5 +1,5 @@
1
1
  # ==============================================================================
2
- # edge/metrics.rip — lightweight in-process metrics collector
2
+ # serving/metrics.rip — lightweight in-process metrics collector
3
3
  # ==============================================================================
4
4
 
5
5
  LATENCY_WINDOW = 1000
@@ -101,3 +101,31 @@ export createMetrics = ->
101
101
  latency: m.percentiles()
102
102
 
103
103
  m
104
+
105
+ export buildDiagnosticsBody = (state) ->
106
+ snap = state.metrics.snapshot(state.startedAt, state.appRegistry, state.servingRuntime.upstreamPool)
107
+ JSON.stringify
108
+ status: if snap.gauges.workersActive > 0 then 'healthy' else 'degraded'
109
+ version: { server: state.serverVersion, rip: state.ripVersion }
110
+ uptime: snap.uptime
111
+ apps: snap.apps
112
+ proxies: snap.upstreams
113
+ metrics:
114
+ requests: snap.counters.requests
115
+ responses: snap.counters.responses
116
+ latency: snap.latency
117
+ queue: snap.counters.queue
118
+ workers: snap.counters.workers
119
+ acme: snap.counters.acme
120
+ websocket: snap.counters.websocket
121
+ gauges: snap.gauges
122
+ realtime: state.realtimeStats
123
+ hosts: state.hosts
124
+ streams: state.streamDiagnostics
125
+ config: Object.assign({}, state.configInfo,
126
+ multiplexer: state.multiplexer
127
+ activeRuntime: state.activeRuntime
128
+ retiredRuntimes: state.retiredRuntimes
129
+ activeStreamRuntime: state.activeStreamRuntime
130
+ retiredStreamRuntimes: state.retiredStreamRuntimes
131
+ )
@@ -0,0 +1,99 @@
1
+ # ==============================================================================
2
+ # serving/proxy.rip — HTTP and WebSocket proxy to upstream backends
3
+ # ==============================================================================
4
+
5
+ import { getUpstream, selectTarget, markTargetBusy, releaseTarget, shouldRetry, computeRetryDelayMs } from './upstream.rip'
6
+ import { serviceUnavailableResponse, buildUpstreamResponse, proxyToUpstream } from './forwarding.rip'
7
+ import { isDebug, stripInternalHeaders } from './logging.rip'
8
+ import { toUpstreamWsUrl } from './runtime.rip'
9
+
10
+ export proxyRouteToUpstream = (req, route, requestId, clientIp, runtime, metrics, flags, addSecurityHeaders, logAccess) ->
11
+ upstream = getUpstream(runtime.upstreamPool, route.proxy)
12
+ unless upstream
13
+ console.error "[proxy] no proxy '#{route.proxy}'" if isDebug()
14
+ return serviceUnavailableResponse()
15
+
16
+ attempt = 1
17
+ start = performance.now()
18
+
19
+ while attempt <= upstream.retry.attempts
20
+ target = selectTarget(upstream, runtime.upstreamPool.nowFn)
21
+ unless target
22
+ console.error "[proxy] no healthy target for '#{route.proxy}'" if isDebug()
23
+ return serviceUnavailableResponse()
24
+
25
+ markTargetBusy(target)
26
+ workerSeconds = 0
27
+ res = null
28
+ success = false
29
+
30
+ try
31
+ t0 = performance.now()
32
+ timeoutMs = route.timeouts?.readMs or upstream.timeouts?.readMs or flags.readTimeoutMs
33
+ res = proxyToUpstream!(req, target.url,
34
+ timeoutMs: timeoutMs
35
+ clientIp: clientIp
36
+ )
37
+ workerSeconds = (performance.now() - t0) / 1000
38
+ success = res.status < 500
39
+ console.error "[proxy] #{route.proxy} -> #{target.url} status=#{res.status} attempt=#{attempt}" if isDebug()
40
+ catch err
41
+ console.error "[proxy] #{route.proxy} error: #{err.message or err}" if isDebug()
42
+ res = serviceUnavailableResponse()
43
+ finally
44
+ releaseTarget(target, workerSeconds * 1000, success, runtime.upstreamPool)
45
+
46
+ if res and shouldRetry(upstream.retry, req.method, res.status, false) and attempt < upstream.retry.attempts
47
+ delayMs = computeRetryDelayMs(upstream.retry, attempt, runtime.upstreamPool.randomFn)
48
+ await new Promise (r) -> setTimeout(r, delayMs)
49
+ attempt++
50
+ continue
51
+
52
+ totalSeconds = (performance.now() - start) / 1000
53
+ metrics.forwarded++
54
+ metrics.recordLatency(totalSeconds)
55
+ metrics.recordStatus(res.status)
56
+ response = buildUpstreamResponse(
57
+ res,
58
+ req,
59
+ totalSeconds,
60
+ workerSeconds,
61
+ addSecurityHeaders,
62
+ logAccess,
63
+ stripInternalHeaders
64
+ )
65
+ response.headers.set('X-Request-Id', requestId) if requestId
66
+ response.headers.set('X-Rip-Route', route.id) if route.id
67
+ return response
68
+
69
+ serviceUnavailableResponse()
70
+
71
+ export upgradeProxyWebSocket = (req, bunServer, route, requestId, runtime) ->
72
+ upstream = getUpstream(runtime.upstreamPool, route.proxy)
73
+ return new Response('Service unavailable', { status: 503 }) unless upstream
74
+ target = selectTarget(upstream, runtime.upstreamPool.nowFn)
75
+ return new Response('Service unavailable', { status: 503 }) unless target
76
+
77
+ inUrl = new URL(req.url)
78
+ protocols = (req.headers.get('sec-websocket-protocol') or '')
79
+ .split(',')
80
+ .map((p) -> p.trim())
81
+ .filter(Boolean)
82
+
83
+ markTargetBusy(target)
84
+ data =
85
+ kind: 'ws-proxy'
86
+ runtime: runtime
87
+ requestId: requestId
88
+ routeId: route.id
89
+ upstreamTarget: target
90
+ upstreamUrl: toUpstreamWsUrl(target.url, inUrl.pathname, inUrl.search)
91
+ protocols: protocols
92
+ passthrough: null
93
+ released: false
94
+
95
+ if bunServer.upgrade(req, { data })
96
+ return
97
+
98
+ releaseTarget(target, 0, false, runtime.upstreamPool)
99
+ new Response('WebSocket upgrade failed', { status: 400 })
@@ -1,5 +1,5 @@
1
1
  # ==============================================================================
2
- # edge/queue.rip — scheduling, queue drain, and job processing
2
+ # serving/queue.rip — scheduling, queue drain, and job processing
3
3
  # ==============================================================================
4
4
 
5
5
  # --- Scheduler ---
@@ -1,5 +1,5 @@
1
1
  # ==============================================================================
2
- # edge/ratelimit.rip — per-IP sliding window rate limiter
2
+ # serving/ratelimit.rip — per-IP sliding window rate limiter
3
3
  # ==============================================================================
4
4
 
5
5
  DEFAULT_WINDOW_MS = 60000 # 1 minute
@@ -1,5 +1,5 @@
1
1
  # ==============================================================================
2
- # edge/realtime.rip — Bam-style WebSocket realtime hub
2
+ # serving/realtime.rip — Bam-style WebSocket realtime hub
3
3
  # ==============================================================================
4
4
  #
5
5
  # Manages WebSocket connections, group membership, and message routing.
@@ -194,7 +194,76 @@ export handlePublish = (hub, body) ->
194
194
 
195
195
  export getRealtimeStats = (hub) ->
196
196
  clients: hub.sockets.size
197
- groups: hub.members.size - hub.sockets.size # groups minus client entries
197
+ groups: hub.members.size - hub.sockets.size
198
198
  deliveries: hub.deliveries
199
199
  messages: hub.messages
200
200
  connections: hub.connections
201
+
202
+ export proxyRealtimeToWorker = (headers, frameType, body, getSocket, releaseSocket) ->
203
+ sock = getSocket()
204
+ return null unless sock
205
+ proxyHeaders = new Headers(headers)
206
+ proxyHeaders.set('Sec-WebSocket-Frame', frameType)
207
+ proxyHeaders.set('Content-Type', 'text/plain')
208
+ proxyHeaders.delete('Upgrade')
209
+ proxyHeaders.delete('Connection')
210
+ proxyHeaders.delete('Sec-WebSocket-Key')
211
+ proxyHeaders.delete('Sec-WebSocket-Version')
212
+ proxyHeaders.delete('Sec-WebSocket-Extensions')
213
+ try
214
+ res = fetch! "http://localhost/v1/realtime",
215
+ method: 'POST'
216
+ headers: proxyHeaders
217
+ body: body or ''
218
+ unix: sock.socket
219
+ decompress: false
220
+ res.text!
221
+ catch e
222
+ console.error "realtime: worker proxy failed:", e.message
223
+ null
224
+ finally
225
+ releaseSocket(sock)
226
+
227
+ export buildWebSocketHandlers = (hub, server) ->
228
+ websocket:
229
+ idleTimeout: 120
230
+ sendPings: true
231
+
232
+ open: (ws) ->
233
+ if ws.data?.kind is 'ws-proxy'
234
+ server.retainRuntimeWs(ws.data.runtime)
235
+ ws.data.passthrough = server.createWsPassthrough(ws, ws.data.upstreamUrl, ws.data.protocols or [])
236
+ return
237
+
238
+ { clientId, headers } = ws.data
239
+ addClient(hub, clientId, ws)
240
+ server.metrics.wsConnections++
241
+ server.logEvent 'ws_open', { clientId }
242
+ response = server.proxyRealtimeToWorker!(headers, 'open', '')
243
+ processResponse(hub, response, clientId) if response
244
+
245
+ message: (ws, message) ->
246
+ if ws.data?.kind is 'ws-proxy'
247
+ ws.data.passthrough?.sendToUpstream(message)
248
+ return
249
+
250
+ { clientId, headers } = ws.data
251
+ server.metrics.wsMessages++
252
+ isBinary = typeof message isnt 'string'
253
+ msg = if isBinary then Buffer.from(message) else message
254
+ frameType = if isBinary then 'binary' else 'text'
255
+ response = server.proxyRealtimeToWorker!(headers, frameType, msg)
256
+ processResponse(hub, response, clientId) if response
257
+
258
+ close: (ws) ->
259
+ if ws.data?.kind is 'ws-proxy'
260
+ ws.data.passthrough?.close()
261
+ unless ws.data.released
262
+ server.releaseProxyTarget(ws.data)
263
+ ws.data.released = true
264
+ return
265
+
266
+ { clientId, headers } = ws.data
267
+ server.logEvent 'ws_close', { clientId }
268
+ removeClient(hub, clientId)
269
+ server.proxyRealtimeToWorker!(headers, 'close', '')
@@ -1,5 +1,5 @@
1
1
  # ==============================================================================
2
- # edge/registry.rip — per-app state and multi-app registry
2
+ # serving/registry.rip — per-app state and multi-app registry
3
3
  # ==============================================================================
4
4
 
5
5
  createAppState = (appId, config) ->
@@ -1,5 +1,5 @@
1
1
  # ==============================================================================
2
- # edge/router.rip — edge route compilation and matching
2
+ # serving/router.rip — route compilation and matching
3
3
  # ==============================================================================
4
4
 
5
5
  normalizeMethods = (methods) ->
@@ -85,7 +85,7 @@ compileRoute = (route, order, inheritedHost = null) ->
85
85
  pathBase: pathBase(path)
86
86
  methods
87
87
  priority: route.priority or order
88
- upstream: route.upstream or null
88
+ proxy: route.proxy or null
89
89
  app: route.app or null
90
90
  static: route.static or null
91
91
  root: route.root or null
@@ -128,7 +128,7 @@ export matchRoute = (table, hostname, pathname, method = 'GET') ->
128
128
 
129
129
  export describeRoute = (route) ->
130
130
  return null unless route
131
- action = if route.upstream? then "proxy:#{route.upstream}"
131
+ action = if route.proxy? then "proxy:#{route.proxy}"
132
132
  else if route.app? then "app:#{route.app}"
133
133
  else if route.static? then "static"
134
134
  else if route.redirect? then "redirect"
@@ -1,19 +1,19 @@
1
1
  # ==============================================================================
2
- # edge/runtime.rip — edge runtime lifecycle helpers
2
+ # serving/runtime.rip — serving runtime lifecycle helpers
3
3
  # ==============================================================================
4
4
 
5
5
  import { createUpstreamPool } from './upstream.rip'
6
- import { compileRouteTable, describeRoute } from './router.rip'
7
- import { resolveConfigSource, loadConfig, loadEdgeConfig, summarizeConfig, formatConfigErrors, checkConfigFile } from './config.rip'
6
+ import { compileRouteTable } from './router.rip'
7
+ import { resolveConfigSource, loadConfig, summarizeConfig, formatConfigErrors, checkConfigFile } from './config.rip'
8
8
 
9
- export createEdgeRuntime = (configInfo = null, upstreamPool = null, routeTable = null) ->
9
+ export createServingRuntime = (configInfo = null, upstreamPool = null, routeTable = null) ->
10
10
  upstreamPool = upstreamPool or createUpstreamPool()
11
11
  routeTable = routeTable or compileRouteTable()
12
12
  configInfo = configInfo or {
13
13
  kind: 'none'
14
14
  path: null
15
15
  version: null
16
- counts: { apps: 0, upstreams: 0, routes: 0, sites: 0 }
16
+ counts: { apps: 0, proxies: 0, routes: 0, hosts: 0 }
17
17
  lastResult: 'none'
18
18
  loadedAt: null
19
19
  note: null
@@ -23,7 +23,7 @@ export createEdgeRuntime = (configInfo = null, upstreamPool = null, routeTable =
23
23
  activeRouteDescriptions: []
24
24
  }
25
25
  {
26
- id: "edge-#{Date.now()}-#{Math.random().toString(16).slice(2, 8)}"
26
+ id: "srv-#{Date.now()}-#{Math.random().toString(16).slice(2, 8)}"
27
27
  upstreamPool
28
28
  routeTable
29
29
  configInfo
@@ -33,6 +33,8 @@ export createEdgeRuntime = (configInfo = null, upstreamPool = null, routeTable =
33
33
  retiredAt: null
34
34
  }
35
35
 
36
+ export createEdgeRuntime = (configInfo, upstreamPool, routeTable) -> createServingRuntime(configInfo, upstreamPool, routeTable)
37
+
36
38
  export createReloadHistoryEntry = (id, source, oldVersion, newVersion, result, reason = null, code = null, details = null) ->
37
39
  id: id
38
40
  source: source
@@ -50,9 +52,9 @@ export restoreRegistrySnapshot = (registry, snapshot) ->
50
52
  registry.wildcardIndex = new Map(snapshot.wildcardIndex)
51
53
 
52
54
  export configNote = (loaded) ->
53
- return null unless loaded?.source?.kind is 'edge'
54
- if loaded.summary.counts.upstreams > 0 or loaded.summary.counts.routes > 0 or loaded.summary.counts.sites > 0
55
- 'Edgefile upstream routes, websocket routes, wildcard hosts, managed app-route expansion, and per-app server-side reload parity are live.'
55
+ return null unless loaded?.source?.kind in ['serve', 'edge']
56
+ if loaded.summary.counts.proxies > 0 or loaded.summary.counts.routes > 0 or loaded.summary.counts.hosts > 0
57
+ 'Composable host blocks, proxy routes, websocket routes, wildcard hosts, and managed app routing are live.'
56
58
  else
57
59
  null
58
60
 
@@ -62,9 +64,9 @@ export toUpstreamWsUrl = (baseUrl, pathName, search) ->
62
64
  "#{protocol}//#{origin.host}#{pathName}#{search}"
63
65
 
64
66
  export loadRuntimeConfig = (flags) ->
65
- source = resolveConfigSource(flags.appEntry, flags.edgefilePath)
67
+ source = resolveConfigSource(flags.appEntry, flags.configPath)
66
68
  return null unless source?.path
67
- normalized = if source.kind is 'edge' then loadEdgeConfig!(source.path) else loadConfig!(source.path)
69
+ normalized = loadConfig!(source.path)
68
70
  return null unless normalized
69
71
  {
70
72
  source
@@ -73,25 +75,25 @@ export loadRuntimeConfig = (flags) ->
73
75
  }
74
76
 
75
77
  export printCheckConfigResult = (loaded) ->
76
- label = if loaded.source.kind is 'edge' then 'Edgefile.rip' else 'config.rip'
78
+ label = 'serve.rip'
77
79
  p "rip-server: #{label} OK"
78
80
  p " path: #{loaded.summary.path}"
79
- p " apps: #{loaded.summary.counts.apps} upstreams: #{loaded.summary.counts.upstreams} routes: #{loaded.summary.counts.routes} sites: #{loaded.summary.counts.sites}"
81
+ p " apps: #{loaded.summary.counts.apps} proxies: #{loaded.summary.counts.proxies} hosts: #{loaded.summary.counts.hosts} routes: #{loaded.summary.counts.routes}"
80
82
  p " version: #{loaded.summary.version}" if loaded.summary.version?
81
83
  note = configNote(loaded)
82
84
  p " note: #{note}" if note
83
85
 
84
86
  export runCheckConfig = (flags) ->
85
- source = resolveConfigSource(flags.appEntry, flags.edgefilePath)
87
+ source = resolveConfigSource(flags.appEntry, flags.configPath)
86
88
  unless source?.path
87
- console.error 'rip-server: no Edgefile.rip or config.rip found to validate'
89
+ console.error 'rip-server: no serve.rip found to validate'
88
90
  exit 1
89
91
  try
90
92
  checked = checkConfigFile!(source.path)
91
93
  printCheckConfigResult({ source, normalized: checked.normalized, summary: checked.summary })
92
94
  catch e
93
95
  if e.validationErrors
94
- label = if source.kind is 'edge' then 'Edgefile.rip' else 'config.rip'
96
+ label = 'serve.rip'
95
97
  console.error formatConfigErrors(label, e.validationErrors)
96
98
  else
97
99
  console.error "rip-server: config check failed: #{e.message or e}"
@@ -1,5 +1,5 @@
1
1
  # ==============================================================================
2
- # edge/security.rip — request smuggling and validation defenses
2
+ # serving/security.rip — request smuggling and validation defenses
3
3
  # ==============================================================================
4
4
 
5
5
  MAX_URL_LENGTH = 8192