On this page
responses
introduction
the Response class wraps the raw node http response. however, you almost never interact with the response object directly. instead, controllers return one of the globally available response helpers: render(), json(), redirect(), back(), abort(), or status().
dframework detects the returned helper and finalizes the http response automatically.
basic responses
the status() helper is used to set the http status code. it returns a chainable response object. you can chain .json() or .send() onto it.
1export default class WebhookController {2 async handle() {3 // responds with a 202 accepted and empty body4 return status(202).send('');5 }6}
headers and cookies
you can attach headers and cookies to the response before finalizing it. these methods are chainable.
1export default class DownloadController {2 async export() {3 const csv = await generateCsv();4 return status(200)5 .set('Content-Disposition', 'attachment; filename="export.csv"')6 .type('text/csv')7 .send(csv);8 }9}to set a cookie, use the .cookie() method.
1export default class ThemeController {2 async update() {3 return status(200)4 .cookie('theme', 'dark', { httpOnly: false, path: '/', maxAge: 31536000 })5 .json({ success: true });6 }7}
json responses
the json() helper automatically sets the Content-Type to application/json; charset=utf-8 and serializes the provided object.
1export default class ApiController {2 async user(req) {3 const user = await User.find(req.params.id);4 return json({ success: true, user });5 }6}if validation errors were bound to the response via .withErrors(), the framework automatically injects them into the json payload. if the application is running in local development mode with the debugbar enabled, performance metrics are also automatically injected into the json payload.
rendering views
the render() helper evaluates a view template and sends the resulting html. rendering is scheduled asynchronously, which allows you to chain data binding methods before the html is actually compiled.
1export default class ProfileController {2 async show() {3 const user = Auth.user();4 5 return render('app.profile.show', { user })6 .withData({ title: 'my profile' })7 .antiPeeping(false);8 }9}if a form submission fails, you can flash the validation errors and the old input back to the view using .withErrors() and .withInput(). you can also flash custom key/value pairs using .with(key, value).
1export default class SettingsController {2 async update(req) {3 const validation = validate(req.body, rules);4 5 if (validation.fails()) {6 return back().withErrors(validation.errors()).withInput(req.body).with('toast', 'settings could not be saved');7 }8 9 // ...10 }11}
redirects
the redirect(url, code = 302, force = false) helper creates a redirect response.
as noted in the controllers documentation, dframework redirect helper is strictly protected against open redirect vulnerabilities. it refuses to redirect to cross origin or protocol relative urls, throwing an error instead (except in local development).
it is also spa aware. if the request was made by the client side router (dSPAHttpRequest), it returns a json instruction for the frontend router to execute instead of issuing a standard http 302. setting the force boolean to true forces the spa router to perform a hard page reload.
1export default class AuthController {2 async logout() {3 await Auth.logout();4 return redirect('/home');5 }6}the back() helper redirects the user to their previous location based on the session's internal history tracking.
1export default class PostController {2 async destroy(req) {3 await Post.delete(req.params.id);4 return back('/fallback-url');5 }6}
error responses
the abort(code, message) helper immediately halts execution and returns an error response. it is context aware: if the request was made via ajax, it automatically returns a json error payload. if it was a standard browser request, it passes the error to the global error handler which renders the appropriate html error page (e.g. 404, 500).
1export default class FileController {2 async show(req) {3 const file = await File.find(req.params.id);4 5 if (!file) {6 return abort(404, 'file not found');7 }8 9 if (file.owner_id !== Auth.user().id) {10 return abort(403, 'unauthorized access');11 }12 13 return json({ file });14 }15}
