In other frameworks, the concept of request forwarding exists, were a request can be internally redirected to another controller action within the app without responding back to the user with an explicit redirect.
For an ecommerce example, if a product has a SEO-friendly URL of /red-shoes.html
, a request to that URL would internally forward to /catalog/product/id/1234
. The user would receive a 200 response code and the product page for product ID 1234 would be rendered at the original URL of /red-shoes.html
. The behavior I'm trying to avoid is issuing a 301 redirect to /catalog/product/view/id/1234
and losing the friendly URL.
How can this be accomplished in Laravel (5.7)? I can introduce a piece of middleware to intercept the request, but in middleware, I can only redirect within the app. redirect()
sends a 302 back to the user, which I don't want.
namespace App\Http\Middleware;
use Closure;
use App\Rewrite;
class ProductForward
{
public function handle($request, Closure $next)
{
// make a lookup to see if URI in request matches a known product
$productId = Product::lookupRequest($request);
if ($productId) { // if matches, forward to product controller
return redirect()->route('catalog_product', ['id' => $productId]); // not desired
}
// if no match is found, continue on with the request
return $next($request);
}
}
As a follow-up, is it possible to execute this lookup after routing has completed, if no route matches?
For example, assume the route /login
exists to render the login page. If the user goes to /login
, there's no point in looking up a product-friendly URL for this request - just render the login page. But, if the user visits /blue-shoe.html
, and that's not a pre-defined route in Laravel, execute the product lookup and forward after app routing but before a 404 is rendered.