Forum Moderators: phranque

Message Too Old, No Replies

URL construction

adding characters

         

montesano

7:23 am on Dec 10, 2011 (gmt 0)

10+ Year Member



Hi, I have urls that look like 'mysite.com/48YSWD96', however I need to be able to write them as urls that look like 'mysite.com/?d=48YSWD96' and still have them go to the same place. My .htaccess code looks like this:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^([^/]+)/$ $1.php
RewriteRule ^([^/]+)/([^/]+)/$ /$1/$2.php

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule (.*)$ /$1/ [R=301,L]
RewriteBase /

I hope that was clear. What do I need to add? any help is much appreciated, thanks.

[edited by: engine at 11:29 am (utc) on Dec 16, 2011]

g1smd

7:54 am on Dec 10, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Why do you want to move from using clean and simple URLs to using parameters in the URLs?

It's not so much what you add, as what you delete. You will need to destroy the rewrites you already have, and with it all the benefits of using simple URLs. You'll also need to add a redirect so that requests for the old URL are redirected to the new one.

If you're moving from static files to a new dynamic system, you can quite easily retain the same URLs out there on the web by altering the rewrites instead of deleting them. This would have many benefits, not least that there would be no break in indexing and ranking.

lucy24

9:04 am on Dec 10, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Ouch.

RewriteBase, if needed, goes at the very beginning, right after RewriteEngine On. Since / is the default, you don't need it.

Leave a blank line after each Rule. In the case of your example rules, this helps emphasize that Rule #2-- the one ending in /$1/$2.php --is a freestanding, conditionless rule, with no connection to Rule #1. But they can easily be collapsed into a single Rule if you want the Conditions to apply to both:

RewriteRule ^([^/]+(/[^/]+)?)/$ /$1.php

Replace the ? with a * if you want to allow for any number of subdirectories. Put a [L] flag at the end of each Rule unless you've got a clear and specific reason not to.

Is your last Condition intended to mean requests for extentionless URLs? That is, neither .bzt nor / ? You can put this requirement into the Rule itself:

RewriteRule ^([^.]+[^/.])$ /$1/ [R=301,L,NC]

mod_rewrite will have to hiccup backward once-- when it reaches the end of [^.]+ and then has to make room for the final character-- but this is a lot faster than evaluating a whole separate Condition. No legitimate request would end in . but you want to exclude the, um, illegitimate ones.

montesano

3:14 pm on Dec 10, 2011 (gmt 0)

10+ Year Member



Thank you lucy for helping me clean up my htaccess. @g1smd, I wont get into why exactly I need my url's like that, but the fact is I do need them that way. Any other way would be redundant. Can you please explain to me in further detail how to add redirects for requests for the old url. In that regard, will the old url show in a browser's url field after the request is made(by that I mean will /?d=48YSWD96 automatically change into /48YSWD96 in the url field after the request to go to that page is made, because I don't want that. I need the ?d= forced, just like I've already forced my trailing slashes; which I'm willing to give up)? And if I have to destroy my rewrites - how so? Thanks

g1smd

7:46 pm on Dec 10, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



To be clear you need to first define which things are URLs used "out there" on the web and which are internal paths and files used "here" inside the server. URLs and paths are not at all the same thing, they are merely associated by the action of the server software.

Example:

URL: example.com/foo - what the user requests (URL includes the domain name).
Internal path that serves the content: /foo.php - where inside the server it really resides (does NOT include domain name).

You currently have a redirect from URL example.com/foo.php to URL example.com/foo and a rewrite from URL example.com/foo to INTERNAL PATH /foo.php.

How that works is if user requests URL example.com/foo.php they are redirected to URL example.com/foo. User then makes new request for URL example.com/foo and the content is served from INTERNAL PATH /foo.php without revealing the details of that location.

Now you decide to change the URL that user uses to be example.com/?id=foo

What you do next depends on where inside the server the content resides. Is it still at /foo.php or is it now at /index.php?id=foo

If you cannot define all of these details in clear and simple terms you do not have enough information to begin coding.

[edited by: g1smd at 8:24 pm (utc) on Dec 10, 2011]

lucy24

8:06 pm on Dec 10, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I wont get into why exactly I need my url's like that, but the fact is I do need them that way. Any other way would be redundant.

This is tantalizing. For the sake of other people coming along later and reading this thread, could you please take the time to explain a little of the background? It's always useful to know why people are doing what they're doing. Sometimes there's more than one solution to a problem, and you want to find the one that best matches what you need to do. It can be something as simple as what order to put certain rules in, so as to catch the most common type of request first.

Think of it like those horrible "word problems" in grade-school math. The arithmetic itself is easy. But you can't do anything until you've figured out how to get from the words to the numbers.

montesano

10:19 pm on Dec 10, 2011 (gmt 0)

10+ Year Member



Thanks g1smd. I appreciate you helping me, and baring with the fact that I'm new to this.

my internal paths look like: /48YSWD96.php

As for my current .htaccess, which I modded to Lucy's standards(thanks Lucy), I just transferred that from another site of mine. I rather like forcing the trailing slash, but in this case it isn't necessary. The removing of the .php is however. I guess what I'm saying so far in regard to my current .htaccess file is, the whole thing can be scrapped for the sake of achieving the goal at hand.

before making any modifications to my .htaccess, of course, one would have to request mysite.com/48YSWD96.php to get to path /48YSWD96.php. After mods, the links I put 'out there' looked like: mysite.com/48YSWD96 and would take a visitor to path: /48YSWD96.php and would also force their url to mysite.com/48YSWD96/. Simply because I like it like that.

In this case however, I need to post links/url's 'out there' that look like: mysite.com/?d=48YSWD96 and take a user to path: /48YSWD96.php. So, the trailing slash isn't needed, the removal of .php still is, and I need to force(if that's what you would call it in this case) "?d=" before the filename.

Tantalizing as it may be Suzy, and I appreciate your help very much as well - I will not, cannot, tell you why I need my urls constructed like this. I hope you respect that. I sympathize with other viewers but I'm sure they can still learn from this.

Oh one more thing g1smd, "Now you decide to change the URL that user uses to be example.com/?id=foo" unless I'm misunderstanding you, that's false. I need to change the URL that user uses to be example.com/?d=foo, not /?id=foo. I mean I need to post link/url's 'out there' on the web that look like:example.com/?d=foo and take a visitor who clicks on it/types it in their url to filepath:/foo.php
I hope that's doable. I know it is in one case, I need it to be in mine.

I apologize for not being more clear earlier.

[edited by: montesano at 10:29 pm (utc) on Dec 10, 2011]

g1smd

10:27 pm on Dec 10, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



After mods, the links I put 'out there' looked like:
example.com/48YSWD96
and would take a visitor to path:
/48YSWD96.php
and would also force their url to
example.com/48YSWD96/
.

There's two errors in your description. The correct wording for what happens is that users are redirected from
example.com/48YSWD96
to
example.com/48YSWD96/
and the latter request is then rewritten to
/48YSWD96.php
to serve the content. You should not have been linking to
example.com/48YSWD96
. If you want users to see and use a URL ending with a slash, like
example.com/48YSWD96/
then that is the URL that you should have used in the links. URLs are defined by what you put in the
href=
part of a link.

----

Thanks for the previous definitions. It's a very simple job then:

Use a RewriteRule for each task...

Redirect{1}:
(www.)example.com/<stuff>
and
(www.)example.com/<stuff>/
to
www.example.com/d=<stuff>


Redirect{2}:
(www.)example.com/<stuff>.php
to
www.example.com/d=<stuff>


Redirect: all non-www to www retaining original path.

Rewrite:
example.com/d=<stuff>
to
/stuff.php


Note: {1} - this rule could clash with existing "real" folder names so will need a RewriteCond of some sort to ensure that does not happen.

Note: {2} - this rule also needs a RewriteCond looking at THE_REQUEST in order to prevent an infinite redirect-rewrite loop.

This is exactly backwards to how I would organise the URL format for a site.

[edited by: g1smd at 10:46 pm (utc) on Dec 10, 2011]

montesano

10:39 pm on Dec 10, 2011 (gmt 0)

10+ Year Member



Here we go again with the grade-school math 'word problems', Lucy ;).

I cant put that into code g1smd. My current htaccess was copy/pasted from somewhere on the web. I know next to zip about this. I hope I'm not out of line in asking you to write that code for me?

montesano

10:46 pm on Dec 10, 2011 (gmt 0)

10+ Year Member



Am I hot?

RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^([^/]+)/$ $1.php [L]

RewriteRule ^([^/]+(/[^/]+)*)/$ /$1.php [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule ^([^.]+[^/.])$ /$1/ [R=301,L,NC]

RewriteRule Redirect{1}: (www.)example.com/<stuff> and (www.)example.com/<stuff>/ to www.example.com/d=<stuff> f.php

RewriteCond %{THE_REQUEST}
RewriteRule Redirect{2}: (www.)example.com/<stuff>.php to www.example.com/d=<stuff>

RewriteRule Redirect: all non-www to www retaining original path.

Rewrite: example.com/d=<stuff> to /stuff.php

montesano

2:37 am on Dec 12, 2011 (gmt 0)

10+ Year Member



Ok, so I changed the file path to:/d=48YSWD96. I didn't know I could do that - I thought I tried before and it didn't work. So Now all I need to do is force the question mark. I need to be able to put links 'out there' on the web like: 'mysite.com/?d=48YSWD96 and take the visitor to filepath: /d=48YSWD96. When I make a page with a name like '?d=48YSWD96', when visited, it's just an index page for the root folder. I need it to be a page with content, so I'm guessing the only way is to 'force' the question mark with a mod in the htaccess. I'd really appreciate further help with this.

lucy24

3:12 am on Dec 12, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Do a Forums search for "query string" + "boilerplate" ;) You only need to read it once; it really is boilerplate so it's always the same. Er, that is, you may need to read it more than once*, but you only need to read one copy of it.


* See unrelated thread on Readability.

montesano

6:45 pm on Dec 13, 2011 (gmt 0)

10+ Year Member



Thanks, I think I figured out the rewrite condition but I need help on the rewrite rule. What I have now takes me to a Internal Server Error.

RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^([^/]+)/$ $1.php [L]

RewriteRule ^([^/]+(/[^/]+)*)/$ /$1.php [L]

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule ^([^.]+[^/.])$ /$1/ [R=301,L,NC]

RewriteCond %{QUERY_STRING} ^?[a-z]+$
RewriteRule ^(index\.php)?$

lucy24

10:38 pm on Dec 13, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



OK, let's pick this apart. Assuming that g1 will speak up if I've mistranslated at any point. Remember that Conditions are only evaluated if the Rule itself can potentially apply.

Rule #1:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^([^/]+)/$ $1.php [L]
IF request is for a first-level directory THEN IF the directory doesn't exist, AND it would be an existing file if you attached .php to the end (meaning that the real name ends in /.php), THEN rewrite, replacing the slash with .php

Surviving requests: anything other than a first-level directory AND any first-level directories that actually exist AND anything that isn't really a file ending in /.php

Rule #2:
RewriteRule ^([^/]+(/[^/]+)*)/$ /$1.php [L]
IF request is for any directory, including first-level directories that didn't get picked up by Rule #1 (no conditions, so you do this even if the requested directory actually exists), THEN rewrite, replacing the final slash with .php

Surviving requests: anything that doesn't end in /

Rule #3:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule ^([^.]+[^/.])$ /$1/ [R=301,L,NC]
IF request is for anything that doesn't have an extension and doesn't end in /, THEN IF the request is not for an existing file AND not for an existing directory (note that neither of these conditions is necessary, since directories must end in / and files must have an extension) AND the request does not end in a slash or an extension (also unnecessary, because the Rule already says this), THEN redirect, adding a slash to the end of the request.

When the redirect from this rule returns to mod_rewrite, it will meet Rules 1 and 2.

Surviving requests: anything with an extension

Rule #4:
RewriteCond %{QUERY_STRING} ^?[a-z]+$
RewriteRule ^(index\.php)?$
If the request is for exactly index.php or exactly nothing, THEN IF the query string consists entirely of lower-case letters with no = or & or numerals, then ... uhm ... what?

montesano

5:55 am on Dec 14, 2011 (gmt 0)

10+ Year Member



"If the request is for exactly index.php or exactly nothing, THEN IF the query string consists entirely of lower-case letters with no = or & or numerals, then ... uhm ... what? "

Hell I dunno, that's what I took from your suggested search of "query string" + "boilerplate". It was very hard for me to see how that example directly related to my situation. But, I went from getting a 404 error to internal server error, I thought that was progress. All I want to do is force a "?" before the filename. But I cant name it that way because it turns into an index page for the root folder and completely disregards the content. So I thought I could achieve this through modding my htaccess. And in reading that post about boilerplate, I couldn't figure out how to do it, so the above result(my last post) was the best I could come up with. What do you suggest I replace Rewrite Rule 4 with then?

lucy24

9:01 am on Dec 14, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



It's not a Rule yet. So far it's only got a pattern without a target. You have to say what happens to index.php.

And I'm not sure you understand the question mark. It means two entirely different and unrelated things, one in Regular Expressions and the other in URLs. You want the URL kind, hence the suggestion to read up on Query Strings in connection with mod_rewrite.

g1smd

9:21 am on Dec 14, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



You have to say what happens to requests for index.php.

Remember. Mod_rewrite kicks in only after a request is made to the server after a link is clicked or a URL is typed into a browser. Mod_rewrite deals with those requests by checking the list of rules and seeing if any patterns match this request. For a pattern that matches, mod_rewrite either sends back a redirect response to the browser telling it to ask for a different rule or it rewrites the internal file pointer value to instead fetch content from a different internal filepath from that suggested by the one in the URL request.

You need to be sure when you need to redirect and when you need to rewrite. Redirects are a URL to URL translation. Rewrites are a URL to internal filepath translation. Both use a RewriteRule but the coding is slightly different for each.

lucy24

10:57 am on Dec 14, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



mod_rewrite ... sends back a redirect response to the browser telling it to ask for a different rule

You know you've been working with mod_rewrite too long when your fingers know how to spell "url" without consulting your brain.
:)

montesano

6:34 pm on Dec 14, 2011 (gmt 0)

10+ Year Member



okay, enough of the run-around. I didn't necessarily come here for a lecture. & I can't hold out another day. Either of you have a paypal account?

g1smd

6:40 pm on Dec 14, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



telling it to ask for a different rule

Yes. That was a typo: "rule" should say "URL".


Run around? The purpose of this forum is education. Teach a man to fish and all that...

montesano

6:47 pm on Dec 14, 2011 (gmt 0)

10+ Year Member



Lemme tell u somethin', in this case, I already know how to fish. I just need my damn fishing pole to work. I take it your answer to my question's a no. Lucy, the offer still stands for you. If you can mod my htaccess to do what i need it to do, I will pay you; otherwise, it's been real.

montesano

9:10 pm on Dec 14, 2011 (gmt 0)

10+ Year Member



***Problem solved elsewhere***

RewriteCond %{QUERY_STRING} (^|&)d=([A-Za-z0-9]+)($|&)
RewriteRule ^$ /d=%2.php [L]

^is all you need to add to an htaccess like mine(for anyone whose lurkin).

Thanks for nothin', guys.

[edited by: engine at 11:30 am (utc) on Dec 16, 2011]