# HTTP Responses
* Creating Responses
* Attaching Headers to Responses
* Attaching Cookies to Responses
* Cookies and Encryption
* Redirects
* Redirecting to Named Routes
* Redirecting to Controller Actions
* Redirecting to External Domains
* Redirecting With Flashed Session Data
* Other Response Types
* View Responses
* JSON Responses
* File Downloads
* File Responses
* Streamed Responses
* Consuming Streamed Responses
* Streamed JSON Responses
* Event Streams (SSE)
* Streamed Downloads
* Response Macros
## Creating Responses
#### Strings and Arrays
All routes and controllers should return a response to be sent back to the
user's browser. Laravel provides several different ways to return responses.
The most basic response is returning a string from a route or controller. The
framework will automatically convert the string into a full HTTP response:
1Route::get('/', function () {
2 return 'Hello World';
3});
Route::get('/', function () {
return 'Hello World';
});
In addition to returning strings from your routes and controllers, you may
also return arrays. The framework will automatically convert the array into a
JSON response:
1Route::get('/', function () {
2 return [1, 2, 3];
3});
Route::get('/', function () {
return [1, 2, 3];
});
Did you know you can also return [Eloquent collections](/docs/12.x/eloquent-
collections) from your routes or controllers? They will automatically be
converted to JSON. Give it a shot!
#### Response Objects
Typically, you won't just be returning simple strings or arrays from your
route actions. Instead, you will be returning full `Illuminate\Http\Response`
instances or [views](/docs/12.x/views).
Returning a full `Response` instance allows you to customize the response's
HTTP status code and headers. A `Response` instance inherits from the
`Symfony\Component\HttpFoundation\Response` class, which provides a variety of
methods for building HTTP responses:
1Route::get('/home', function () {
2 return response('Hello World', 200)
3 ->header('Content-Type', 'text/plain');
4});
Route::get('/home', function () {
return response('Hello World', 200)
->header('Content-Type', 'text/plain');
});
#### Eloquent Models and Collections
You may also return [Eloquent ORM](/docs/12.x/eloquent) models and collections
directly from your routes and controllers. When you do, Laravel will
automatically convert the models and collections to JSON responses while
respecting the model's [hidden attributes](/docs/12.x/eloquent-
serialization#hiding-attributes-from-json):
1use App\Models\User;
2
3Route::get('/user/{user}', function (User $user) {
4 return $user;
5});
use App\Models\User;
Route::get('/user/{user}', function (User $user) {
return $user;
});
### Attaching Headers to Responses
Keep in mind that most response methods are chainable, allowing for the fluent
construction of response instances. For example, you may use the `header`
method to add a series of headers to the response before sending it back to
the user:
1return response($content)
2 ->header('Content-Type', $type)
3 ->header('X-Header-One', 'Header Value')
4 ->header('X-Header-Two', 'Header Value');
return response($content)
->header('Content-Type', $type)
->header('X-Header-One', 'Header Value')
->header('X-Header-Two', 'Header Value');
Or, you may use the `withHeaders` method to specify an array of headers to be
added to the response:
1return response($content)
2 ->withHeaders([
3 'Content-Type' => $type,
4 'X-Header-One' => 'Header Value',
5 'X-Header-Two' => 'Header Value',
6 ]);
return response($content)
->withHeaders([
'Content-Type' => $type,
'X-Header-One' => 'Header Value',
'X-Header-Two' => 'Header Value',
]);
#### Cache Control Middleware
Laravel includes a `cache.headers` middleware, which may be used to quickly
set the `Cache-Control` header for a group of routes. Directives should be
provided using the "snake case" equivalent of the corresponding cache-control
directive and should be separated by a semicolon. If `etag` is specified in
the list of directives, an MD5 hash of the response content will automatically
be set as the ETag identifier:
1Route::middleware('cache.headers:public;max_age=2628000;etag')->group(function () {
2 Route::get('/privacy', function () {
3 // ...
4 });
5
6 Route::get('/terms', function () {
7 // ...
8 });
9});
Route::middleware('cache.headers:public;max_age=2628000;etag')->group(function () {
Route::get('/privacy', function () {
// ...
});
Route::get('/terms', function () {
// ...
});
});
### Attaching Cookies to Responses
You may attach a cookie to an outgoing `Illuminate\Http\Response` instance
using the `cookie` method. You should pass the name, value, and the number of
minutes the cookie should be considered valid to this method:
1return response('Hello World')->cookie(
2 'name', 'value', $minutes
3);
return response('Hello World')->cookie(
'name', 'value', $minutes
);
The `cookie` method also accepts a few more arguments which are used less
frequently. Generally, these arguments have the same purpose and meaning as
the arguments that would be given to PHP's native
[setcookie](https://secure.php.net/manual/en/function.setcookie.php) method:
1return response('Hello World')->cookie(
2 'name', 'value', $minutes, $path, $domain, $secure, $httpOnly
3);
return response('Hello World')->cookie(
'name', 'value', $minutes, $path, $domain, $secure, $httpOnly
);
If you would like to ensure that a cookie is sent with the outgoing response
but you do not yet have an instance of that response, you can use the `Cookie`
facade to "queue" cookies for attachment to the response when it is sent. The
`queue` method accepts the arguments needed to create a cookie instance. These
cookies will be attached to the outgoing response before it is sent to the
browser:
1use Illuminate\Support\Facades\Cookie;
2
3Cookie::queue('name', 'value', $minutes);
use Illuminate\Support\Facades\Cookie;
Cookie::queue('name', 'value', $minutes);
#### Generating Cookie Instances
If you would like to generate a `Symfony\Component\HttpFoundation\Cookie`
instance that can be attached to a response instance at a later time, you may
use the global `cookie` helper. This cookie will not be sent back to the
client unless it is attached to a response instance:
1$cookie = cookie('name', 'value', $minutes);
2
3return response('Hello World')->cookie($cookie);
$cookie = cookie('name', 'value', $minutes);
return response('Hello World')->cookie($cookie);
#### Expiring Cookies Early
You may remove a cookie by expiring it via the `withoutCookie` method of an
outgoing response:
1return response('Hello World')->withoutCookie('name');
return response('Hello World')->withoutCookie('name');
If you do not yet have an instance of the outgoing response, you may use the
`Cookie` facade's `expire` method to expire a cookie:
1Cookie::expire('name');
Cookie::expire('name');
### Cookies and Encryption
By default, thanks to the `Illuminate\Cookie\Middleware\EncryptCookies`
middleware, all cookies generated by Laravel are encrypted and signed so that
they can't be modified or read by the client. If you would like to disable
encryption for a subset of cookies generated by your application, you may use
the `encryptCookies` method in your application's `bootstrap/app.php` file:
1->withMiddleware(function (Middleware $middleware) {
2 $middleware->encryptCookies(except: [
3 'cookie_name',
4 ]);
5})
->withMiddleware(function (Middleware $middleware) {
$middleware->encryptCookies(except: [
'cookie_name',
]);
})
## Redirects
Redirect responses are instances of the `Illuminate\Http\RedirectResponse`
class, and contain the proper headers needed to redirect the user to another
URL. There are several ways to generate a `RedirectResponse` instance. The
simplest method is to use the global `redirect` helper:
1Route::get('/dashboard', function () {
2 return redirect('/home/dashboard');
3});
Route::get('/dashboard', function () {
return redirect('/home/dashboard');
});
Sometimes you may wish to redirect the user to their previous location, such
as when a submitted form is invalid. You may do so by using the global `back`
helper function. Since this feature utilizes the
[session](/docs/12.x/session), make sure the route calling the `back` function
is using the `web` middleware group:
1Route::post('/user/profile', function () {
2 // Validate the request...
3
4 return back()->withInput();
5});
Route::post('/user/profile', function () {
// Validate the request...
return back()->withInput();
});
### Redirecting to Named Routes
When you call the `redirect` helper with no parameters, an instance of
`Illuminate\Routing\Redirector` is returned, allowing you to call any method
on the `Redirector` instance. For example, to generate a `RedirectResponse` to
a named route, you may use the `route` method:
1return redirect()->route('login');
return redirect()->route('login');
If your route has parameters, you may pass them as the second argument to the
`route` method:
1// For a route with the following URI: /profile/{id}
2
3return redirect()->route('profile', ['id' => 1]);
// For a route with the following URI: /profile/{id}
return redirect()->route('profile', ['id' => 1]);
#### Populating Parameters via Eloquent Models
If you are redirecting to a route with an "ID" parameter that is being
populated from an Eloquent model, you may pass the model itself. The ID will
be extracted automatically:
1// For a route with the following URI: /profile/{id}
2
3return redirect()->route('profile', [$user]);
// For a route with the following URI: /profile/{id}
return redirect()->route('profile', [$user]);
If you would like to customize the value that is placed in the route
parameter, you can specify the column in the route parameter definition
(`/profile/{id:slug}`) or you can override the `getRouteKey` method on your
Eloquent model:
1/**
2 * Get the value of the model's route key.
3 */
4public function getRouteKey(): mixed
5{
6 return $this->slug;
7}
/**
* Get the value of the model's route key.
*/
public function getRouteKey(): mixed
{
return $this->slug;
}
### Redirecting to Controller Actions
You may also generate redirects to [controller
actions](/docs/12.x/controllers). To do so, pass the controller and action
name to the `action` method:
1use App\Http\Controllers\UserController;
2
3return redirect()->action([UserController::class, 'index']);
use App\Http\Controllers\UserController;
return redirect()->action([UserController::class, 'index']);
If your controller route requires parameters, you may pass them as the second
argument to the `action` method:
1return redirect()->action(
2 [UserController::class, 'profile'], ['id' => 1]
3);
return redirect()->action(
[UserController::class, 'profile'], ['id' => 1]
);
### Redirecting to External Domains
Sometimes you may need to redirect to a domain outside of your application.
You may do so by calling the `away` method, which creates a `RedirectResponse`
without any additional URL encoding, validation, or verification:
1return redirect()->away('https://www.google.com');
return redirect()->away('https://www.google.com');
### Redirecting With Flashed Session Data
Redirecting to a new URL and [flashing data to the
session](/docs/12.x/session#flash-data) are usually done at the same time.
Typically, this is done after successfully performing an action when you flash
a success message to the session. For convenience, you may create a
`RedirectResponse` instance and flash data to the session in a single, fluent
method chain:
1Route::post('/user/profile', function () {
2 // ...
3
4 return redirect('/dashboard')->with('status', 'Profile updated!');
5});
Route::post('/user/profile', function () {
// ...
return redirect('/dashboard')->with('status', 'Profile updated!');
});
After the user is redirected, you may display the flashed message from the
[session](/docs/12.x/session). For example, using [Blade
syntax](/docs/12.x/blade):
1@if (session('status'))
2
3 {{ session('status') }}
4
5@endif
@if (session('status'))
{{ session('status') }}
@endif
#### Redirecting With Input
You may use the `withInput` method provided by the `RedirectResponse` instance
to flash the current request's input data to the session before redirecting
the user to a new location. This is typically done if the user has encountered
a validation error. Once the input has been flashed to the session, you may
easily [retrieve it](/docs/12.x/requests#retrieving-old-input) during the next
request to repopulate the form:
1return back()->withInput();
return back()->withInput();
## Other Response Types
The `response` helper may be used to generate other types of response
instances. When the `response` helper is called without arguments, an
implementation of the `Illuminate\Contracts\Routing\ResponseFactory`
[contract](/docs/12.x/contracts) is returned. This contract provides several
helpful methods for generating responses.
### View Responses
If you need control over the response's status and headers but also need to
return a [view](/docs/12.x/views) as the response's content, you should use
the `view` method:
1return response()
2 ->view('hello', $data, 200)
3 ->header('Content-Type', $type);
return response()
->view('hello', $data, 200)
->header('Content-Type', $type);
Of course, if you do not need to pass a custom HTTP status code or custom
headers, you may use the global `view` helper function.
### JSON Responses
The `json` method will automatically set the `Content-Type` header to
`application/json`, as well as convert the given array to JSON using the
`json_encode` PHP function:
1return response()->json([
2 'name' => 'Abigail',
3 'state' => 'CA',
4]);
return response()->json([
'name' => 'Abigail',
'state' => 'CA',
]);
If you would like to create a JSONP response, you may use the `json` method in
combination with the `withCallback` method:
1return response()
2 ->json(['name' => 'Abigail', 'state' => 'CA'])
3 ->withCallback($request->input('callback'));
return response()
->json(['name' => 'Abigail', 'state' => 'CA'])
->withCallback($request->input('callback'));
### File Downloads
The `download` method may be used to generate a response that forces the
user's browser to download the file at the given path. The `download` method
accepts a filename as the second argument to the method, which will determine
the filename that is seen by the user downloading the file. Finally, you may
pass an array of HTTP headers as the third argument to the method:
1return response()->download($pathToFile);
2
3return response()->download($pathToFile, $name, $headers);
return response()->download($pathToFile);
return response()->download($pathToFile, $name, $headers);
Symfony HttpFoundation, which manages file downloads, requires the file being
downloaded to have an ASCII filename.
### File Responses
The `file` method may be used to display a file, such as an image or PDF,
directly in the user's browser instead of initiating a download. This method
accepts the absolute path to the file as its first argument and an array of
headers as its second argument:
1return response()->file($pathToFile);
2
3return response()->file($pathToFile, $headers);
return response()->file($pathToFile);
return response()->file($pathToFile, $headers);
## Streamed Responses
By streaming data to the client as it is generated, you can significantly
reduce memory usage and improve performance, especially for very large
responses. Streamed responses allow the client to begin processing data before
the server has finished sending it:
1Route::get('/stream', function () {
2 return response()->stream(function (): void {
3 foreach (['developer', 'admin'] as $string) {
4 echo $string;
5 ob_flush();
6 flush();
7 sleep(2); // Simulate delay between chunks...
8 }
9 }, 200, ['X-Accel-Buffering' => 'no']);
10});
Route::get('/stream', function () {
return response()->stream(function (): void {
foreach (['developer', 'admin'] as $string) {
echo $string;
ob_flush();
flush();
sleep(2); // Simulate delay between chunks...
}
}, 200, ['X-Accel-Buffering' => 'no']);
});
For convenience, if the closure you provide to the `stream` method returns a
[Generator](https://www.php.net/manual/en/language.generators.overview.php),
Laravel will automatically flush the output buffer between strings returned by
the generator, as well as disable Nginx output buffering:
1Route::post('/chat', function () {
2 return response()->stream(function (): Generator {
3 $stream = OpenAI::client()->chat()->createStreamed(...);
4
5 foreach ($stream as $response) {
6 yield $response->choices[0];
7 }
8 });
9});
Route::post('/chat', function () {
return response()->stream(function (): Generator {
$stream = OpenAI::client()->chat()->createStreamed(...);
foreach ($stream as $response) {
yield $response->choices[0];
}
});
});
### Consuming Streamed Responses
Streamed responses may be consumed using Laravel's `stream` npm package, which
provides a convenient API for interacting with Laravel response and event
streams. To get started, install the `@laravel/stream-react` or
`@laravel/stream-vue` package:
React Vue
1npm install @laravel/stream-react
npm install @laravel/stream-react
1npm install @laravel/stream-vue
npm install @laravel/stream-vue
Then, `useStream` may be used to consume the event stream. After providing
your stream URL, the hook will automatically update the `data` with the
concatenated response as content is returned from your Laravel application:
React Vue
1import { useStream } from "@laravel/stream-react";
2
3function App() {
4 const { data, isFetching, isStreaming, send } = useStream("chat");
5
6 const sendMessage = () => {
7 send({
8 message: `Current timestamp: ${Date.now()}`,
9 });
10 };
11
12 return (
13
When sending data back to the stream via `send`, the active connection to the
stream is canceled before sending the new data. All requests are sent as JSON
`POST` requests.
Since the `useStream` hook makes a `POST` request to your application, a valid
CSRF token is required. The easiest way to provide the CSRF token is to
[include it via a meta tag in your application layout's
head](/docs/12.x/csrf#csrf-x-csrf-token).
The second argument given to `useStream` is an options object that you may use
to customize the stream consumption behavior. The default values for this
object are shown below:
React Vue
1import { useStream } from "@laravel/stream-react";
2
3function App() {
4 const { data } = useStream("chat", {
5 id: undefined,
6 initialInput: undefined,
7 headers: undefined,
8 csrfToken: undefined,
9 onResponse: (response: Response) => void,
10 onData: (data: string) => void,
11 onCancel: () => void,
12 onFinish: () => void,
13 onError: (error: Error) => void,
14 });
15
16 return
`onResponse` is triggered after a successful initial response from the stream
and the raw [Response](https://developer.mozilla.org/en-
US/docs/Web/API/Response) is passed to the callback. `onData` is called as
each chunk is received - the current chunk is passed to the callback.
`onFinish` is called when a stream has finished and when an error is thrown
during the fetch / read cycle.
By default, a request is not made to the stream on initialization. You may
pass an initial payload to the stream by using the `initialInput` option:
React Vue
1import { useStream } from "@laravel/stream-react";
2
3function App() {
4 const { data } = useStream("chat", {
5 initialInput: {
6 message: "Introduce yourself.",
7 },
8 });
9
10 return
{data}
;
11}
import { useStream } from "@laravel/stream-react";
function App() {
const { data } = useStream("chat", {
initialInput: {
message: "Introduce yourself.",
},
});
return
{data}
;
}
1
10
11
12
{{ data }}
13
{{ data }}
To cancel a stream manually, you may use the `cancel` method returned from the
hook:
React Vue
1import { useStream } from "@laravel/stream-react";
2
3function App() {
4 const { data, cancel } = useStream("chat");
5
6 return (
7
Each time the `useStream` hook is used, a random `id` is generated to identify
the stream. This is sent back to the server with each request in the
`X-STREAM-ID` header. When consuming the same stream from multiple components,
you can read and write to the stream by providing your own `id`:
React Vue
1// App.tsx
2import { useStream } from "@laravel/stream-react";
3
4function App() {
5 const { data, id } = useStream("chat");
6
7 return (
8
26 );
27}
// App.tsx
import { useStream } from "@laravel/stream-react";
function App() {
const { data, id } = useStream("chat");
return (
{data}
);
}
// StreamStatus.tsx
import { useStream } from "@laravel/stream-react";
function StreamStatus({ id }) {
const { isFetching, isStreaming } = useStream("chat", { id });
return (
{isFetching &&
Connecting...
}
{isStreaming &&
Generating...
}
);
}
1
2
8
9
10
11
{{ data }}
12
13
14
15
16
17
26
27
28
29
Connecting...
30
Generating...
31
32
{{ data }}
Connecting...
Generating...
### Streamed JSON Responses
If you need to stream JSON data incrementally, you may utilize the
`streamJson` method. This method is especially useful for large datasets that
need to be sent progressively to the browser in a format that can be easily
parsed by JavaScript:
1use App\Models\User;
2
3Route::get('/users.json', function () {
4 return response()->streamJson([
5 'users' => User::cursor(),
6 ]);
7});
use App\Models\User;
Route::get('/users.json', function () {
return response()->streamJson([
'users' => User::cursor(),
]);
});
The `useJsonStream` hook is identical to the useStream hook except that it
will attempt to parse the data as JSON once it has finished streaming:
React Vue
1import { useJsonStream } from "@laravel/stream-react";
2
3type User = {
4 id: number;
5 name: string;
6 email: string;
7};
8
9function App() {
10 const { data, send } = useJsonStream<{ users: User[] }>("users");
11
12 const loadUsers = () => {
13 send({
14 query: "taylor",
15 });
16 };
17
18 return (
19
### Event Streams (SSE)
The `eventStream` method may be used to return a server-sent events (SSE)
streamed response using the `text/event-stream` content type. The
`eventStream` method accepts a closure which should
[yield](https://www.php.net/manual/en/language.generators.overview.php)
responses to the stream as the responses become available:
1Route::get('/chat', function () {
2 return response()->eventStream(function () {
3 $stream = OpenAI::client()->chat()->createStreamed(...);
4
5 foreach ($stream as $response) {
6 yield $response->choices[0];
7 }
8 });
9});
Route::get('/chat', function () {
return response()->eventStream(function () {
$stream = OpenAI::client()->chat()->createStreamed(...);
foreach ($stream as $response) {
yield $response->choices[0];
}
});
});
If you would like to customize the name of the event, you may yield an
instance of the `StreamedEvent` class:
1use Illuminate\Http\StreamedEvent;
2
3yield new StreamedEvent(
4 event: 'update',
5 data: $response->choices[0],
6);
use Illuminate\Http\StreamedEvent;
yield new StreamedEvent(
event: 'update',
data: $response->choices[0],
);
#### Consuming Event Streams
Event streams may be consumed using Laravel's `stream` npm package, which
provides a convenient API for interacting with Laravel event streams. To get
started, install the `@laravel/stream-react` or `@laravel/stream-vue` package:
React Vue
1npm install @laravel/stream-react
npm install @laravel/stream-react
1npm install @laravel/stream-vue
npm install @laravel/stream-vue
Then, `useEventStream` may be used to consume the event stream. After
providing your stream URL, the hook will automatically update the `message`
with the concatenated response as messages are returned from your Laravel
application:
React Vue
1import { useEventStream } from "@laravel/stream-react";
2
3function App() {
4 const { message } = useEventStream("/chat");
5
6 return
{message}
;
7}
import { useEventStream } from "@laravel/stream-react";
function App() {
const { message } = useEventStream("/chat");
return
{message}
;
}
1
6
7
8
{{ message }}
9
{{ message }}
The second argument given to `useEventStream` is an options object that you
may use to customize the stream consumption behavior. The default values for
this object are shown below:
React Vue
1import { useEventStream } from "@laravel/stream-react";
2
3function App() {
4 const { message } = useEventStream("/stream", {
5 eventName: "update",
6 onMessage: (message) => {
7 //
8 },
9 onError: (error) => {
10 //
11 },
12 onComplete: () => {
13 //
14 },
15 endSignal: "",
16 glue: " ",
17 });
18
19 return
;
}
1
Event streams may also be manually consumed via an
[EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource)
object by your application's frontend. The `eventStream` method will
automatically send a `` update to the event stream when the stream is
complete:
1const source = new EventSource('/chat');
2
3source.addEventListener('update', (event) => {
4 if (event.data === '') {
5 source.close();
6
7 return;
8 }
9
10 console.log(event.data);
11});
const source = new EventSource('/chat');
source.addEventListener('update', (event) => {
if (event.data === '') {
source.close();
return;
}
console.log(event.data);
});
To customize the final event that is sent to the event stream, you may provide
a `StreamedEvent` instance to the `eventStream` method's `endStreamWith`
argument:
1return response()->eventStream(function () {
2 // ...
3}, endStreamWith: new StreamedEvent(event: 'update', data: ''));
return response()->eventStream(function () {
// ...
}, endStreamWith: new StreamedEvent(event: 'update', data: ''));
### Streamed Downloads
Sometimes you may wish to turn the string response of a given operation into a
downloadable response without having to write the contents of the operation to
disk. You may use the `streamDownload` method in this scenario. This method
accepts a callback, filename, and an optional array of headers as its
arguments:
1use App\Services\GitHub;
2
3return response()->streamDownload(function () {
4 echo GitHub::api('repo')
5 ->contents()
6 ->readme('laravel', 'laravel')['contents'];
7}, 'laravel-readme.md');
use App\Services\GitHub;
return response()->streamDownload(function () {
echo GitHub::api('repo')
->contents()
->readme('laravel', 'laravel')['contents'];
}, 'laravel-readme.md');
## Response Macros
If you would like to define a custom response that you can re-use in a variety
of your routes and controllers, you may use the `macro` method on the
`Response` facade. Typically, you should call this method from the `boot`
method of one of your application's [service providers](/docs/12.x/providers),
such as the `App\Providers\AppServiceProvider` service provider:
1caps('foo');
return response()->caps('foo');