@jaredwray/mockhttp 1.9.0 → 2.1.0

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 (67) hide show
  1. package/README.md +40 -8
  2. package/dist/index.d.mts +90 -11
  3. package/dist/index.mjs +203 -240
  4. package/package.json +17 -13
  5. package/site/dist/api/index.html +17983 -0
  6. package/site/dist/api/swagger.json +5487 -0
  7. package/site/dist/changelog/index.html +784 -0
  8. package/site/dist/changelog/page/2/index.html +577 -0
  9. package/site/dist/changelog/v0-2-0/index.html +437 -0
  10. package/site/dist/changelog/v0-2-1/index.html +438 -0
  11. package/site/dist/changelog/v0-2-2/index.html +436 -0
  12. package/site/dist/changelog/v0-2-3/index.html +440 -0
  13. package/site/dist/changelog/v0-3-0/index.html +443 -0
  14. package/site/dist/changelog/v0-4-0/index.html +437 -0
  15. package/site/dist/changelog/v0-4-1/index.html +441 -0
  16. package/site/dist/changelog/v0-4-2/index.html +446 -0
  17. package/site/dist/changelog/v0-4-3/index.html +437 -0
  18. package/site/dist/changelog/v0-5-0/index.html +443 -0
  19. package/site/dist/changelog/v0-6-0/index.html +444 -0
  20. package/site/dist/changelog/v0-6-1/index.html +441 -0
  21. package/site/dist/changelog/v0-7-0/index.html +445 -0
  22. package/site/dist/changelog/v0-8-0/index.html +440 -0
  23. package/site/dist/changelog/v0-9-0/index.html +437 -0
  24. package/site/dist/changelog/v1-0-0/index.html +446 -0
  25. package/site/dist/changelog/v1-0-1/index.html +437 -0
  26. package/site/dist/changelog/v1-1-0/index.html +445 -0
  27. package/site/dist/changelog/v1-2-0/index.html +443 -0
  28. package/site/dist/changelog/v1-3-0/index.html +448 -0
  29. package/site/dist/changelog/v1-4-0/index.html +445 -0
  30. package/site/dist/changelog/v1-5-0/index.html +439 -0
  31. package/site/dist/changelog/v1-5-1/index.html +443 -0
  32. package/site/dist/changelog/v1-6-0/index.html +467 -0
  33. package/site/dist/changelog/v1-7-0/index.html +462 -0
  34. package/site/dist/changelog/v1-8-0/index.html +481 -0
  35. package/site/dist/changelog/v1-8-1/index.html +457 -0
  36. package/site/dist/changelog/v1-9-0/index.html +495 -0
  37. package/site/dist/changelog/v2-0-0/index.html +500 -0
  38. package/site/dist/changelog/v2-1-0/index.html +476 -0
  39. package/site/dist/changelog-latest.json +269 -0
  40. package/site/dist/changelog.json +399 -0
  41. package/site/dist/css/api.css +1113 -0
  42. package/site/dist/css/highlight/highlight.min.js +1433 -0
  43. package/site/dist/css/highlight/styles/base16/docula.css +123 -0
  44. package/site/dist/css/home.css +133 -0
  45. package/site/dist/css/styles.css +1227 -0
  46. package/site/dist/css/variables.css +32 -0
  47. package/site/dist/docs/bins/index.html +980 -0
  48. package/site/dist/docs/configuration/index.html +809 -0
  49. package/site/dist/docs/hosted/index.html +583 -0
  50. package/site/dist/docs/how-to-deploy/cloudflare/index.html +655 -0
  51. package/site/dist/docs/how-to-deploy/docker/index.html +664 -0
  52. package/site/dist/docs/how-to-deploy/wasmer/index.html +625 -0
  53. package/site/dist/docs/https/index.html +796 -0
  54. package/site/dist/docs/index.html +640 -0
  55. package/site/dist/docs/library/index.html +818 -0
  56. package/site/dist/docs/taps/index.html +746 -0
  57. package/site/dist/favicon.svg +14 -0
  58. package/site/dist/feed.xml +1 -0
  59. package/site/dist/index.html +640 -0
  60. package/site/dist/js/api.js +363 -0
  61. package/site/dist/js/search.js +436 -0
  62. package/site/dist/llms-full.txt +7640 -0
  63. package/site/dist/llms.txt +43 -0
  64. package/site/dist/logo.svg +21 -0
  65. package/site/dist/robots.txt +2 -0
  66. package/site/dist/search-index.json +1 -0
  67. package/site/dist/sitemap.xml +1 -0
@@ -0,0 +1,625 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+
4
+ <head>
5
+ <meta charset="UTF-8">
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
+ <meta name="description" content="Deploy the MockHTTP Node.js server to Wasmer Edge with app.yaml, Anybuild, and wasmer deploy.">
8
+ <link rel="stylesheet" href="/css/variables.css">
9
+ <link rel="stylesheet" href="/css/styles.css">
10
+ <link rel="stylesheet" href="/css/highlight/styles/base16/docula.css">
11
+ <link rel="icon" href="/logo.svg">
12
+ <script>
13
+ (function(){
14
+ window.__doculaThemeKey = 'docula:theme:' + ('https://mockhttp.org').replace(/^https?:\/\//, '');
15
+ var mode = localStorage.getItem(window.__doculaThemeKey) || 'light';
16
+ var resolved = mode === 'system'
17
+ ? (window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark')
18
+ : mode;
19
+ if (resolved === 'light') document.documentElement.setAttribute('data-theme', 'light');
20
+ try {
21
+ var authState = JSON.parse(localStorage.getItem('docula-auth-state'));
22
+ if (authState) {
23
+ window.__doculaAuth = authState;
24
+ if (authState.loggedIn) {
25
+ document.documentElement.classList.add('docula-auth-logged-in');
26
+ }
27
+ }
28
+ } catch (e) {
29
+ // Ignore localStorage parsing errors
30
+ }
31
+ if (!window.__doculaAuth) {
32
+ window.__doculaAuth = { loggedIn: false, displayName: null };
33
+ }
34
+ })();
35
+ </script>
36
+ <title>MockHTTP - Wasmer</title>
37
+ <script type="application/ld+json">
38
+ {"@context":"https://schema.org","@type":"TechArticle","headline":"Wasmer","description":"Deploy the MockHTTP Node.js server to Wasmer Edge with app.yaml, Anybuild, and wasmer deploy.","url":"https://mockhttp.org/docs/how-to-deploy/wasmer/","publisher":{"@type":"Organization","name":"MockHTTP"},"dateModified":"2026-10-03","keywords":[]}
39
+ </script>
40
+ </head>
41
+
42
+ <body>
43
+ <header class="header">
44
+ <div class="header-top">
45
+ <div class="header-top__content">
46
+ <button class="mobile-menu-toggle" id="mobile-menu-toggle" aria-label="Toggle navigation menu">
47
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="18" y2="18"/></svg>
48
+ </button>
49
+ <a href="/" class="logo-link">
50
+ <img alt="MockHTTP" class="logo__img" src="/logo.svg">
51
+ </a>
52
+ <nav class="header-bottom__nav">
53
+ <a class="header-bottom__item" href="/docs/" id="nav-docs">
54
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg>
55
+ <span>Documentation</span>
56
+ </a>
57
+ <a class="header-bottom__item" href="/api" id="nav-api">
58
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m16 18 6-6-6-6"/><path d="m8 6-6 6 6 6"/></svg>
59
+ <span>API Reference</span>
60
+ </a>
61
+ <a class="header-bottom__item" href="/changelog/" id="nav-changelog">
62
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 6a13 13 0 0 0 8.4-2.8A1 1 0 0 1 21 4v12a1 1 0 0 1-1.6.8A13 13 0 0 0 11 14H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2z"/><path d="M6 14a12 12 0 0 0 2.4 7.2 2 2 0 0 0 3.2-2.4A8 8 0 0 1 10 14"/><path d="M8 6v8"/></svg>
63
+ <span>Changelog</span>
64
+ </a>
65
+ </nav>
66
+ <div class="header-actions">
67
+ <button class="search-button" id="search-button" type="button" aria-label="Search" aria-keyshortcuts="Meta+K Control+K">
68
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
69
+ <span class="search-button__text">Search</span>
70
+ <span class="search-button__shortcut">⌘K</span>
71
+ </button>
72
+ <button class="theme-button" id="theme-toggle" aria-label="Theme: system (following system)">
73
+ <svg class="theme-button__icon theme-button__icon--system" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="14" rx="2"/><line x1="8" x2="16" y1="21" y2="21"/><line x1="12" x2="12" y1="17" y2="21"/></svg>
74
+ <svg class="theme-button__icon theme-button__icon--sun theme-button__icon--hidden" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/></svg>
75
+ <svg class="theme-button__icon theme-button__icon--moon theme-button__icon--hidden" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20.985 12.486a9 9 0 1 1-9.473-9.472c.405-.022.617.46.402.803a6 6 0 0 0 8.268 8.268c.344-.215.825-.004.803.401"/></svg>
76
+ </button>
77
+ </div>
78
+ </div>
79
+ </div>
80
+ </header>
81
+ <aside class="mobile-sidebar" id="mobile-sidebar">
82
+ <nav class="mobile-nav">
83
+ <a class="mobile-nav__item" href="/docs/">
84
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></svg>
85
+ <span>Documentation</span>
86
+ </a>
87
+ <a class="mobile-nav__item" href="/api">
88
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m16 18 6-6-6-6"/><path d="m8 6-6 6 6 6"/></svg>
89
+ <span>API Reference</span>
90
+ </a>
91
+ <a class="mobile-nav__item" href="/changelog/">
92
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 6a13 13 0 0 0 8.4-2.8A1 1 0 0 1 21 4v12a1 1 0 0 1-1.6.8A13 13 0 0 0 11 14H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2z"/><path d="M6 14a12 12 0 0 0 2.4 7.2 2 2 0 0 0 3.2-2.4A8 8 0 0 1 10 14"/><path d="M8 6v8"/></svg>
93
+ <span>Changelog</span>
94
+ </a>
95
+ </nav>
96
+ <div class="mobile-sidebar__docs" id="mobile-sidebar-docs"></div>
97
+ </aside>
98
+ <div class="sidebar-backdrop" id="sidebar-backdrop"></div>
99
+ <div class="search-modal" id="search-modal" hidden>
100
+ <div class="search-modal__backdrop" data-search-close></div>
101
+ <div class="search-modal__panel" role="dialog" aria-modal="true" aria-label="Search">
102
+ <div class="search-modal__header">
103
+ <svg class="search-modal__icon" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
104
+ <input
105
+ type="search"
106
+ id="search-input"
107
+ class="search-modal__input"
108
+ placeholder="Search"
109
+ autocomplete="off"
110
+ autocorrect="off"
111
+ autocapitalize="off"
112
+ spellcheck="false"
113
+ aria-label="Search"
114
+ aria-controls="search-results"
115
+ aria-activedescendant=""
116
+ role="combobox"
117
+ aria-expanded="true"
118
+ />
119
+ <button class="search-modal__clear" id="search-clear" type="button" aria-label="Clear search" hidden>
120
+ <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
121
+ </button>
122
+ </div>
123
+ <div class="search-modal__body">
124
+ <ul class="search-results" id="search-results" role="listbox" aria-label="Search results"></ul>
125
+ <div class="search-modal__empty" id="search-empty" hidden>
126
+ No results for "<span class="search-modal__empty-query" id="search-empty-query"></span>"
127
+ </div>
128
+ <div class="search-modal__initial" id="search-initial">
129
+ Type to search the documentation.
130
+ </div>
131
+ </div>
132
+ <div class="search-modal__footer">
133
+ <span class="search-modal__hint"><kbd class="search-modal__kbd">↑</kbd><kbd class="search-modal__kbd">↓</kbd> to navigate</span>
134
+ <span class="search-modal__hint"><kbd class="search-modal__kbd">↵</kbd> to select</span>
135
+ <span class="search-modal__hint"><kbd class="search-modal__kbd">esc</kbd> to close</span>
136
+ </div>
137
+ </div>
138
+ </div>
139
+ <script>
140
+ window.__doculaSearch = { indexUrl: "/search-index.json" };
141
+ </script>
142
+ <script src="/js/search.js" defer></script>
143
+ <div class="page-dropdown" id="page-dropdown">
144
+ <button class="page-dropdown__toggle" id="page-dropdown-toggle">
145
+ <span class="page-dropdown__title">Wasmer</span>
146
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m7 15 5 5 5-5"/><path d="m7 9 5-5 5 5"/></svg>
147
+ </button>
148
+ <div class="page-dropdown__list" id="page-dropdown-list">
149
+ <section class="nav-sidebar__section">
150
+ <ul class="nav-sidebar__list">
151
+ <li>
152
+ <a href="/docs/" class="nav-sidebar__item">Getting Started</a>
153
+ </li>
154
+ </ul>
155
+ </section>
156
+ <section class="nav-sidebar__section">
157
+ <ul class="nav-sidebar__list">
158
+ <li>
159
+ <a href="/docs/https/" class="nav-sidebar__item">HTTPS and HTTP/2</a>
160
+ </li>
161
+ </ul>
162
+ </section>
163
+ <section class="nav-sidebar__section">
164
+ <ul class="nav-sidebar__list">
165
+ <li>
166
+ <a href="/docs/taps/" class="nav-sidebar__item">Taps</a>
167
+ </li>
168
+ </ul>
169
+ </section>
170
+ <section class="nav-sidebar__section">
171
+ <ul class="nav-sidebar__list">
172
+ <li>
173
+ <a href="/docs/bins/" class="nav-sidebar__item">Bins</a>
174
+ </li>
175
+ </ul>
176
+ </section>
177
+ <section class="nav-sidebar__section">
178
+ <ul class="nav-sidebar__list">
179
+ <li>
180
+ <a href="/docs/configuration/" class="nav-sidebar__item">Configuration</a>
181
+ </li>
182
+ </ul>
183
+ </section>
184
+ <section class="nav-sidebar__section">
185
+ <ul class="nav-sidebar__list">
186
+ <li>
187
+ <a href="/docs/library/" class="nav-sidebar__item">Library API</a>
188
+ </li>
189
+ </ul>
190
+ </section>
191
+ <section class="nav-sidebar__section">
192
+ <ul class="nav-sidebar__list">
193
+ <li>
194
+ <a href="/docs/hosted/" class="nav-sidebar__item">MockHttp.org Live</a>
195
+ </li>
196
+ </ul>
197
+ </section>
198
+ <section class="nav-sidebar__section nav-sidebar__section--collapsible">
199
+ <h2 class="nav-sidebar__title">
200
+ <button type="button" class="nav-sidebar__toggle" aria-expanded="true">
201
+ <span class="nav-sidebar__toggle-label">How to Deploy</span>
202
+ <svg class="nav-sidebar__chevron" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg>
203
+ </button>
204
+ </h2>
205
+ <ul class="nav-sidebar__list">
206
+ <li>
207
+ <a href="/docs/how-to-deploy/cloudflare/" class="nav-sidebar__item">Cloudflare</a>
208
+ </li>
209
+ <li>
210
+ <a href="/docs/how-to-deploy/docker/" class="nav-sidebar__item">Docker</a>
211
+ </li>
212
+ <li>
213
+ <a href="/docs/how-to-deploy/wasmer/" class="nav-sidebar__item">Wasmer</a>
214
+ </li>
215
+ </ul>
216
+ </section>
217
+ </div>
218
+ </div>
219
+ <div class="content">
220
+ <aside class="nav-sidebar" id="nav-sidebar">
221
+ <section class="nav-sidebar__section">
222
+ <ul class="nav-sidebar__list">
223
+ <li>
224
+ <a href="/docs/" class="nav-sidebar__item">Getting Started</a>
225
+ </li>
226
+ </ul>
227
+ </section>
228
+ <section class="nav-sidebar__section">
229
+ <ul class="nav-sidebar__list">
230
+ <li>
231
+ <a href="/docs/https/" class="nav-sidebar__item">HTTPS and HTTP/2</a>
232
+ </li>
233
+ </ul>
234
+ </section>
235
+ <section class="nav-sidebar__section">
236
+ <ul class="nav-sidebar__list">
237
+ <li>
238
+ <a href="/docs/taps/" class="nav-sidebar__item">Taps</a>
239
+ </li>
240
+ </ul>
241
+ </section>
242
+ <section class="nav-sidebar__section">
243
+ <ul class="nav-sidebar__list">
244
+ <li>
245
+ <a href="/docs/bins/" class="nav-sidebar__item">Bins</a>
246
+ </li>
247
+ </ul>
248
+ </section>
249
+ <section class="nav-sidebar__section">
250
+ <ul class="nav-sidebar__list">
251
+ <li>
252
+ <a href="/docs/configuration/" class="nav-sidebar__item">Configuration</a>
253
+ </li>
254
+ </ul>
255
+ </section>
256
+ <section class="nav-sidebar__section">
257
+ <ul class="nav-sidebar__list">
258
+ <li>
259
+ <a href="/docs/library/" class="nav-sidebar__item">Library API</a>
260
+ </li>
261
+ </ul>
262
+ </section>
263
+ <section class="nav-sidebar__section">
264
+ <ul class="nav-sidebar__list">
265
+ <li>
266
+ <a href="/docs/hosted/" class="nav-sidebar__item">MockHttp.org Live</a>
267
+ </li>
268
+ </ul>
269
+ </section>
270
+ <section class="nav-sidebar__section nav-sidebar__section--collapsible">
271
+ <h2 class="nav-sidebar__title">
272
+ <button type="button" class="nav-sidebar__toggle" aria-expanded="true">
273
+ <span class="nav-sidebar__toggle-label">How to Deploy</span>
274
+ <svg class="nav-sidebar__chevron" xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg>
275
+ </button>
276
+ </h2>
277
+ <ul class="nav-sidebar__list">
278
+ <li>
279
+ <a href="/docs/how-to-deploy/cloudflare/" class="nav-sidebar__item">Cloudflare</a>
280
+ </li>
281
+ <li>
282
+ <a href="/docs/how-to-deploy/docker/" class="nav-sidebar__item">Docker</a>
283
+ </li>
284
+ <li>
285
+ <a href="/docs/how-to-deploy/wasmer/" class="nav-sidebar__item">Wasmer</a>
286
+ </li>
287
+ </ul>
288
+ </section>
289
+ </aside>
290
+ <article class="article">
291
+ <header class="article__header">
292
+ <h1 class="article__title">Wasmer</h1>
293
+ <p class="article__description">Deploy the MockHTTP Node.js server to Wasmer Edge with app.yaml, Anybuild, and wasmer deploy.</p>
294
+ </header>
295
+ <div class="article__body">
296
+ <main class="article__main">
297
+ <p>Wasmer Edge runs the same Node.js server as <a href="/docs/how-to-deploy/docker/">Docker</a>. The test app for this repository is <a href="https://mockhttp.wasmer.app">mockhttp.wasmer.app</a>.</p>
298
+ <p>This deploy does not publish the <a href="/docs/how-to-deploy/cloudflare/">Cloudflare Worker</a>. <a href="https://mockhttp.org">mockhttp.org</a> stays on Cloudflare.</p>
299
+ <h2 id="table-of-contents">Table of Contents</h2>
300
+ <ul>
301
+ <li><a href="#app-configuration">App configuration</a></li>
302
+ <li><a href="#build-with-anybuild">Build with Anybuild</a></li>
303
+ <li><a href="#deploy-from-the-cli">Deploy from the CLI</a></li>
304
+ <li><a href="#deploy-from-github-actions">Deploy from GitHub Actions</a></li>
305
+ <li><a href="#runtime-behavior">Runtime behavior</a></li>
306
+ </ul>
307
+ <h2 id="app-configuration">App configuration</h2>
308
+ <p><a href="https://github.com/jaredwray/mockhttp/blob/main/app.yaml"><code>app.yaml</code></a> describes the Edge app:</p>
309
+ <pre><code class="hljs language-yaml"><span class="hljs-attr">kind:</span> <span class="hljs-string">wasmer.io/App.v0</span>
310
+ <span class="hljs-attr">name:</span> <span class="hljs-string">mockhttp</span>
311
+ <span class="hljs-attr">owner:</span> <span class="hljs-string">jaredwray</span>
312
+ <span class="hljs-attr">package:</span> <span class="hljs-string">.</span>
313
+ <span class="hljs-attr">env:</span>
314
+ <span class="hljs-attr">HOST:</span> <span class="hljs-string">"0.0.0.0"</span>
315
+ <span class="hljs-attr">LOGGING:</span> <span class="hljs-string">"false"</span>
316
+ <span class="hljs-attr">AUTO_DETECT_PORT:</span> <span class="hljs-string">"false"</span>
317
+ </code></pre>
318
+ <p><code>package: .</code> deploys the repository directory. <code>HOST</code> binds the server on all interfaces. Logging is off. Wasmer injects <code>PORT</code>. <code>AUTO_DETECT_PORT=false</code> keeps that port instead of scanning for another one.</p>
319
+ <p>Change <code>name</code> and <code>owner</code> before you deploy your own app. The environment variables are the same ones the Docker image reads (<code>PORT</code>, <code>HOST</code>, <code>LOGGING</code>, <code>HTTP2</code>, and <code>AUTO_DETECT_PORT</code>). See <a href="/docs/how-to-deploy/docker/">Docker</a> for what each one does.</p>
320
+ <h2 id="build-with-anybuild">Build with Anybuild</h2>
321
+ <p><a href="https://github.com/jaredwray/mockhttp/blob/main/Anybuild"><code>Anybuild</code></a> tells Wasmer how to build the package on a remote builder:</p>
322
+ <ul>
323
+ <li>Node.js 24 and pnpm <code>12.4.1</code></li>
324
+ <li>Build command: <code>pnpm run build &#x26;&#x26; pnpm website:build</code></li>
325
+ <li>Start command: <code>node dist/index.mjs</code></li>
326
+ </ul>
327
+ <p>The build command produces <code>dist/</code> and <code>site/dist/</code> while Docula is still installed. Wasmer then prunes dev dependencies. The docs site has to exist before that prune, because Docula is a dev dependency.</p>
328
+ <h2 id="deploy-from-the-cli">Deploy from the CLI</h2>
329
+ <p>Install the <a href="https://docs.wasmer.io/install">Wasmer CLI</a> and log in, then from the repository root:</p>
330
+ <pre><code class="hljs language-bash">wasmer deploy --build-remote
331
+ </code></pre>
332
+ <p><code>--build-remote</code> uploads the source and runs the Anybuild file on Wasmer's builders. When the deploy finishes, the CLI prints the app URL.</p>
333
+ <h2 id="deploy-from-github-actions">Deploy from GitHub Actions</h2>
334
+ <p><a href="https://github.com/jaredwray/mockhttp/blob/main/.github/workflows/deploy-wasmer.yaml"><code>.github/workflows/deploy-wasmer.yaml</code></a> runs on the <code>released</code> event (a published release, not a prerelease) and when the workflow is started by hand. The <code>wasmer</code> environment provides <code>WASMER_TOKEN</code>. The deploy step runs:</p>
335
+ <pre><code class="hljs language-bash">wasmer deploy --non-interactive --build-remote
336
+ </code></pre>
337
+ <h2 id="runtime-behavior">Runtime behavior</h2>
338
+ <p>Bins use the default in-memory store, so a bin exists only on the instance that created it. Taps are a library API (<code>mock.taps.inject</code>) and have no HTTP routes, so a deployed app cannot inject one.</p>
339
+ <p><code>@fastify/rate-limit</code> is on at 1000 requests per minute. It keys on the address that connects to the process. The server does not trust proxy headers, and the allow list is only <code>127.0.0.1</code> and <code>::1</code>. On the test app, <code>/ip</code> reports <code>127.0.0.100</code>, which is the edge proxy rather than the caller, and the response includes <code>x-ratelimit-limit: 1000</code>. Clients that share that proxy address share one limit on that instance. This is not the Cloudflare limiter used by <a href="https://mockhttp.org">mockhttp.org</a>.</p>
340
+ <p>The process listens with HTTP. Wasmer terminates TLS for the <code>*.wasmer.app</code> hostname.</p>
341
+ </main>
342
+ <aside class="content-aside">
343
+ <h2 class="content-aside__title">TABLE OF CONTENTS</h2>
344
+ <ul class="content-aside__list" id="toc-list">
345
+ </ul>
346
+ </aside>
347
+ </div>
348
+ <a class="article__edit-link" href="https://github.com/jaredwray/mockhttp/edit/main/site/docs/how-to-deploy/wasmer.md" target="_blank" rel="noopener noreferrer">
349
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z"/><path d="m15 5 4 4"/></svg>
350
+ Edit this page
351
+ </a>
352
+ </article>
353
+ </div>
354
+ <footer>
355
+ <a href="/llms.txt" class="footer__link">llms.txt</a>
356
+ <a href="/feed.xml" class="footer__link" aria-label="RSS Feed">
357
+ <svg class="footer__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor"><circle cx="6.18" cy="17.82" r="2.18"/><path d="M4 4.44v2.83c7.03 0 12.73 5.7 12.73 12.73h2.83c0-8.59-6.97-15.56-15.56-15.56zm0 5.66v2.83c3.9 0 7.07 3.17 7.07 7.07h2.83c0-5.47-4.43-9.9-9.9-9.9z"/></svg>
358
+ </a>
359
+
360
+ <a href="https://docula.org/" target="_blank" rel="noopener noreferrer" class="footer__link" aria-label="Docula">
361
+ <svg class="footer__bat" xmlns="http://www.w3.org/2000/svg" viewBox="70 110 360 205" fill="currentColor"><path d="M420,173c-16.76-18-72.78-36.65-131.59-30.58A160.15,160.15,0,0,0,269,120.55c-3.78,4.52-11.15,9.45-19,9.45s-15.23-4.93-19-9.45a160.15,160.15,0,0,0-19.4,21.83C152.78,136.31,96.76,154.94,80,173c48.86,5.86,79.5,34.09,79.5,72.06,52.37,0,77,28,90.5,59.94C263.54,273,288.13,245,340.5,245,340.5,207,371.14,178.8,420,173Z"/><circle cx="239.19" cy="145.36" r="3.32" fill="#fff"/><circle cx="260.81" cy="145.36" r="3.32" fill="#fff"/></svg>
362
+ </a>
363
+ <span class="footer__updated">updated: 2026-10-03</span>
364
+ </footer>
365
+ <script src="/css/highlight/highlight.min.js"></script>
366
+ <script>
367
+ document.addEventListener('DOMContentLoaded', () => {
368
+ document.querySelectorAll('pre code').forEach(el => { el.textContent = el.textContent.trimEnd(); });
369
+ hljs.highlightAll();
370
+ var kbd = document.querySelector('.search-button__shortcut');
371
+ if (kbd) kbd.textContent = navigator.platform.indexOf('Mac') > -1 ? '⌘K' : 'Ctrl K';
372
+
373
+ // Copy code buttons
374
+ const copyIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>';
375
+ const checkIcon = '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>';
376
+ document.querySelectorAll('pre').forEach(function(pre) {
377
+ const btn = document.createElement('button');
378
+ btn.className = 'copy-code-btn';
379
+ btn.innerHTML = copyIcon;
380
+ btn.setAttribute('aria-label', 'Copy code');
381
+ btn.addEventListener('click', function() {
382
+ const code = pre.querySelector('code');
383
+ const text = code ? code.textContent : pre.textContent;
384
+ navigator.clipboard.writeText(text || '').then(function() {
385
+ btn.innerHTML = checkIcon;
386
+ setTimeout(function() { btn.innerHTML = copyIcon; }, 2000);
387
+ });
388
+ });
389
+ pre.appendChild(btn);
390
+ });
391
+ });
392
+ </script>
393
+ <script>
394
+ (function() {
395
+ var themeKey = window.__doculaThemeKey;
396
+ function getMode() {
397
+ return localStorage.getItem(themeKey) || 'light';
398
+ }
399
+
400
+ function resolveTheme(mode) {
401
+ if (mode === 'system') {
402
+ return window.matchMedia('(prefers-color-scheme: light)').matches ? 'light' : 'dark';
403
+ }
404
+ return mode;
405
+ }
406
+
407
+ var cachedEls = null;
408
+ function getThemeEls() {
409
+ if (!cachedEls) {
410
+ cachedEls = {
411
+ systemIcon: document.querySelector('.theme-button__icon--system'),
412
+ sunIcon: document.querySelector('.theme-button__icon--sun'),
413
+ moonIcon: document.querySelector('.theme-button__icon--moon'),
414
+ toggle: document.getElementById('theme-toggle')
415
+ };
416
+ }
417
+ return cachedEls;
418
+ }
419
+
420
+ function applyTheme(mode) {
421
+ var resolved = resolveTheme(mode);
422
+ if (resolved === 'light') {
423
+ document.documentElement.setAttribute('data-theme', 'light');
424
+ } else {
425
+ document.documentElement.removeAttribute('data-theme');
426
+ }
427
+
428
+ var els = getThemeEls();
429
+ if (els.systemIcon && els.sunIcon && els.moonIcon) {
430
+ els.systemIcon.classList.add('theme-button__icon--hidden');
431
+ els.sunIcon.classList.add('theme-button__icon--hidden');
432
+ els.moonIcon.classList.add('theme-button__icon--hidden');
433
+ if (mode === 'system') {
434
+ els.systemIcon.classList.remove('theme-button__icon--hidden');
435
+ } else if (mode === 'light') {
436
+ els.sunIcon.classList.remove('theme-button__icon--hidden');
437
+ } else {
438
+ els.moonIcon.classList.remove('theme-button__icon--hidden');
439
+ }
440
+ }
441
+
442
+ if (els.toggle) {
443
+ var labels = { system: 'Theme: system (following system)', light: 'Theme: light', dark: 'Theme: dark' };
444
+ els.toggle.setAttribute('aria-label', labels[mode] || 'Toggle theme');
445
+ }
446
+ }
447
+
448
+ function nextMode(current) {
449
+ var cycle = { system: 'light', light: 'dark', dark: 'system' };
450
+ return cycle[current] || 'system';
451
+ }
452
+
453
+ var currentMode = getMode();
454
+
455
+ document.addEventListener('DOMContentLoaded', function() {
456
+ applyTheme(currentMode);
457
+
458
+ var els = getThemeEls();
459
+ if (els.toggle) {
460
+ els.toggle.addEventListener('click', function() {
461
+ currentMode = nextMode(currentMode);
462
+ localStorage.setItem(themeKey, currentMode);
463
+ applyTheme(currentMode);
464
+ });
465
+ }
466
+ });
467
+
468
+ window.matchMedia('(prefers-color-scheme: light)').addEventListener('change', function() {
469
+ if (getMode() === 'system') {
470
+ applyTheme('system');
471
+ }
472
+ });
473
+ })();
474
+ </script>
475
+ <script defer>
476
+ document.addEventListener('DOMContentLoaded', () => {
477
+ const menuToggle = document.getElementById('mobile-menu-toggle');
478
+ const mobileSidebar = document.getElementById('mobile-sidebar');
479
+ const backdrop = document.getElementById('sidebar-backdrop');
480
+ if (menuToggle && mobileSidebar) {
481
+ menuToggle.addEventListener('click', () => {
482
+ mobileSidebar.classList.toggle('mobile-sidebar--open');
483
+ if (backdrop) backdrop.classList.toggle('sidebar-backdrop--visible');
484
+ });
485
+ if (backdrop) {
486
+ backdrop.addEventListener('click', () => {
487
+ mobileSidebar.classList.remove('mobile-sidebar--open');
488
+ backdrop.classList.remove('sidebar-backdrop--visible');
489
+ });
490
+ }
491
+ }
492
+
493
+ // Page dropdown toggle (docs pages)
494
+ const dropdownToggle = document.getElementById('page-dropdown-toggle');
495
+ const dropdownList = document.getElementById('page-dropdown-list');
496
+ if (dropdownToggle && dropdownList) {
497
+ dropdownToggle.addEventListener('click', () => {
498
+ dropdownList.classList.toggle('page-dropdown__list--open');
499
+ });
500
+ }
501
+
502
+ // Active sidebar link highlighting
503
+ const sidebarLinks = document.querySelectorAll('.nav-sidebar__item');
504
+ const currentPath = window.location.pathname;
505
+ sidebarLinks.forEach((link) => {
506
+ if (link.getAttribute('href') === currentPath || link.getAttribute('href') === currentPath.replace(/\/$/, '')) {
507
+ link.classList.add('nav-sidebar__item--active');
508
+ }
509
+ });
510
+
511
+ // Sidebar section collapse/expand
512
+ const SIDEBAR_STORAGE_KEY = 'docula:sidebar-sections';
513
+ const collapsibleSections = document.querySelectorAll('.nav-sidebar__section--collapsible');
514
+ if (collapsibleSections.length > 0) {
515
+ let storedSectionState = {};
516
+ try {
517
+ storedSectionState = JSON.parse(localStorage.getItem(SIDEBAR_STORAGE_KEY) || '{}');
518
+ } catch (e) { storedSectionState = {}; }
519
+
520
+ const setSectionOpen = (section, toggle, open) => {
521
+ toggle.setAttribute('aria-expanded', open ? 'true' : 'false');
522
+ section.classList.toggle('nav-sidebar__section--collapsed', !open);
523
+ };
524
+
525
+ collapsibleSections.forEach((section, idx) => {
526
+ const toggle = section.querySelector('.nav-sidebar__toggle');
527
+ const list = section.querySelector('.nav-sidebar__list');
528
+ if (!toggle || !list) return;
529
+ const listId = 'nav-sidebar-section-' + idx;
530
+ list.id = listId;
531
+ toggle.setAttribute('aria-controls', listId);
532
+
533
+ const key = 'section-' + idx;
534
+ const hasStored = Object.prototype.hasOwnProperty.call(storedSectionState, key);
535
+ const isOpen = hasStored ? !!storedSectionState[key] : true;
536
+ setSectionOpen(section, toggle, isOpen);
537
+
538
+ toggle.addEventListener('click', () => {
539
+ const next = toggle.getAttribute('aria-expanded') !== 'true';
540
+ setSectionOpen(section, toggle, next);
541
+ storedSectionState[key] = next;
542
+ try {
543
+ localStorage.setItem(SIDEBAR_STORAGE_KEY, JSON.stringify(storedSectionState));
544
+ } catch (e) { /* storage unavailable */ }
545
+ });
546
+ });
547
+ }
548
+
549
+ // Active nav link highlighting (header + mobile). Highlight only the
550
+ // single most-specific link: the one whose path is the longest prefix of
551
+ // the current path. A plain startsWith() check lights up every link whose
552
+ // path merely prefixes the current one, so when the site is embedded under
553
+ // a base path (e.g. served at /developer with docs at that root) the
554
+ // Documentation link — whose path is a prefix of every page — would stay
555
+ // highlighted everywhere. Trailing slashes are normalized so matches stop
556
+ // at a path boundary. We read the anchor's resolved origin/pathname so
557
+ // absolute, relative, and same-origin hrefs all work, while cross-origin
558
+ // links and non-anchor items (e.g. the mobile logout button) are skipped.
559
+ const withTrailingSlash = (p) => (p.endsWith('/') ? p : p + '/');
560
+ const here = withTrailingSlash(currentPath);
561
+ const markActiveNav = (selector, activeClass) => {
562
+ let bestLink = null;
563
+ let bestLength = -1;
564
+ document.querySelectorAll(selector).forEach((link) => {
565
+ // Only same-origin anchors can match the current pathname.
566
+ if (!link.href || link.origin !== window.location.origin) return;
567
+ const base = withTrailingSlash(link.pathname);
568
+ if (here.startsWith(base) && base.length > bestLength) {
569
+ bestLink = link;
570
+ bestLength = base.length;
571
+ }
572
+ });
573
+ if (bestLink) bestLink.classList.add(activeClass);
574
+ };
575
+ markActiveNav('.header-bottom__item', 'header-bottom__item--active');
576
+ markActiveNav('.mobile-nav__item', 'mobile-nav__item--active');
577
+
578
+ // TOC extraction: move the inline TOC into the right sidebar and hide the original
579
+ const tocHeading = document.getElementById('table-of-contents');
580
+ if (tocHeading) {
581
+ const tocList = tocHeading.nextElementSibling;
582
+ const tocTarget = document.getElementById('toc-list');
583
+ if (tocList && tocList.tagName === 'UL' && tocTarget) {
584
+ tocTarget.innerHTML = tocList.innerHTML;
585
+ tocHeading.style.display = 'none';
586
+ tocList.style.display = 'none';
587
+ }
588
+ }
589
+
590
+ // Hide the TOC aside if it has no entries
591
+ const tocSidebar = document.getElementById('toc-list');
592
+ if (tocSidebar && tocSidebar.children.length === 0) {
593
+ const aside = tocSidebar.closest('.content-aside');
594
+ if (aside) { aside.style.display = 'none'; }
595
+ }
596
+
597
+ // Image lightbox
598
+ const lightboxOverlay = document.createElement('div');
599
+ lightboxOverlay.className = 'lightbox-overlay';
600
+ lightboxOverlay.addEventListener('click', function(e) {
601
+ if (e.target !== lightboxImg) lightboxOverlay.classList.remove('lightbox-overlay--visible');
602
+ });
603
+ const lightboxClose = document.createElement('button');
604
+ lightboxClose.className = 'lightbox-close';
605
+ lightboxClose.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>';
606
+ lightboxClose.addEventListener('click', function() {
607
+ lightboxOverlay.classList.remove('lightbox-overlay--visible');
608
+ });
609
+ const lightboxImg = document.createElement('img');
610
+ lightboxOverlay.appendChild(lightboxClose);
611
+ lightboxOverlay.appendChild(lightboxImg);
612
+ document.body.appendChild(lightboxOverlay);
613
+
614
+ document.querySelectorAll('.article__main img, .changelog-entry-body img').forEach(function(img) {
615
+ if (img.closest('a')) return;
616
+ img.addEventListener('click', function() {
617
+ lightboxImg.src = img.src;
618
+ lightboxOverlay.classList.add('lightbox-overlay--visible');
619
+ });
620
+ });
621
+ });
622
+ </script>
623
+ </body>
624
+
625
+ </html>