1

The user friendly URLs should be hyphened, for example:

http://example.com/some-category/some-file

My inherited folder structure however, is pascal cased, therefore the rewritten URL should look like this:

http://example.com/SomeCategory/SomeFile.php

Note: The amount of words in a category or file name will vary, so don't expect consistency in that way. ex. http://example.com/some-long-category/file.

Im wondering how to do this, with a general rewrite condition-rule pair for any category and file, using Apache's mod_rewrite.

You can test your rules here, without the need to setup an Apache server.

undefined
  • 3,949
  • 4
  • 26
  • 38

2 Answers2

1

Note that the question has been updated since this answer was written, and did not originally state that it is not a consistent format - this answer covers word-word/word-word

This part needs to be in your main server config, at root level or in the <VirtualHost>:

RewriteEngine on
RewriteMap uc int:toupper

Then this in your .htaccess:

RewriteEngine on
RewriteRule ([a-z])([a-z]*)-([a-z])([a-z]*)/([a-z])([a-z]*)-([a-z])([a-z]*) %{uc:$1}$2%{uc:$3}$4/%{uc:$5}$6%{uc:$7}$8.php

I believe the rewrite engine does not need to be on in the first one, but have put it in to be sure. I will leave the testing to you. I've done more than enough of the work! Can't test it there anyway as it needs the first part setting up.

It will redirect single letters in any of the four word positions. Assume all are the same format, two words using a to z only separated by one hyphen.

If you don't have access to the main server config then I suggest running a script to rename your files instead, making the names all lowercase at least. It's not possible without the RewriteMap and that has to go in the main config.

Ref:

Community
  • 1
  • 1
  • I'm so sorry, maybe I wasn't clear, the problem is that they won't be in the same format everytime. Therefore sometimes an URL may look like `http://example.com/some-very-long-category/file` – undefined Jan 11 '17 at 03:44
  • I honestly woudn't know, is it absolutely necessary? Is there another method that can programatically change the URL without needing the exact number of possibilities? – undefined Jan 11 '17 at 03:47
  • I'll get back to you. –  Jan 11 '17 at 03:51
  • If it's impossible, then i guess between zero and three hyphens should be enough. Still, it feels like a patch. – undefined Jan 11 '17 at 04:32
  • I have a solution covering unlimited words, just writing it up now. –  Jan 11 '17 at 04:35
1

I decided that adding another answer for the updated question made most sense, since my original answer may be useful for someone and is a valid approach as the question was originally stated.

mod_rewrite, as I understand it, loops until the URL is not altered, so we should be able to use that to loop until every word is changed. Here's the code.

This part needs to be in your main server config, at root level or in the <VirtualHost>:

RewriteEngine on
RewriteMap uc int:toupper

Then this in your .htaccess:

RewriteEngine on
RewriteRule (.*)(?:^|-|(/))([a-z])([a-z]*)(?![a-z])(.*?)(?:\.php)?$ $1$2${uc:$3}$4$5.php

That should do it. Please try it and let me know results.

As discovered in the comments, there is a default limit of 10 iterations, which means ten words limit. If you need to match more than ten words then you can increase the LimitInternalRecursion directive as appropriate.

Note: The many comments below are mostly concerned with testing and tweaking until it worked, which it does. Although it then turned out that bare directories need to be matched too. A problem for another day, and perhaps another question!

  • Updated a couple of times since posting so please check you're testing the latest version. –  Jan 11 '17 at 04:49
  • Unfortunately it gives me an Internal Server Error, using XAMPP, i've put the first lines in the httpd.conf (and then reset the server), and the other ones in the websites root folder. Tested with a folder named `TheAudio`, a file inside it called `TheFile.php` and a URL `/the-audio/the-file`. – undefined Jan 11 '17 at 05:00
  • It needs updating, there's a problem. Would be interested to know what the log files show for the server error though? –  Jan 11 '17 at 05:01
  • Yes, sorry, only this: `[Wed Jan 11 02:02:26.208365 2017] [core:error] [pid 7904:tid 1888] [client ::1:53379] AH00124: Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.` So i'm guessing there is an infinite recursion problem. – undefined Jan 11 '17 at 05:03
  • Yep, great, thanks. Confirms what I thought. Have updated it, please try again. It wasn't infinite, but it was uppercasing every letter one at a time. –  Jan 11 '17 at 05:06
  • Still, same error, to anyone who reads this in the future, please, never name files with PascalCase. – undefined Jan 11 '17 at 05:12
  • If you want to cover more than ten words (or perhaps nine) you will need to increase LimitInternalRecursion to words+1. –  Jan 11 '17 at 05:12
  • Can we do a "LogLevel rewrite:trace3" and get some info? Sorry this is right at the limit of my skills, will test on my server if not resolved soon. –  Jan 11 '17 at 05:13
  • I understand, here's a [**log**](http://pastebin.com/ER0mBnYm) with trace3, it appears as though it appends a lot of .php extensions. – undefined Jan 11 '17 at 05:18
  • Thanks. Ok one last try for this evening, that's the limit of my attempts without testing at my end. Have updated it just now. –  Jan 11 '17 at 05:22
  • Nope, here's the [**trace**](http://pastebin.com/7F8R1mK0). Thanks anyways, you've done way more than enough already, I'm going to keep at it and if I find a solution I'll make sure to let you in on it. – undefined Jan 11 '17 at 05:25
  • Actually looking at the log, the uppercasing isn't working. The replacement is blank instead of the uppercased letter. Is the RewriteMap in the main server config? –  Jan 11 '17 at 05:25
  • Ok thanks. You could just change the file names with a script for an easier solution. One time deal. Or RewriteMap can run through a script to do the job. I'll play with this again tomorrow though if you don't solve it. –  Jan 11 '17 at 05:28
  • That last log looks good if only the uppercasing was working it should do it. –  Jan 11 '17 at 05:30
  • It's in the apache *httpd.conf* file, am I wrong there? Honestly I know very little of server configuration. Here's a [**snippet**](http://imgur.com/a/uYx3i). (That would be the bottom of the file) – undefined Jan 11 '17 at 05:31
  • That looks good. Looks like it was me, a syntax error on the use of the rewritemap in the rule (was using % instead of $). Please try again, looking good now hopefully. –  Jan 11 '17 at 05:35
  • Don't forget to take that rewrite:trace3 logging out again when finished it will slow the server. –  Jan 11 '17 at 05:37
  • Nice work man! It works perfectly for file access. However (and obviously it wasn't intended to do so) it doesn't work for accesing just the directory, without a file, is there an easy fix, maybe another, shorter rule for handling directories? – undefined Jan 11 '17 at 05:40
  • Great stuff! Pleased to hear it. Let me think on the directories issue. –  Jan 11 '17 at 05:41
  • The problem with the directories must be just the adding of .php I think? Can we get a trace? –  Jan 11 '17 at 05:44
  • Yes, [**looks like it**](http://pastebin.com/isFBMd13), I'm guessing I'll need a separate rule for this cases, where there's no need for appending the .php extension. If so, I'll need a condition or filter rule. – undefined Jan 11 '17 at 05:48
  • Tweaked a few times. –  Jan 11 '17 at 05:54
  • Alright, a few problems with that approach. First, it doesn't work with `/the-audio` (notice no trailing slash), and second, it changes the url in the browser to `TheAudio`, instead of `the-audio`. Finally, if you look at the [**trace**](http://pastebin.com/tfQuSWG4) it seems like it's iterating a large amount of times, finding the index.php (Ups, commented before last tweaks) – undefined Jan 11 '17 at 05:55
  • Unfortunately now it doesn't work, here's a [**trace**](http://pastebin.com/uu2BU8zL) (bet you're getting tired of those, it's fine if you want to stop). Again, looks fairly large and over-iterated. – undefined Jan 11 '17 at 05:58
  • Yeah if it worked I was going to say I really didn't like it as a solution for the iterations and many file system tests. Think I need to look at this tomorrow now. Got the posted problem solved anyway. This directory issue changes things and needs thinking about. If you could accept my answer and perhaps vote both answers up it would be much appreciated! Will think on this for tomorrow. –  Jan 11 '17 at 06:02
  • Thanks, no problem at all. Glad we got the main piece working. Thanks for all the traces etc. Was a fun problem to solve. Too tired to think further now! –  Jan 11 '17 at 06:08
  • Can I ask you to post another question with the directory problem? I suggest you post your current code, describe the problem with the directories and perhaps link to this question for reference. I will then look at that tomorrow and someone else may solve it anyway. –  Jan 11 '17 at 06:26
  • I have a solution for the directory issue for you, but it will be much better in a new question to house the questions I have, any testing and not complicate this one that is complete. Let me know if you still need assistance with that and I can look at it. –  Jan 12 '17 at 01:00
  • I'll get right on it, however i've decided on running a script to normalize file names, because of the huge amount of processing the server would have to make on each request. However, I'm facing [**another challenge**](http://stackoverflow.com/questions/41603578/apaches-mod-rewrite-failing-to-remove-trailing-slash), perhaps you could help – undefined Jan 12 '17 at 01:17
  • Well don't worry about it if you don't need it. A few iterations of the rewrites is not a big concern, it's all very low level operations and well optimised. But yes, normalising the file names would be my approach. I can perhaps help you with a Perl script for that if you need assistance. Just ask the question! :) –  Jan 12 '17 at 01:27