Mod Rewirte for CalDav and CardDav urls in Owncloud - apache

I want to shorten my owncloud caldav and carddav urls.
currently the urls are :
https://site.mysite.com/owncloud/remote.php/caldav/principals/edison/
https://site.mysite.com/owncloud/remote.php/carddav/addressbooks/edison/contacts
Note : The name edison and what ever follows after that is dynamic it will change depending on the users.
I want it to be
https://site.mysite.com/caldav/principals/edison/
https://site.mysite.com/carddav/addressbooks/edison/contacts
.htaccess file contains
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_URI} !\.sso/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
Eg:
If the user request for https://site.mysite.com/caldav/principals/edison/ . Then it should redirect to https://site.mysite.com/owncloud/remote.php/caldav/principals/edison/
How can it be done using mod_rewrite ?

mod_rewrite Prepend Path to Requested URL with Dynamic Portion
Starting at server root, enter the requested URL path in the RewriteRule "pattern" parameter, and the desired path in the "substitution" parameter. In the form:
RewriteRule pattern substitution [flags]
In this case:
RewriteRule ^caldav/principals/edison/$ owncloud/remote.php/caldav/principals/edison/ [L]
If a portion of the URL (between slashes) varies and you don't want to (or can't) write a rule for every situation then use the regular expression ([^/]+) to capture the dynamic portion and inject it into your substituted path using the RE capture variable $1:
RewriteRule ^caldav/principals/([^/]+)/$ owncloud/remote.php/caldav/principals/$1/ [L]
The first set of parenthesis is $1, the second set is $2, etc. And capturing parenthesis can be nested.
Put the more specific rules higher in the rules list, and more general rules lower in the list. So I suggest putting this rule first, right after RewriteBase /.

Related

In Apache how to do an external redirect to the slashless version of a URL with a subfolder .htaccess file

On Apache 2.4 I have an .htaccess (in a subfolder) which rewrites slashless requests inside that folder to appropriate index files:
DirectorySlash Off
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} !/$
RewriteCond %{REQUEST_FILENAME}/index.html -f
RewriteRule (.*) $1/index.html [L]
This works for the slashless version exactly as expected. Now I want to redirect the slashed version externally to the slashless version. I tried adding the lines:
RewriteCond %{REQUEST_FILENAME} -d
RewriteCond %{REQUEST_URI} /$
RewriteRule ^(.*)/ $1 [R=302,L]
However this does not work: The redirect is issued, however it does not go to the slashless URL, but to a URL with a system specific part injected.
So, for a sample URL http://example.com/path/to/dir/ the redirected URL looks like this http://example.com/fs9e/username/sub/public/path/to/dir instead of just http://example.com/path/to/dir.
How can I fix this? Many thanks for any pointers!
PS: The real case is a little bit more complicated because I do a subdomain-to-folder rewrite in the root .htacces, but I assume this is not relevant here.
RewriteRule ^(.*)/ $1 [R=302,L]
You are missing the slash prefix (/) on the substitution string (2nd argument) - to make the substitution root-relative. Or rather, /subfolder/ (since this .htaccess file is located in a subfolder). Since this is a relative substitution string (not starting with a slash or scheme+hostname), the directory-prefix*1 (which I assume is /fs9e/username/sub/public/path/) is added back (by default*2), resulting in a malformed redirect. (This is correct for internal rewrites, but not external redirects.)
It should be like this:
RewriteRule ^(.*)/$ /subfolder/$1 [R=302,L]
Note you were also missing the end-of-string anchor ($) on the RewriteRule pattern. (This also negates the need for the preceding condition that checks that REQUEST_URI ends in a slash.)
Note also that this "redirect" should go before the earlier "rewrite".
*1 The directory-prefix is the absolute filesystem path of the location of the .htaccess file.
*2 The alternative is to set a RewriteBase /subfolder - but that then affects all relative substitutions. You could also use an environment variable to apply a specific prefix only to some rules.

Convert Query Parameters to Pretty URL

I have script file post.php which I'm using without .php extension using code below
Options -Indexes
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME}.php -f
RewriteRule ^(.*)$ $1.php [NC,L]
I want to use a pretty URL. For example, when I request the URL /post/12 it should give me $_GET parameter 12 like I'm using with a query string: post?id=12.
Is it possible? Also, I don't want to direct all requests to index.php. Only requests that are made to posts.php script.
Handle requests of the form /post/12 with a separate rule, before your generic rewrite that appends the .php extension.
Try it like this:
Options -Indexes -MultiViews
RewriteEngine On
# Remove trailing slash if not a directory
# eg. "/post/" is redirected to "/post"
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*)/$ /$1 [R=301,L]
# Rewrite "/post/<id>" to "/post.php?id=<id>"
RewriteRule ^(post)/(\d+)$ $1.php?id=$2 [L]
# Rewrite "/post" to "/post.php" (and other extensionless URLs)
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule (.*) $1.php [L]
Notes:
MultiViews needs to be disabled for the second rule to work.
Your initial rule that appends the .php extension was not quite correct. It could have resulted in a 500 error under certain conditions. However, the first condition was superfluous - there's no point checking that the request does not map to a file before checking that the request + .php does map to a file. These are mutually inclusive expressions.
Without the first rule that removes the trailing slash (eg. /post/ to /post) it raises the question of what to do with a request for /post/ (without an id) - should this serve /post.php (the same as /post) or /post.php?id= (empty URl param)? Both of which are presumably the same thing anyway. However, these would both result in duplicate content (potentially), hence the need for a redirect.

mod-rewrite, how to implement a second rule?

I'm trying to get a .htaccess file RewriteRule in my web application. I need a double rule to match two URL formats that might happen:
Rule 1 (not commented below and works like a charm)
http://example.com/whatever -> /index.php?page=whatever&
http://example.com/whatever/ -> /index.php?page=whatever&
http://example.com/whatever/?test=me -> /index.php?page=whatever&test=me
Rule 2 (commented out below and does not work, but should work like this)
http://example.com/api/ -> index.php?page=api&func=
http://example.com/api/whateverelse -> index.php?page=api&func=whateverelse
The folder /api/ does not exists on the server and by reading the documentation the L parameters should prevent the parsing of more rules. Yet if I uncomment the ^\/api\/(.*)$ I get an 404 response.
The goal is that if the first rule gets parsed the second rule is omitted, and the goal is that the first rule actually works.
Is there someone that could point me in the right direction here?
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule ^\/api\/(.*)$ //index.php?page=api&func=$1 [NC,L]
RewriteRule ^\/?([^\/]+)\/?$ //index.php?page=$1&%{QUERY_STRING} [NC,L]
I tried to debug it by adding:
LogLevel alert rewrite:trace6
but this is not allowed in the .htaccess and I do not have direct access to the server configuration files.
#RewriteRule ^\/api\/(.*)$ //index.php?page=api&func=$1 [NC,L]
This doesn't work because in .htaccess the URL-path matched by the RewriteRule pattern does not start with a slash. You have included a slash prefix on the regex, so it never matches.
In the following rule, the slash prefix is made optional with the ? quantifier, ie. ^\/? - so it will match. (The slash prefix is only required when the directive is used in a server context. By making it "optional", it would work in either.)
If you are only using .htaccess then you can remove the slash prefix from the RewriteRule pattern altogether.
For example:
RewriteRule ^api/(.*) /index.php?page=api&func=$1 [NC,L]
Additional notes...
No need to backslash escape slashes in the regex, as they carry no special meaning. (Apache uses spaces as argument delimiters.)
Not sure what the double slash prefix on the substitution string was for? ie. //index.php. You should only have at most one slash here, or none at all for an internal rewrite (and the index.php file is in the same directory as the .htaccess file). (The double slash still "works", only because Apache is reducing instances of multiple slashes when it maps the URL to the filesystem.)
The RewriteCond directives only apply to the first RewriteRule directive that follows, so you may need to repeat these for the second rule. (Or reverse the logic and stop processing when a request does map to a file/directory? However, this might depend on what other directives you have in the file.) If you don't have physical files that start /api then you can remove the conditions from that rule.
You don't need to manually append the QUERY_STRING to the substitution. This is what the QSA (Query String Append) flag is for. The QSA flag will also avoid a stray & at the end when no query string is present on the request.
The NC flag is not required on the last rule. It may not be required on the "api" rule either, unless /API, or /ApI etc. might be required - but this should be avoided.
So, bringing this together, we have....
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^api/(.*) /index.php?page=api&func=$1 [NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/?$ /index.php?page=$1 [QSA,L]

Configure htaccess for url rewriting

I need help for my url's rewriting. I want to organize my url's precisely by taking account of the current organization of my current tree:
-! /www
.htaccess,
index.php, ...
--! **/views**, /assets
pageA.php, pageB.php, pageC.php
---! **/pageA**, /pageB, /pageC, /errors (404.php, 500.php...)
pageA1.php, **pageA2.php**, pageA3.php
/!\ I use specific names for each pages, the prefixes and numbers are just for examples and for a better comprehension about connexions between files and folders. In reality I use pages names like: "contact-us.php", "our-product.php" ...
(1) When I going to pageA.php I would like this url path: www.mywebsite.fr/pageA
(2) When I going to pageA2.php, I would like: www.mywebsite.fr/pageA/pageA2
(3) I don't want extension files (.php, .html)
Actually, I can't go into the path (2) cause I have a 404 page.
I created folders with the same name as a specific php pages it's just for my own organization, but it can be a bad way (for SEO or anything else...) in fact, I don't know...
My rewrite module (in .htaccess of www) is:
<IfModule mod_rewrite.c>
Options +FollowSymlinks
RewriteEngine on
RewriteBase /
# Retirer les extensions des pages et les rendres accessibles en lecture
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /([^\ ]+)\.php
RewriteRule ^/?(.*)\.php$ /$1 [L,R=301]
# check to see if the request is for a PHP file:
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^/?(.*)$ /$1.php [L]
# Suppression d'un sous répertoire
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/views/$1.php -f
RewriteRule (.*) /views/$1.php [QSA,L]
</IfModule>
This is just off the top of my head, but it should work:
RewriteRule ^page([A-Z]{1})([1-9]?).php$ http://www.mywebsite.fr/page$1$2
RewriteRule ^page([A-Z]{1})([1-9]{1})$ http://www.mywebsite.fr/page$1/page$1$2 [L,R=301]
The first Rewrite directive checks for a filename match starting with
page
and ending (prior to the filename extension, .php) with
a single letter (from A to Z); and
(optionally) a single number (from 1 to 9)
If it does, it captures both the letter (and the optional number) and rewrites the URI without the .php file extension at the end.
For those URIs which do include the optional number, the second Rewrite directive captures both the letter and the number separately from each other.
It then builds the redirect according to the correct folder structure, deploying both the captured letter and the captured number.

My .htaccess rule is not working

I want all my URL with matching pattern as
/released/2013/iron-man
/released/2013/abc-of-death
/released/2012/saw6
to be redirected to
/released/1.php
and I can the name as well.
I am adding this rule to my .htaccess file but its not working
RewriteRule ^released/([0-9]+)/?$ /released/1.php?id=$1 [L]
The trailing question mark matches an optional ending / which is not what you want.
^released/([0-9]+)/iron-man$
or
RewriteRule ^released/([0-9]+)/(.+)$ /released/1.php?id=$1+$2
Problem is that you have $ after second slash but you have movie name after 2nd slash like iron-man etc. Remove $ since you are not matching it.
Make sure that mod_rewrite and .htaccess are enabled through httpd.conf and then put this code in your .htaccess under DOCUMENT_ROOT directory:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(released)/([0-9]+)/ /$1/1.php?id=$2 [L,QSA,NC]
A RewriteRule which does not specify a specific external domain is always executed internally. To make it redirect as you ask add [R=301] at the end - or 302, 303 or 307 depending on which kind of redirect you require, but usually 301 is fine.
Besides that, the regular expression you wrote does not allow for extended URLs - remove the trailing $. After that the /? part is moot so you can remove it as well.
The resulting line would read:
RewriteRule ^released/([0-9]+) /released/1.php?id=$1 [L,R=301]