tighten / ziggy

Use your Laravel routes in JavaScript.
MIT License
3.87k stars 247 forks source link

URL For Fallback Needs to be decoded #593

Closed nishpatel closed 1 year ago

nishpatel commented 1 year ago

Ziggy version

1.4.6

Laravel version

v8.83.24

Description

Any fallback URL will need to be decoded e.g.

decodeURIComponent(route('catalog', { fallbackPlaceholder: 'mens/blazers?&filter[material][in][]=169' }));

The issue is without decodeURIComponent the URL would simply go to a 404.

Ziggy call and context

route('catalog', { fallbackPlaceholder: 'mens/blazers?&filter[material][in][]=169' });

Ziggy configuration

{
    "url": "https://ps-headless.test",
    "port": null,
    "defaults": {
        "store": "uk"
    },
    "routes": {
        "root": {
            "uri": "/",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "login": {
            "uri": "{store?}/customer/account/login",
            "methods": [
                "POST"
            ]
        },
        "logout": {
            "uri": "{store?}/customer/account/logout",
            "methods": [
                "POST"
            ]
        },
        "password.reset": {
            "uri": "{store?}/customer/account/reset-password/{token}",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "password.update": {
            "uri": "{store?}/customer/account/reset-password",
            "methods": [
                "POST"
            ]
        },
        "register": {
            "uri": "{store?}/customer/account/register",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "home": {
            "uri": "{store?}",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "customer": {
            "uri": "{store?}/customer/api",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "customer.wishlist.share.view": {
            "uri": "{store?}/wishlist/share/view/{sharingCode}",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "customer.account": {
            "uri": "{store?}/customer/account",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "customer.dashboard-data": {
            "uri": "{store?}/customer/dashboard-data",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "customer.account.edit": {
            "uri": "{store?}/customer/account/edit",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "customer.account.update": {
            "uri": "{store?}/customer/account/edit",
            "methods": [
                "POST"
            ]
        },
        "customer.orders": {
            "uri": "{store?}/customer/orders",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "customer.orders.order": {
            "uri": "{store?}/customer/orders/{orderId}",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "customer.wishlist": {
            "uri": "{store?}/customer/wishlist",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "customer.wishlist.share": {
            "uri": "{store?}/customer/wishlist/share",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "customer.wishlist.share.post": {
            "uri": "{store?}/customer/wishlist/share",
            "methods": [
                "POST"
            ]
        },
        "customer.wishlist.add.product": {
            "uri": "{store?}/customer/wishlist/product/add",
            "methods": [
                "POST"
            ]
        },
        "customer.wishlist.update.product": {
            "uri": "{store?}/customer/wishlist/product/update",
            "methods": [
                "POST"
            ]
        },
        "customer.wishlist.remove.product": {
            "uri": "{store?}/customer/wishlist/product/remove",
            "methods": [
                "POST"
            ]
        },
        "customer.wishlist.cart.add": {
            "uri": "{store?}/customer/wishlist/items/cart/add",
            "methods": [
                "POST"
            ]
        },
        "customer.addresses": {
            "uri": "{store?}/customer/addresses",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "customer.addresses.new": {
            "uri": "{store?}/customer/addresses/new",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "customer.addresses.new.store": {
            "uri": "{store?}/customer/addresses/new",
            "methods": [
                "POST"
            ]
        },
        "customer.addresses.delete": {
            "uri": "{store?}/customer/addresses/delete",
            "methods": [
                "POST"
            ]
        },
        "customer.addresses.edit": {
            "uri": "{store?}/customer/addresses/{addressId}",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "customer.addresses.edit.update": {
            "uri": "{store?}/customer/addresses/{addressId}",
            "methods": [
                "POST"
            ]
        },
        "customer.newsletter": {
            "uri": "{store?}/customer/newsletter",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "customer.newsletter.unsubscribe": {
            "uri": "{store?}/customer/newsletter/unsubscribe",
            "methods": [
                "POST"
            ]
        },
        "customer.newsletter.update": {
            "uri": "{store?}/customer/newsletter/update",
            "methods": [
                "POST"
            ]
        },
        "customer.storecredit": {
            "uri": "{store?}/customer/storecredit",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "checkout.cart": {
            "uri": "{store?}/cart",
            "methods": [
                "POST"
            ]
        },
        "checkout.cart.get": {
            "uri": "{store?}/cart",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "checkout.cart.add.product": {
            "uri": "{store?}/cart/product/add",
            "methods": [
                "POST"
            ]
        },
        "checkout.cart.add.bundle.product": {
            "uri": "{store?}/cart/product/addBundle",
            "methods": [
                "POST"
            ]
        },
        "checkout.cart.update.products": {
            "uri": "{store?}/cart/product/update",
            "methods": [
                "POST"
            ]
        },
        "checkout.cart.remove.product": {
            "uri": "{store?}/cart/product/remove",
            "methods": [
                "POST"
            ]
        },
        "enquiries.returns": {
            "uri": "{store?}/enquiries/returns",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "enquiries.shipping.rates": {
            "uri": "{store?}/enquiries/shippingRates",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "enquiries.types": {
            "uri": "{store?}/enquiries/types",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "enquiries.contact.submit": {
            "uri": "{store?}/enquiries/submit",
            "methods": [
                "POST"
            ]
        },
        "contact.us": {
            "uri": "{store?}/contact-us",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "request.password.reset": {
            "uri": "{store?}/password-reset",
            "methods": [
                "POST"
            ]
        },
        "reset.password": {
            "uri": "{store?}/reset-password",
            "methods": [
                "POST"
            ]
        },
        "newsletter.submit": {
            "uri": "{store?}/newsletter",
            "methods": [
                "POST"
            ]
        },
        "product.oos_notification": {
            "uri": "{store?}/oos-notification",
            "methods": [
                "POST"
            ]
        },
        "product.size_guide": {
            "uri": "{store?}/size-guide",
            "methods": [
                "POST"
            ]
        },
        "product.find_in_shop": {
            "uri": "{store?}/find-in-shop",
            "methods": [
                "POST"
            ]
        },
        "reservation.submit": {
            "uri": "{store?}/reservation",
            "methods": [
                "POST"
            ]
        },
        "product": {
            "uri": "{store?}/product/{sku}/{?data}",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "category": {
            "uri": "{store?}/category/{uid}/{?data}",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "category.merchandised.products": {
            "uri": "{store?}/category/merchandised/products",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "category.product.list": {
            "uri": "{store?}/category/get-product-list",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "category.promo.blocks": {
            "uri": "{store?}/category/get-promo-blocks",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "search.results": {
            "uri": "{store?}/search",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "search.results.products": {
            "uri": "{store?}/search/products",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "shop.list": {
            "uri": "{store?}/stores",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "shop.additional.list": {
            "uri": "{store?}/stores/list",
            "methods": [
                "POST"
            ]
        },
        "shop.view": {
            "uri": "{store?}/stores/{urlKey}",
            "methods": [
                "GET",
                "HEAD"
            ]
        },
        "catalog": {
            "uri": "{store?}/{fallbackPlaceholder}",
            "methods": [
                "GET",
                "HEAD"
            ],
            "wheres": {
                "fallbackPlaceholder": ".*"
            }
        }
    },
    "absolute": true
}

Route definition

//
bakerkretzmar commented 1 year ago

I don't understand what the problem is here exactly. What is happening and what are you expecting to happen instead?

What does route('catalog', { fallbackPlaceholder: 'mens/blazers?&filter[material][in][]=169' }); output?

nishpatel commented 1 year ago

Hi so when you add query params in we are getting this:

https://test.com/uk/mens/blazers%3F%26filter%5Bmaterial%5D%5Bin%5D%5B%5D%3D169'

When you decode you get this:

https://test.com/uk/mens/blazers?&filter[material][in][]=169

Obviously passing the first route will not work if you follow?

bakerkretzmar commented 1 year ago

What is your catalog route definition?

I'm not sure you're using fallback routes correctly—I don't think you would ever actually pass a value into the fallbackPlaceholder parameter. fallbackPlaceholder is injected by Laravel to make it possible to access the URL path inside your fallback route handler:

Route::fallback(function (Request $request, $fallbackPlaceholder) {
    // This route is only run when no other route in the application matches the request
    // E.g. if you don't have a route at `example.com/foo/bar/baz/bing` and it would normally 404,
    // instead you can handle it here, and $fallbackPlaceholder will be 'foo/bar/baz/bing' so that you
    // can figure out where the user intended to go and do something based on that
});

If you're trying to manually direct a user to the exact URL at test.com/uk/mens/blazers?&filter[material][in][]=169 you should do that, using it as a string instead of passing it through Ziggy.

If you're trying to direct them to test.com/uk with a default category of mens/blazers?&filter[material][in][]=169, you should navigate them to test.com/uk and then check for a category value in your controller and set a default there if it's missing.

Is that what you're trying to do and does that make sense?

bakerkretzmar commented 1 year ago

Closing this for now because I don't think it's an issue with Ziggy, but feel free to comment here if you have more info to add or any other questions.