Nipun commited on
Commit
1b9bcd8
·
1 Parent(s): 0f02098

Fix binary/image handling - use blob for preview

Browse files
Files changed (1) hide show
  1. app.py +55 -24
app.py CHANGED
@@ -629,18 +629,14 @@ def ui():
629
  try {
630
  const res = await fetch(url, opts);
631
  const elapsed = Math.round(performance.now() - start);
632
- const text = await res.text();
 
633
 
634
  // Status
635
  const statusEl = document.getElementById('status');
636
  statusEl.textContent = res.status + ' ' + res.statusText;
637
  statusEl.className = 'status-value ' + (res.ok ? 'status-ok' : (res.status >= 500 ? 'status-err' : 'status-warn'));
638
 
639
- // Meta
640
- document.getElementById('time').textContent = elapsed + 'ms';
641
- document.getElementById('size').textContent = text.length > 1024 ? (text.length / 1024).toFixed(1) + ' KB' : text.length + ' B';
642
- document.getElementById('content-type').textContent = res.headers.get('content-type')?.split(';')[0] || '-';
643
-
644
  // Response headers
645
  const headersHtml = [];
646
  res.headers.forEach((value, name) => {
@@ -648,21 +644,41 @@ def ui():
648
  });
649
  document.getElementById('response-headers').innerHTML = headersHtml.join('') || '<div style="color:#86868b">No headers</div>';
650
 
651
- // Raw response
652
- document.getElementById('response-raw').textContent = text;
 
 
 
 
653
 
654
- // Formatted response
655
- let display;
656
- try {
657
- const json = JSON.parse(text);
658
- display = highlightJSON(JSON.stringify(json, null, 2));
659
- } catch {
660
- display = text.replace(/</g, '&lt;').replace(/>/g, '&gt;');
661
- }
662
- document.getElementById('response').innerHTML = display;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
663
 
664
- // Preview
665
- renderPreview(text, res.headers.get('content-type') || '');
 
666
 
667
  } catch (err) {
668
  document.getElementById('status').textContent = 'Error';
@@ -680,7 +696,26 @@ def ui():
680
  document.getElementById('url').onkeydown = (e) => { if (e.key === 'Enter') sendRequest(); };
681
  sendRequest();
682
 
683
- // Preview rendering
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
684
  function renderPreview(text, contentType) {
685
  const container = document.getElementById('preview-container');
686
  const ct = contentType.toLowerCase();
@@ -693,10 +728,6 @@ def ui():
693
  iframe.srcdoc = text;
694
  container.innerHTML = '';
695
  container.appendChild(iframe);
696
- } else if (ct.includes('image/')) {
697
- // Show image (requires blob URL for binary)
698
- const url = document.getElementById('url').value;
699
- container.innerHTML = `<img class="preview-image" src="${url}" alt="Image preview">`;
700
  } else if (ct.includes('application/json') || ct.includes('json')) {
701
  // Interactive JSON tree
702
  try {
 
629
  try {
630
  const res = await fetch(url, opts);
631
  const elapsed = Math.round(performance.now() - start);
632
+ const contentType = res.headers.get('content-type') || '';
633
+ const isBinary = contentType.includes('image/') || contentType.includes('octet-stream');
634
 
635
  // Status
636
  const statusEl = document.getElementById('status');
637
  statusEl.textContent = res.status + ' ' + res.statusText;
638
  statusEl.className = 'status-value ' + (res.ok ? 'status-ok' : (res.status >= 500 ? 'status-err' : 'status-warn'));
639
 
 
 
 
 
 
640
  // Response headers
641
  const headersHtml = [];
642
  res.headers.forEach((value, name) => {
 
644
  });
645
  document.getElementById('response-headers').innerHTML = headersHtml.join('') || '<div style="color:#86868b">No headers</div>';
646
 
647
+ if (isBinary) {
648
+ // Handle binary data
649
+ const blob = await res.blob();
650
+ document.getElementById('time').textContent = elapsed + 'ms';
651
+ document.getElementById('size').textContent = blob.size > 1024 ? (blob.size / 1024).toFixed(1) + ' KB' : blob.size + ' B';
652
+ document.getElementById('content-type').textContent = contentType.split(';')[0] || '-';
653
 
654
+ document.getElementById('response-raw').textContent = `[Binary data: ${blob.size} bytes]`;
655
+ document.getElementById('response').innerHTML = `<span style="color:#86868b">[Binary data: ${blob.size} bytes, type: ${contentType}]</span>`;
656
+
657
+ // Preview binary
658
+ renderBinaryPreview(blob, contentType, url);
659
+ } else {
660
+ // Handle text data
661
+ const text = await res.text();
662
+ document.getElementById('time').textContent = elapsed + 'ms';
663
+ document.getElementById('size').textContent = text.length > 1024 ? (text.length / 1024).toFixed(1) + ' KB' : text.length + ' B';
664
+ document.getElementById('content-type').textContent = contentType.split(';')[0] || '-';
665
+
666
+ // Raw response
667
+ document.getElementById('response-raw').textContent = text;
668
+
669
+ // Formatted response
670
+ let display;
671
+ try {
672
+ const json = JSON.parse(text);
673
+ display = highlightJSON(JSON.stringify(json, null, 2));
674
+ } catch {
675
+ display = text.replace(/</g, '&lt;').replace(/>/g, '&gt;');
676
+ }
677
+ document.getElementById('response').innerHTML = display;
678
 
679
+ // Preview
680
+ renderPreview(text, contentType);
681
+ }
682
 
683
  } catch (err) {
684
  document.getElementById('status').textContent = 'Error';
 
696
  document.getElementById('url').onkeydown = (e) => { if (e.key === 'Enter') sendRequest(); };
697
  sendRequest();
698
 
699
+ // Preview rendering for binary content
700
+ function renderBinaryPreview(blob, contentType, url) {
701
+ const container = document.getElementById('preview-container');
702
+ const ct = contentType.toLowerCase();
703
+
704
+ if (ct.includes('image/')) {
705
+ const blobUrl = URL.createObjectURL(blob);
706
+ container.innerHTML = `<img class="preview-image" src="${blobUrl}" alt="Image preview" onload="URL.revokeObjectURL(this.src)">`;
707
+ } else {
708
+ // Generic binary
709
+ container.innerHTML = `<div class="preview-text" style="text-align:center;padding:40px;">
710
+ <div style="font-size:32px;margin-bottom:12px;">Binary Data</div>
711
+ <div style="color:#86868b;">${blob.size} bytes</div>
712
+ <div style="color:#86868b;">${contentType}</div>
713
+ <a href="${url}" download style="display:inline-block;margin-top:16px;padding:8px 16px;background:#007aff;color:#fff;border-radius:6px;text-decoration:none;">Download</a>
714
+ </div>`;
715
+ }
716
+ }
717
+
718
+ // Preview rendering for text content
719
  function renderPreview(text, contentType) {
720
  const container = document.getElementById('preview-container');
721
  const ct = contentType.toLowerCase();
 
728
  iframe.srcdoc = text;
729
  container.innerHTML = '';
730
  container.appendChild(iframe);
 
 
 
 
731
  } else if (ct.includes('application/json') || ct.includes('json')) {
732
  // Interactive JSON tree
733
  try {