Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a signedRoute in laravel Lumen API

Tags:

url

laravel

lumen

I am getting an error while using signedRoute from URL facade in laravel Lumen

Call to undefined method Laravel\Lumen\Routing\UrlGenerator::signedRoute()

When i check the URLGenerator class, i can see the functions are there. Is there anything i am doing wrong?

like image 696
hugo411 Avatar asked Oct 20 '25 04:10

hugo411


2 Answers

It isn't possible with a vanilla Lumen. The functions simply don't appear in the source, even if the facade's DocBlock says otherwise.

One option is to extract the functions from the Laravel Framework source (/src/Illuminate/Routing/UrlGenerator.php#L308-L411) into your own UrlGenerator class and bind it:

App\Services\UrlGenerator:

class UrlGenerator extends \Laravel\Lumen\Routing\UrlGenerator
{
    use InteractsWithTime;

    /**
     * The encryption key resolver callable.
     *
     * @var callable
     */
    protected $keyResolver;

    /**
     * Create a signed route URL for a named route.
     *
     * @param  string  $name
     * @param  mixed  $parameters
     * @param  \DateTimeInterface|\DateInterval|int|null  $expiration
     * @param  bool  $absolute
     * @return string
     *
     * @throws \InvalidArgumentException
     */
    public function signedRoute($name, $parameters = [], $expiration = null, $absolute = true)
    {
        $parameters = Arr::wrap($parameters);

        if (array_key_exists('signature', $parameters)) {
            throw new InvalidArgumentException(
                '"Signature" is a reserved parameter when generating signed routes. Please rename your route parameter.'
            );
        }

        if ($expiration) {
            $parameters = $parameters + ['expires' => $this->availableAt($expiration)];
        }

        ksort($parameters);

        $key = call_user_func($this->keyResolver);

        return $this->route($name, $parameters + [
                'signature' => hash_hmac('sha256', $this->route($name, $parameters, $absolute), $key),
            ], $absolute);
    }

    /**
     * Create a temporary signed route URL for a named route.
     *
     * @param  string  $name
     * @param  \DateTimeInterface|\DateInterval|int  $expiration
     * @param  array  $parameters
     * @param  bool  $absolute
     * @return string
     */
    public function temporarySignedRoute($name, $expiration, $parameters = [], $absolute = true)
    {
        return $this->signedRoute($name, $parameters, $expiration, $absolute);
    }

    /**
     * Determine if the given request has a valid signature.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  bool  $absolute
     * @return bool
     */
    public function hasValidSignature(Request $request, $absolute = true)
    {
        return $this->hasCorrectSignature($request, $absolute)
            && $this->signatureHasNotExpired($request);
    }

    /**
     * Determine if the given request has a valid signature for a relative URL.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return bool
     */
    public function hasValidRelativeSignature(Request $request)
    {
        return $this->hasValidSignature($request, false);
    }

    /**
     * Determine if the signature from the given request matches the URL.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  bool  $absolute
     * @return bool
     */
    public function hasCorrectSignature(Request $request, $absolute = true)
    {
        $url = $absolute ? $request->url() : '/'.$request->path();

        $original = rtrim($url.'?'.Arr::query(
                Arr::except($request->query(), 'signature')
            ), '?');

        $signature = hash_hmac('sha256', $original, call_user_func($this->keyResolver));

        return hash_equals($signature, (string) $request->query('signature', ''));
    }

    /**
     * Determine if the expires timestamp from the given request is not from the past.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return bool
     */
    public function signatureHasNotExpired(Request $request)
    {
        $expires = $request->query('expires');

        return ! ($expires && Carbon::now()->getTimestamp() > $expires);
    }

    /**
     * Set the encryption key resolver.
     *
     * @param  callable  $keyResolver
     * @return $this
     */
    public function setKeyResolver(callable $keyResolver)
    {
        $this->keyResolver = $keyResolver;

        return $this;
    }
}

App\Providers\AppServiceProvider:

$this->app->bind(\App\Services\UrlGenerator::class, function () {
    $urlGeneratorWithSignedRoutes = new \App\Services\UrlGenerator($this->app);

    $urlGeneratorWithSignedRoutes->setKeyResolver(function () {
        return $this->app->make('config')->get('app.key');
    });

    return $urlGeneratorWithSignedRoutes;
});
like image 116
Freshleaf Media Avatar answered Oct 23 '25 02:10

Freshleaf Media


Everything as Freshleaf Media wrote, but instead of class binding, added url singleton (Lument 5.8).

        $this->app->singleton('url', function () {
            $urlGeneratorWithSignedRoutes = new \App\Services\UrlGenerator($this->app);

            $urlGeneratorWithSignedRoutes->setKeyResolver(function () {
                return $this->app->make('config')->get('app.key');
            });

            return $urlGeneratorWithSignedRoutes;
        });
like image 22
Simonas D. Avatar answered Oct 23 '25 03:10

Simonas D.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!