@rip-lang/api 0.7.2 → 0.7.4
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.
- package/api.rip +3 -3
- package/middleware.rip +72 -1
- package/package.json +1 -1
package/api.rip
CHANGED
|
@@ -90,18 +90,18 @@ createContext = (req, params = {}) ->
|
|
|
90
90
|
|
|
91
91
|
ctx =
|
|
92
92
|
json: (data, status = 200, headers = {}) ->
|
|
93
|
-
for k, v of headers then out.set(k, v)
|
|
94
93
|
out.set 'Content-Type', 'application/json'
|
|
94
|
+
for k, v of headers then out.set(k, v)
|
|
95
95
|
new Response JSON.stringify(data), { status, headers: out }
|
|
96
96
|
|
|
97
97
|
text: (str, status = 200, headers = {}) ->
|
|
98
|
-
for k, v of headers then out.set(k, v)
|
|
99
98
|
out.set 'Content-Type', 'text/plain; charset=UTF-8'
|
|
99
|
+
for k, v of headers then out.set(k, v)
|
|
100
100
|
new Response str, { status, headers: out }
|
|
101
101
|
|
|
102
102
|
html: (str, status = 200, headers = {}) ->
|
|
103
|
-
for k, v of headers then out.set(k, v)
|
|
104
103
|
out.set 'Content-Type', 'text/html; charset=UTF-8'
|
|
104
|
+
for k, v of headers then out.set(k, v)
|
|
105
105
|
new Response str, { status, headers: out }
|
|
106
106
|
|
|
107
107
|
redirect: (location, status = 302) ->
|
package/middleware.rip
CHANGED
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
# ==============================================================================
|
|
4
4
|
#
|
|
5
5
|
# Usage:
|
|
6
|
-
# import { cors, logger, compress, sessions } from '@rip-lang/api/middleware'
|
|
6
|
+
# import { cors, logger, compress, sessions, prettyJson } from '@rip-lang/api/middleware'
|
|
7
7
|
# import { session } from '@rip-lang/api'
|
|
8
8
|
#
|
|
9
9
|
# use logger()
|
|
10
10
|
# use cors origin: 'https://myapp.com'
|
|
11
11
|
# use compress()
|
|
12
12
|
# use sessions()
|
|
13
|
+
# use prettyJson # Pretty JSON for iOS mobile browsers
|
|
13
14
|
#
|
|
14
15
|
# before ->
|
|
15
16
|
# session.userId = 123 # Works anywhere via AsyncLocalStorage
|
|
@@ -390,3 +391,73 @@ export bodyLimit = (opts = {}) ->
|
|
|
390
391
|
return c.json { error: message }, 413
|
|
391
392
|
|
|
392
393
|
await next()
|
|
394
|
+
|
|
395
|
+
# ==============================================================================
|
|
396
|
+
# prettyJson — Pretty JSON for iOS Mobile Browsers
|
|
397
|
+
# ==============================================================================
|
|
398
|
+
#
|
|
399
|
+
# Renders JSON as syntax-highlighted HTML for iOS mobile browsers.
|
|
400
|
+
# Solves the iOS Safari/Chrome "download" footer issue when viewing JSON.
|
|
401
|
+
#
|
|
402
|
+
# Usage:
|
|
403
|
+
# use prettyJson
|
|
404
|
+
#
|
|
405
|
+
# Only activates when:
|
|
406
|
+
# 1. Request is from iOS (iPhone/iPad)
|
|
407
|
+
# 2. Browser is directly viewing (Accept: text/html, not API call)
|
|
408
|
+
#
|
|
409
|
+
|
|
410
|
+
export prettyJson = (c, next) ->
|
|
411
|
+
originalJson = c.json.bind(c)
|
|
412
|
+
|
|
413
|
+
c.json = (data, status = 200, headers = {}) ->
|
|
414
|
+
if _shouldRenderHtmlJson(c.req.raw)
|
|
415
|
+
return _renderHtmlJson(data, status)
|
|
416
|
+
originalJson(data, status, headers)
|
|
417
|
+
|
|
418
|
+
next!()
|
|
419
|
+
|
|
420
|
+
_shouldRenderHtmlJson = (req) ->
|
|
421
|
+
ua = req.headers.get('user-agent') or ''
|
|
422
|
+
accept = req.headers.get('accept') or ''
|
|
423
|
+
dest = req.headers.get('sec-fetch-dest') or ''
|
|
424
|
+
|
|
425
|
+
isIOS = /iPhone|iPad|iPod/i.test(ua)
|
|
426
|
+
acceptsHtml = accept.includes('text/html')
|
|
427
|
+
isNavigation = dest is 'document' or (acceptsHtml and not accept.startsWith('application/json'))
|
|
428
|
+
|
|
429
|
+
isIOS and isNavigation
|
|
430
|
+
|
|
431
|
+
_renderHtmlJson = (data, status) ->
|
|
432
|
+
json = JSON.stringify(data, null, 2)
|
|
433
|
+
|
|
434
|
+
# HTML escape then syntax highlight
|
|
435
|
+
escaped = json
|
|
436
|
+
.replace(/&/g, '&')
|
|
437
|
+
.replace(/</g, '<')
|
|
438
|
+
.replace(/>/g, '>')
|
|
439
|
+
|
|
440
|
+
highlighted = escaped
|
|
441
|
+
.replace(/"([^"]+)":/g, '<span class="k">"$1"</span>:')
|
|
442
|
+
.replace(/: "([^"]*)"/g, ': <span class="s">"$1"</span>')
|
|
443
|
+
.replace(/: (-?\d+\.?\d*)/g, ': <span class="n">$1</span>')
|
|
444
|
+
.replace(/: (true|false)/g, ': <span class="b">$1</span>')
|
|
445
|
+
.replace(/: (null)/g, ': <span class="b">$1</span>')
|
|
446
|
+
|
|
447
|
+
html = """<!DOCTYPE html>
|
|
448
|
+
<html><head>
|
|
449
|
+
<meta charset="utf-8">
|
|
450
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
451
|
+
<title>JSON</title>
|
|
452
|
+
<style>
|
|
453
|
+
*{box-sizing:border-box}
|
|
454
|
+
body{font:14px/1.5 ui-monospace,monospace;background:#1a1a2e;color:#e0e0e0;margin:0;padding:16px}
|
|
455
|
+
pre{margin:0;white-space:pre-wrap;word-break:break-word}
|
|
456
|
+
.k{color:#82aaff}.s{color:#c3e88d}.n{color:#f78c6c}.b{color:#89ddff}
|
|
457
|
+
</style>
|
|
458
|
+
</head><body><pre>#{highlighted}</pre></body></html>"""
|
|
459
|
+
|
|
460
|
+
new Response html, {
|
|
461
|
+
status: status
|
|
462
|
+
headers: new Headers({ 'content-type': 'text/html; charset=utf-8' })
|
|
463
|
+
}
|