Skip to content

Response

Import the Response class and use it in your route handlers:

(ctx) => {
return Res.json({ message: "Hello World" });
};

Returns a JSON response with Content-Type: application/json.

(ctx) => {
return Res.json({
user: { id: 1, name: "Angga" },
status: "success",
});
};
// With custom options
(ctx) => {
return Res.json(
{ error: "Not found" },
{ status: 404, headers: { "X-Custom": "value" } }
);
};

Returns a plain text response with Content-Type: text/plain.

(ctx) => {
return Res.text("Hello, World!");
};
// With custom status
(ctx) => {
return Res.text("Server Error", { status: 500 });
};

Returns an HTML response with Content-Type: text/html.

(ctx) => {
return Res.html(`
<html>
<body>
<h1>Welcome</h1>
<p>Hello from GamanJS!</p>
</body>
</html>
`);
};
// With custom headers
(ctx) => {
return Res.html("<h1>Custom Page</h1>", {
status: 201,
headers: { "X-Frame-Options": "DENY" },
});
};

Renders a template using a configured view engine. Requires setting up a view engine integration first.

(ctx) => {
return Res.render("home", {
title: "Welcome",
user: { name: "Angga" },
});
};
// With custom status
(ctx) => {
return Res.render("error", { message: "Page not found" }, { status: 404 });
};

Returns a streaming response with Content-Type: application/octet-stream.

import { createReadStream } from "fs";
(ctx) => {
const fileStream = createReadStream("./large-file.pdf");
return Res.stream(fileStream);
};
// With custom content type
(ctx) => {
const videoStream = createReadStream("./video.mp4");
return Res.stream(videoStream, {
headers: { "Content-Type": "video/mp4" },
});
};

Returns a redirect Res. Default status is 302 (temporary redirect).

(ctx) => {
return Res.redirect("/login");
};
// Permanent redirect (301)
(ctx) => {
return Res.redirect("/new-url", 301);
};
// Temporary redirect (302) - explicit
(ctx) => {
return Res.redirect("/dashboard", 302);
};

GamanJS automatically detects the response type based on what you return:

Automatically returns Res.text() with status 200:

(ctx) => {
return "Hello, World!"; // → Res.text("Hello, World!")
};
(ctx) => {
return "Server is running"; // Plain text response
};

Strings containing HTML tags automatically return Res.html():

(ctx) => {
return "<h1>Welcome to My Site</h1>"; // → Res.html(...)
};
(ctx) => {
return `
<div>
<h2>User Profile</h2>
<p>Welcome back!</p>
</div>
`; // HTML response
};

Objects automatically return Res.json() with status 200:

(ctx) => {
return { message: "Success", data: [1, 2, 3] }; // → Res.json(...)
};
(ctx) => {
const user = { id: 1, name: "Angga", email: "angga@example.com" };
return user; // JSON response
};

These shortcuts are equivalent to their explicit counterparts:

// Shortcut
(ctx) => ({ message: "OK" })
// Equivalent to
(ctx) => {
return Res.json({ message: "OK" });
}

All response methods accept an optional options parameter:

interface IResponseOptions {
status?: number; // HTTP status code (default: 200)
statusText?: string; // HTTP status text
headers?: Record<string, string | string[]>; // Custom headers
}
// Custom status code
Res.json({ error: "Not found" }, { status: 404 });
// Custom headers
Res.text("Hello", {
headers: {
"X-Custom-Header": "value",
"Cache-Control": "no-cache",
},
});
// Multiple options
Res.html("<h1>Error</h1>", {
status: 500,
statusText: "Internal Server Error",
headers: { "X-Error": "true" },
});

// Success response
(ctx) => Res.json({
success: true,
data: result,
timestamp: new Date()
})
// Error response
(ctx) => Res.json(
{ error: "Validation failed", details: errors },
{ status: 400 }
)
// Paginated response
(ctx) => Res.json({
data: items,
pagination: { page: 1, limit: 10, total: 100 }
})
// PDF download
(ctx) => {
const pdfStream = generatePDF();
return Res.stream(pdfStream, {
headers: {
"Content-Type": "application/pdf",
"Content-Disposition": "attachment; filename=report.pdf",
},
});
};
// Image response
(ctx) => {
const imageBuffer = await generateImage();
return new Response(imageBuffer, {
headers: { "Content-Type": "image/png" },
});
};
// Login redirect
(ctx) => {
if (!ctx.locals.user) {
return Res.redirect("/login");
}
return Res.render("dashboard", { user: ctx.locals.user });
};
// Post-login redirect
(ctx) => {
await ctx.session.set("user", user);
return Res.redirect("/dashboard");
};
(ctx) => {
const accept = ctx.header("accept");
if (accept?.includes("application/json")) {
return { message: "Hello API" };
}
if (accept?.includes("text/html")) {
return "<h1>Hello Web</h1>";
}
return "Hello World";
};

  • Use response shortcuts for simple responses to keep code clean
  • Set appropriate HTTP status codes for different scenarios
  • Include relevant headers for security and caching
  • Use Res.redirect() for navigation flows
  • Configure view engines when using server-side rendering
  • Handle streaming responses for large files
  • Use consistent JSON response formats for APIs
  • Set proper Content-Type headers for file downloads

GamanJS Response system provides both convenience and flexibility, allowing you to choose between explicit response methods and automatic shortcuts based on your needs.