feat: add gzip toggle and cache mode (normal / no-cache / bust)
- Cache-mode selector: Normal, No-cache headers, Cache-bust URL+headers - Cache-bust appends random ?_cb= per iteration to bypass CDN/proxy - gzip toggle: on = k6 default (Accept-Encoding: gzip/br), off = identity - Both options stored in DB with non-destructive migration - History items show cache-mode and gzip pills - Schema migration handles existing DBs gracefully Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -30,6 +30,15 @@ methodSel.addEventListener('change', () => {
|
||||
bodyGroup.style.display = (m !== 'GET' && m !== 'HEAD') ? '' : 'none';
|
||||
});
|
||||
|
||||
// gzip toggle hint
|
||||
const gzipChk = document.getElementById('gzip');
|
||||
const gzipHint = document.getElementById('gzip-hint');
|
||||
gzipChk.addEventListener('change', () => {
|
||||
gzipHint.textContent = gzipChk.checked
|
||||
? 'k6 default — server may compress response'
|
||||
: 'Sends Accept-Encoding: identity — forces uncompressed response';
|
||||
});
|
||||
|
||||
// ---- Run Test ----
|
||||
const form = document.getElementById('test-form');
|
||||
const startBtn = document.getElementById('start-btn');
|
||||
@@ -49,6 +58,8 @@ form.addEventListener('submit', async (e) => {
|
||||
const httpMethod = document.getElementById('httpMethod').value;
|
||||
const requestBody = document.getElementById('requestBody').value.trim();
|
||||
const headers = document.getElementById('headers').value.trim() || '{}';
|
||||
const cacheMode = document.getElementById('cacheMode').value;
|
||||
const gzip = document.getElementById('gzip').checked;
|
||||
|
||||
// Validate headers JSON
|
||||
try { JSON.parse(headers); } catch {
|
||||
@@ -69,7 +80,7 @@ form.addEventListener('submit', async (e) => {
|
||||
res = await fetch('/api/tests', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ url, vus, duration, rpsLimit, httpMethod, requestBody, headers }),
|
||||
body: JSON.stringify({ url, vus, duration, rpsLimit, httpMethod, requestBody, headers, cacheMode, gzip }),
|
||||
});
|
||||
} catch (err) {
|
||||
alert('Failed to start test: ' + err.message);
|
||||
@@ -227,12 +238,22 @@ async function loadHistory() {
|
||||
summaryLine = parts.join(' · ');
|
||||
}
|
||||
|
||||
const cacheBadge = t.cache_mode === 'bust'
|
||||
? '<span class="pill bust">cache-bust</span>'
|
||||
: t.cache_mode === 'no-cache'
|
||||
? '<span class="pill no-cache">no-cache</span>'
|
||||
: '<span class="pill cached">cached</span>';
|
||||
const gzipBadge = t.gzip
|
||||
? '<span class="pill gzip">gzip</span>'
|
||||
: '<span class="pill no-gzip">no-gzip</span>';
|
||||
|
||||
item.innerHTML = `
|
||||
<div>
|
||||
<div class="row1">
|
||||
<span class="badge ${t.status}">${t.status}</span>
|
||||
<span class="url">${escHtml(t.url)}</span>
|
||||
<span class="meta">${t.http_method} · ${t.vus} VUs · ${dur}</span>
|
||||
${cacheBadge}${gzipBadge}
|
||||
</div>
|
||||
<div class="meta">${date}</div>
|
||||
${summaryLine ? `<div class="history-summary">${escHtml(summaryLine)}</div>` : ''}
|
||||
|
||||
@@ -58,6 +58,27 @@
|
||||
<input type="number" id="rpsLimit" min="0" value="0" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="cacheMode">Cache Mode</label>
|
||||
<select id="cacheMode">
|
||||
<option value="normal">Normal (allow cache)</option>
|
||||
<option value="no-cache">No-cache headers (revalidate)</option>
|
||||
<option value="bust">Cache-bust URL + headers (full bypass)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Encoding</label>
|
||||
<div class="toggle-row">
|
||||
<label class="toggle">
|
||||
<input type="checkbox" id="gzip" checked />
|
||||
<span class="toggle-track"></span>
|
||||
<span class="toggle-label">Accept gzip / br</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="hint" id="gzip-hint">k6 default — server may compress response</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group full" id="body-group" style="display:none">
|
||||
<label for="requestBody">Request Body</label>
|
||||
<textarea id="requestBody" rows="4" placeholder='{"key": "value"}'></textarea>
|
||||
@@ -65,7 +86,7 @@
|
||||
|
||||
<div class="form-group full">
|
||||
<label for="headers">
|
||||
Custom Headers <span class="hint">(JSON, optional)</span>
|
||||
Custom Headers <span class="hint">(JSON, optional — merged with above options)</span>
|
||||
</label>
|
||||
<input type="text" id="headers" placeholder='{"Authorization": "Bearer token"}' />
|
||||
</div>
|
||||
|
||||
@@ -112,6 +112,46 @@ textarea { font-family: var(--mono); resize: vertical; }
|
||||
cursor: pointer;
|
||||
transition: background .15s;
|
||||
}
|
||||
|
||||
/* TOGGLE SWITCH */
|
||||
.toggle-row { display: flex; align-items: center; gap: .75rem; margin-top: .15rem; }
|
||||
.toggle { display: flex; align-items: center; gap: .55rem; cursor: pointer; }
|
||||
.toggle input { display: none; }
|
||||
.toggle-track {
|
||||
width: 38px; height: 20px;
|
||||
background: var(--border);
|
||||
border-radius: 999px;
|
||||
position: relative;
|
||||
transition: background .2s;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.toggle-track::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 14px; height: 14px;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
top: 3px; left: 3px;
|
||||
transition: transform .2s;
|
||||
}
|
||||
.toggle input:checked + .toggle-track { background: var(--accent); }
|
||||
.toggle input:checked + .toggle-track::after { transform: translateX(18px); }
|
||||
.toggle-label { font-size: .88rem; color: var(--text); }
|
||||
|
||||
/* PILLS */
|
||||
.pill {
|
||||
display: inline-block;
|
||||
font-size: .72rem;
|
||||
font-weight: 600;
|
||||
padding: .15rem .5rem;
|
||||
border-radius: 999px;
|
||||
letter-spacing: .04em;
|
||||
}
|
||||
.pill.cached { background: rgba(34,197,94,.12); color: #4ade80; }
|
||||
.pill.no-cache { background: rgba(245,158,11,.12); color: #fbbf24; }
|
||||
.pill.bust { background: rgba(239,68,68,.12); color: #f87171; }
|
||||
.pill.gzip { background: rgba(124,58,237,.15); color: var(--accent2); }
|
||||
.pill.no-gzip { background: rgba(100,116,139,.12); color: var(--muted); }
|
||||
.btn-secondary:hover { background: rgba(124,58,237,.15); }
|
||||
|
||||
/* RESULT */
|
||||
|
||||
Reference in New Issue
Block a user