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:
2026-05-01 20:03:36 +02:00
parent 0cd0f96bab
commit 6ef7564e87
4 changed files with 119 additions and 11 deletions

View File

@@ -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>` : ''}