How make slug case insensitive?

Hey folks.

I hope everything is fine with everyone here.

Iā€™m facing an issue with a case sensitive URL match. I can think of 2 possible solutions but I donā€™t know how to implement them on Frontity.

Context: My WordPress has a CPT named ā€œbookā€ (example). All requests to a single book (from Frontity, via REST API) I intercept on WordPress. This interception is to validate if that book exists on the database/CMS. If it doesnā€™t exist, I make a request to an external REST API (from WordPress) to get the basic data from this book and create it in WordPress. The original WordPress REST API request will return the book data (that was just created) to the Frontity application, so the final user always sees a book data even if it didnā€™t exist yet on the WordPress site (the only requirement is the book to exist on the external REST API Iā€™m using).

Issue: If my request (Frontity) is /book/ABC, the request is made with success, the REST API gets the data from the external service/source with success, the post entry is created with success, but Frontity shows a 404 / not found page. I understand this happens because the WordPress URL of this entry is actually /book/abc and not /book/ABC, so Frontity is showing a 404 page (debugging the REST API returned to Frontity, WordPress is doing a case insensitive search - /wp-json/wp/v2/book?_embed=true&slug=ABC returns the same content as /wp-json/wp/v2/book?_embed=true&slug=abc - so I do believe the issue is on Frontity side).

Possible solution #1: Make Frontity redirect all URLs to its own version only with lower case letters: /book/ABC would redirect to /book/abc.

Possible solution #2: Make Frontity recognize the /book/abc entry on WordPress also as /book/ABC (like a case insensitive check on the Frontity side).

But I still donā€™t know how to implement any of these solutions, or even if there is a better one.

If anyone here has any idea how to fix this issue, I will appreciate the support.

Thank you in advance, Fernando

Hi @nandotess85

WordPress slugs are always lowercase so even if you request /book/ABC it will get returned in the JSON as abc and stored in the state in the same way. WordPress adapts the case for slugs internally.

You will probably need to add some logic to your Frontity site to either normalise the case before the request is sent to WordPress, or when you access the data from the state.

Hope this helps. If youā€™re still having the problem then it would be helpful if you could provide a link to a repo so that we can see the code and clone the repo to reproduce the problem.

2 Likes

Hi @mburridge,

Yes, that is exactly what I think. The possible solutions Iā€™m proposing are the ones you mentioned.

At this moment Iā€™m trying to understand/learn how I can implement these options. If you have any doc/example/code that I can see this implemented, I will appreciate it.

Or just give me some technical terms that I can search on Google (if itā€™s something from Frontity, or from React, if itā€™s a component, ā€¦). I will be happy in understanding it, implementing it and sharing here in this post the solution for future developers see the solution.

Thank you so much, Fernando

Hi @nandotess85

Do you have a repo that we can look at so we can see your code? That is something that will assist us in working toward a solution for you.

At the moment Iā€™m not sure where the request URLs are coming from. If it was a link in your site you could determine the case yourself, so Iā€™m guessing that there might be a search box that users can enter the book they want in? I might be completely wrong, hence seeing your code would be helpful.

Hi @mburridge,

Here is the project repo:

Itā€™s a data analytics project for a game. Itā€™s a personal project that Iā€™m using to learn more about Frontity.

There is no search box or anything like that. If you type a user that exists on the data source site/app, on the URL, WordPress is going to fetch the content and create the user automatically.

Example of working URL: https://fortnite.improovement.com/profile/tdk_nandotess/

If you try to access https://fortnite.improovement.com/profile/TDK_nandotess/, which is the real username, Frontity returns 404 even WordPress returns the content.

Thank you, Fernando

Hi @nandotess85

Iā€™ve cloned your repo locally. One thing I noticed was that when you visit https://fortnite.improovement.com/profile/TDK_nandotess/ and you look at frontity.state.source.data in the console you get entries for both /profile/TDK_nandotess/ and for /profile/tdk_nandotess/.

Also, if you check frontity.state.source.profile you have the correct info:

So I tried adding toLowerCase to the get call on line 18 of index.js

const data = state.source.get(state.router.link.toLowerCase());

You may need to do this elsewhere as well, such as line 10 of profile/profile.js.

This didnā€™t completely fix the problem, in that the data didnā€™t display, but it did prevent the 404 from occurring. I didnā€™t dig into the code far enough to figure out how youā€™re displaying the data but this may give you an idea of where you can go to fix this.

Hope this helps, and do please let me know how you get on with this.

1 Like

Thank you so much @mburridge. That is a really helpful insight. I will back to code and start with these steps you have sent me. If I have the luck to fix everything, I will share here the solution. Thanks once again and have a great weekend!

1 Like

Hi @mburridge,

The solution seems, at least itā€™s my perception, on the Frontity side. Anything I do on my side would be a workaround to fix a Frontity ā€œissueā€. But I might be wrong, so let me share here what I have found so you can give me your opinion.

I have fixed the issue changing 3 lines on node_modules/@frontity/wp-source/src/libraries/handlers/postType.ts file.

Line 56
From
if (!state.source.get(route).id || force) {
To
if (!state.source.get(route.toLowerCase()).id || force) {

Line 83 (the key change)
From
if (populated[0].link === route) {
To
if (populated[0].link.toLowerCase() === route.toLowerCase()) {

Line 110
From
const { type, id } = state.source.get(route);
To
const { type, id } = state.source.get(route.toLowerCase());

I donā€™t think this is an elegant solution, since Iā€™m changing over and over the route to lower case. But itā€™s clear to me the main/key issue is on the line 83 where there is a strict condition where WordPress is going to return a route 100% lowercase (/profile/tdk_nandotess/) and Frontity is going to return the route provided by the user on the URL (which can be anything such /profile/tdk_nandotess/ or /profile/TDK_nandotess/).

So my question is: should Frontity compare the routes in a case insensitive way or not? If you think the current condition is correct, itā€™s likely I will need to do a workaround on my project to perform another request for the correct content. I donā€™t feel this is correct since Iā€™m going to always make 2 requests for situations like that (the first one which is a 404 and another one which is the correct one).

Maybe an option on frontity.settings.js for @frontity/wp-source where the developer can decide if the requests are case sensitive or not itā€™s a good solution? Maybeā€¦ Iā€™m sure you guys have the big picture and can let me know if what Iā€™m saying makes sense or not.

Thank you so much, Fernando

Hi @nandotess85

Itā€™s not a good idea to change code in the node_modules folder as they could be over-written next time you run npm i - though Iā€™m sure youā€™re already aware of that.

I think the problem you have is that slugs in WP are always lowercase, but you need to work with the case-sensitive username in case you need to forward it to the external API. If the external API uses the same (lower-case) slugs as the primary WP API then you could convert the slug in the address bar to lowercase before sending. Otherwise I think you will need logic in your theme to handle both case-sensitive username and lowercase slug.

Without knowing anything about the external API that youā€™re querying itā€™s hard to specify exactly what you need to do.

1 Like

Hi @mburridge,

Yes, I know itā€™s not recommended to change anything inside the node_modules. What I did was to test a change on the core of a Fronity component since I do believe itā€™s not an issue on the theme, WordPress or API.

WordPress works with uppercase as well. A quick example from a website Iā€™ve built:

So itā€™s my expectation that Frontity does the same since itā€™s built to work with WordPress.

And just as a reminder, WordPress is returning the data on my situation. Itā€™s not a 404 generated from WordPress. The 404 is from Frontity that is checking the permalink of the post returned versus the route requested on the browser. But itā€™s a === condition, as I have explained in my comment, and I do believe this is the issue. Frontiy should compare the routes forcing the route to be the lower case first before the === condition.

I will move forward knowing this limitation, but I do believe this can be improved on the Frontity core.

Thank you so much for your time answering me. And have a good week!

Best, Fernando

Another idea would be to standardize the route before anything else happens.

node_modules/@frontity/wp-source/src/libraries/route-utils.ts

This also solves the issue. I wonā€™t create a pull-request with this suggestion since Iā€™m not sure what is the best way (best practices) and code patterns I should follow. I probably would ask first a Frontity developerā€™s opinion about this situation.

Thank you, Fernando

Hi @nandotess85

Thatā€™s true, but WP will convert it internally to lowercase for slugs.

Can I suggest you create an issue here. Also take a look at this related issue which you might like to add your own comments to.

I think the problem you have can only be addressed by our Development Team. Meanwhile I guess youā€™ll need to implement a workaround based on our foregoing discussion somewhere in your Frontity theme, or in the code in WP that is handling the intercept.

1 Like

Hi @nandotess85

Here is our documentation page on contributing code in case you want to refer to it.

Do feel free to contribute a PR with your suggestion. The Dev Team will review it and provide you with feedback on best practices, etcā€¦

1 Like

Thanks @mburridge,

I have opened an issue on Github. Iā€™m going to link it here for future community searches.

Thank you once again for your time answering me and all the support provided.

Best, Fernando

2 Likes

Pull-request created with the fix/solution:

Thank you, Fernando

1 Like

Thanks a lot for the contribution @nandotess85

1 Like

Your PR was merged @nandotess85. We let you know once its changes are published. :blush:

1 Like