server.cjs 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. #!/usr/bin/env node
  2. /* eslint-disable compat/compat */
  3. import http from 'node:http'
  4. import qs from 'node:querystring'
  5. import he from 'he'
  6. const e = he.encode
  7. /**
  8. * A very haxxor server that outputs some of the data it receives in a POST form parameter.
  9. */
  10. const server = http.createServer(onrequest)
  11. server.listen(9967)
  12. function onrequest (req, res) {
  13. if (req.url !== '/test') {
  14. res.writeHead(404, { 'content-type': 'text/html' })
  15. res.end('404')
  16. return
  17. }
  18. function onbody (body) {
  19. const fields = qs.parse(body)
  20. const result = JSON.parse(fields.uppyResult)
  21. const assemblies = result[0].transloadit
  22. res.setHeader('content-type', 'text/html')
  23. res.write(Header())
  24. res.write(FormFields(fields))
  25. assemblies.forEach((assembly) => {
  26. res.write(AssemblyResult(assembly))
  27. })
  28. res.end(Footer())
  29. }
  30. {
  31. let body = ''
  32. req.on('data', (chunk) => { body += chunk })
  33. req.on('end', () => {
  34. onbody(body)
  35. })
  36. }
  37. }
  38. function Header () {
  39. return `
  40. <!DOCTYPE html>
  41. <html>
  42. <head>
  43. <style>
  44. body { background: #f1f1f1; }
  45. main {
  46. padding: 20px;
  47. font: 12pt sans-serif;
  48. background: white;
  49. width: 800px;
  50. margin: auto;
  51. }
  52. </style>
  53. </head>
  54. <body>
  55. <main>
  56. `
  57. }
  58. function Footer () {
  59. return `
  60. </main>
  61. </body>
  62. </html>
  63. `
  64. }
  65. function FormFields (fields) {
  66. return `
  67. <h1>Form Fields</h1>
  68. <dl>
  69. ${Object.entries(fields).map(Field).join('\n')}
  70. </dl>
  71. `
  72. function Field ([name, value]) {
  73. if (name === 'transloadit') return ''
  74. let isValueJSON = false
  75. if (value.startsWith('{') || value.startsWith('[')) {
  76. try {
  77. value = JSON.stringify(
  78. JSON.parse(value),
  79. null,
  80. 2
  81. )
  82. isValueJSON = true
  83. } catch {
  84. // Nothing
  85. }
  86. }
  87. const prettyValue = isValueJSON ? `
  88. <details open>
  89. <code>
  90. <pre style="max-width: 100%; max-height: 400px; white-space: pre-wrap; overflow: auto;">${e(value)}</pre>
  91. </code>
  92. </details>
  93. ` : e(value)
  94. return `
  95. <dt>${e(name)}</dt>
  96. <dd>
  97. ${prettyValue}
  98. </dd>
  99. `
  100. }
  101. }
  102. function AssemblyResult (assembly) {
  103. return `
  104. <h1>${e(assembly.assembly_id)} (${e(assembly.ok)})</h1>
  105. ${UploadsList(assembly.uploads)}
  106. ${ResultsList(assembly.results)}
  107. `
  108. }
  109. function UploadsList (uploads) {
  110. return `
  111. <ul>
  112. ${uploads.map(Upload).join('\n')}
  113. </ul>
  114. `
  115. function Upload (upload) {
  116. return `<li>${e(upload.name)}</li>`
  117. }
  118. }
  119. function ResultsList (results) {
  120. return Object.keys(results)
  121. .map(ResultsSection)
  122. .join('\n')
  123. function ResultsSection (stepName) {
  124. return `
  125. <h2>${e(stepName)}</h2>
  126. <ul>
  127. ${results[stepName].map(Result).join('\n')}
  128. </ul>
  129. `
  130. }
  131. function Result (result) {
  132. return `<li>${e(result.name)} <a href="${result.ssl_url}" target="_blank">View</a></li>`
  133. }
  134. }