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