Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
139 changes: 139 additions & 0 deletions frontend/src/components/TryItPanel.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { useState } from "react";

export default function TryItPanel({ endpoint, method = "POST" }) {
const [apiKey, setApiKey] = useState("");
const [jsonBody, setJsonBody] = useState(`{}`);
const [response, setResponse] = useState("");
const [status, setStatus] = useState("");
const [error, setError] = useState("");
const [params, setParams] = useState({});

function buildEndpoint() {
let url = endpoint;
Object.keys(params).forEach(key => {
url = url.replace(`:${key}`, params[key]);
});
return url;
}
Comment on lines +11 to +17

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

URL-encode path parameters to prevent malformed URLs.

User-provided parameter values containing special characters (spaces, slashes, etc.) will produce invalid URLs or cause unintended routing behavior.

Proposed fix
 function buildEndpoint() {
   let url = endpoint;
   Object.keys(params).forEach(key => {
-    url = url.replace(`:${key}`, params[key]);
+    url = url.replace(`:${key}`, encodeURIComponent(params[key] || ""));
   });
   return url;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function buildEndpoint() {
let url = endpoint;
Object.keys(params).forEach(key => {
url = url.replace(`:${key}`, params[key]);
});
return url;
}
function buildEndpoint() {
let url = endpoint;
Object.keys(params).forEach(key => {
url = url.replace(`:${key}`, encodeURIComponent(params[key] || ""));
});
return url;
}
🤖 Prompt for AI Agents
In @frontend/src/components/TryItPanel.jsx around lines 11 - 17, buildEndpoint
currently inserts raw param values into the URL which allows spaces and special
characters to break the URL; update the replacement logic in buildEndpoint to
URL-encode each path param value (use encodeURIComponent on params[key] or
equivalent) before calling url.replace, and guard against null/undefined params
by coercing to string so replacements always produce a valid, encoded URL.



async function sendRequest() {
// Stop if API key is missing
if (!apiKey || apiKey.trim() === "") {
setError("You need an API key. Go to Dashboard → Create Project → Copy API key.");
return;
}

// Clear previous error
setError("");

try {
const res = await fetch(`https://api.urbackend.bitbros.in${buildEndpoint()}`, {



method,
headers: {
"Content-Type": "application/json",
"x-api-key": apiKey,
},
body: method !== "GET" ? jsonBody : null,
});

const data = await res.text();
setStatus(res.status);
setResponse(data);
} catch (err) {
setResponse(err.message);
}
Comment on lines +46 to +48

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Inconsistent error handling leaves stale status displayed.

Network errors are assigned to response state while validation errors use error state. Additionally, status is not cleared, so users may see a previous request's status code alongside the new error message—creating a confusing UX.

Proposed fix
     } catch (err) {
-      setResponse(err.message);
+      setError(`Network error: ${err.message}`);
+      setResponse("");
+      setStatus("");
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} catch (err) {
setResponse(err.message);
}
} catch (err) {
setError(`Network error: ${err.message}`);
setResponse("");
setStatus("");
}
🤖 Prompt for AI Agents
In @frontend/src/components/TryItPanel.jsx around lines 46 - 48, The catch block
currently sets setResponse(err.message) and leaves status unchanged, causing
stale status and inconsistent handling versus validation errors; change the
catch to setError(err.message) (matching validation error usage), clear any
previous response with setResponse('') and reset status (e.g., setStatus(null)
or ''), so network errors use the same error state and the displayed HTTP status
is cleared when an error occurs.

}
Comment on lines +20 to +49

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Validate JSON before sending the request.

The jsonBody is sent without validation. If the user enters invalid JSON, the request will fail with a confusing error or the server will reject it, providing poor UX.

✅ Proposed fix with JSON validation
   async function sendRequest() {
+    // Validate JSON for non-GET requests
+    if (method !== "GET") {
+      try {
+        JSON.parse(jsonBody);
+      } catch (err) {
+        setStatus("400");
+        setResponse(`Invalid JSON: ${err.message}`);
+        return;
+      }
+    }
+
     try {
       const res = await fetch(`https://api.urbackend.bitbros.in${endpoint}`, {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async function sendRequest() {
try {
const res = await fetch(`https://api.urbackend.bitbros.in${endpoint}`, {
method,
headers: {
"Content-Type": "application/json",
"x-api-key": apiKey,
},
body: method !== "GET" ? jsonBody : null,
});
const data = await res.text();
setStatus(res.status);
setResponse(data);
} catch (err) {
setResponse(err.message);
}
}
async function sendRequest() {
// Validate JSON for non-GET requests
if (method !== "GET") {
try {
JSON.parse(jsonBody);
} catch (err) {
setStatus("400");
setResponse(`Invalid JSON: ${err.message}`);
return;
}
}
try {
const res = await fetch(`https://api.urbackend.bitbros.in${endpoint}`, {
method,
headers: {
"Content-Type": "application/json",
"x-api-key": apiKey,
},
body: method !== "GET" ? jsonBody : null,
});
const data = await res.text();
setStatus(res.status);
setResponse(data);
} catch (err) {
setResponse(err.message);
}
}
🤖 Prompt for AI Agents
In @frontend/src/components/TryItPanel.jsx around lines 9 - 26, sendRequest
currently sends jsonBody without validating it; parse jsonBody before making the
fetch and if JSON.parse throws, capture the error and call setStatus(400) and
setResponse with a clear validation error message instead of proceeding; only
include the parsed body (stringify it back or use the original jsonBody) in the
fetch when method !== "GET" and parsing succeeded; keep using
setStatus/responses for HTTP and validation flows and ensure the catch still
handles network/fetch errors by setting setResponse(err.message).


return (
<div className="card" style={{ marginTop: "1.5rem" }}>
<h4 style={{ fontSize: "0.9rem", marginBottom: "1rem", color: "var(--color-text-muted)" }}>
Try It Out
</h4>

<div style={{ marginBottom: "1rem" }}>
<label className="form-label">x-api-key</label>
<input
className="input-field"
value={apiKey}
onChange={(e) => setApiKey(e.target.value)}
placeholder="YOUR API KEY"
/>
</div>
{endpoint.includes(":") && (
<div style={{ marginBottom: "1rem" }}>
<label className="form-label">Path Parameters</label>

{endpoint
.match(/:([a-zA-Z0-9_]+)/g)
?.map(p => {
const key = p.replace(":", "");
return (
<input
key={key}
className="input-field"
placeholder={key}
value={params[key] || ""}
onChange={e => setParams({ ...params, [key]: e.target.value })}
style={{ marginBottom: "0.5rem" }}
/>
);
})}
</div>
)}

{method !== "GET" && (
<div style={{ marginBottom: "1rem" }}>
<label className="form-label">Request Body</label>
<textarea
className="input-field"
style={{ minHeight: "120px", fontFamily: "monospace" }}
value={jsonBody}
onChange={(e) => setJsonBody(e.target.value)}
/>
</div>
)}

{error && (
<div style={{
background: "rgba(239,68,68,0.1)",
border: "1px solid rgba(239,68,68,0.4)",
padding: "0.75rem",
borderRadius: "6px",
color: "#f87171",
marginBottom: "1rem",
fontSize: "0.85rem"
}}>
{error}
</div>
)}

<button onClick={sendRequest} className="btn btn-primary">
Send Request
</button>

{response && (
<div style={{ marginTop: "1rem" }}>
<div style={{ fontSize: "0.8rem", color: "var(--color-text-muted)", marginBottom: "0.25rem" }}>
Status: {status}
</div>
<pre style={{
background: "#0b0b0b",
border: "1px solid #222",
borderRadius: "6px",
padding: "1rem",
color: "var(--color-primary)",
fontSize: "0.8rem",
overflowX: "auto"
}}>
{response}
</pre>
</div>
)}
</div>
);

}
3 changes: 3 additions & 0 deletions frontend/src/pages/Docs.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { useState } from 'react';
import { Copy, Terminal, Database, Shield, HardDrive, Check, Server, Menu, X, ChevronDown, AlertCircle, Zap } from 'lucide-react';
import { API_URL } from '../config';
import TryItPanel from "../components/TryItPanel.jsx";
Comment on lines 3 to +4

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid base-URL drift: ensure TryItPanel uses API_URL (not a hard-coded domain).

Docs.jsx already centralizes the base URL via API_URL (Line 3), but TryItPanel (per provided snippet) builds requests from a fixed https://api.urbackend.bitbros.in. That’s likely to break local/staging docs and makes the docs page inconsistent. Prefer passing API_URL into TryItPanel (or have TryItPanel import the same config) and only pass endpoint from Docs.jsx.

Proposed change (requires updating TryItPanel to accept/use `baseUrl`)
-                        <TryItPanel endpoint="/api/data/products" method="POST" />
+                        <TryItPanel baseUrl={API_URL} endpoint="/api/data/products" method="POST" />

Also applies to: 257-258

🤖 Prompt for AI Agents
In @frontend/src/pages/Docs.jsx around lines 3 - 4, Docs.jsx imports API_URL but
TryItPanel currently uses a hard-coded domain; update Docs.jsx to pass API_URL
into TryItPanel (e.g., as a baseUrl prop) and modify TryItPanel to accept and
use that prop (or import API_URL directly) when building request URLs instead of
the fixed "https://api.urbackend.bitbros.in"; ensure TryItPanel uses the passed
baseUrl when composing requests and remove the hard-coded domain so
local/staging environments follow API_URL.


import Footer from '../components/Layout/Footer';

Expand Down Expand Up @@ -253,6 +254,8 @@ console.log(data);
body={{ name: "MacBook Pro", price: 1299, inStock: true }}
comment="Add a new item"
/>
<TryItPanel endpoint="/api/data/:collectionName" method="POST" />


<h3 style={{ fontSize: '1.1rem', marginTop: '2rem' }}>3. Get / Update / Delete by ID</h3>
<p style={{ fontSize: '0.9rem', color: 'var(--color-text-muted)' }}>
Expand Down
Loading