Avec Zend Framework, lorsque l’on travail un projet conséquent il devient vite utile de travailler avec le mécanisme des modules. Celui-ci permet d’étendre pas mal de chose et surtout une séparation poussée en … module.
Le problème de ce mécanisme1 est qu’il faut définir le chemin pour le chargement automatique à l’aide de ceci :
$autoloader = new Zend_Application_Module_Autoloader(array( 'namespace' => 'SuperModule', 'basePath' => 'path to super module', ));
Je vous propose donc de faire une petite amélioration afin que ce chargement soit fait automatiquement.
Avant tout, dans votre configuration (ici en .ini) vous devez au moins avoir ceci de présent :
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules" resources.modules =
Ensuite, à la base de chaque dossier module créer un fichier Bootstrap.php2 :
<?php class SuperModule_Bootstrap extends Grummfy_Bootstrap{} # EOF
Et pour finir créer le fichier3 library/Grummfy/Bootstrap.php
<?php abstract class Grummfy_Bootstrap extends Zend_Application_Bootstrap_Bootstrap { protected function _initAutoload() { $className = get_class($this); $zf_namespace = explode('_', $className); $reflector = new ReflectionClass($className); $autoloader = new Zend_Application_Module_Autoloader(array( 'namespace' => $zf_namespace[0], 'basePath' => dirname($reflector->getFileName()), )); return $autoloader; } } # EOF
Tags : PHP, programmation, trucs et astuces, ZF
Lors de l’utilisation du mécanisme d’ACL et de génération de menu dans Zend Framework, il est intéressant de limiter l’affichage de ce menu en utilisant les ressources et privilèges associer.
Pour ma part, j’utilise un fichier XML pour construire mon menu, mon sitemap, … 1. Et comme beaucoup je génère mon projet ZF à l’aide de Zend_Tool. Je trouvais donc dommage de devoir réécrire pratiquement la même chose que ce que j’avais déclaré dans Zend_Tool pour reconstruire mon menu. J’ai donc décidé de rapidement écrire un petit script qui reprendrait le fichier XML du projet et le transformerait en menu …
À noter que le script devrait certainement être amélioré, mais que cela permet un gain de temps considérable …
- Comme expliquer dans le manuel http://framework.zend.com/manual/fr/zend.navigation.html ↩
Tags : délire, jouons, PHP, programmation, trucs et astuces, web, ZF
Lorsque l’on travaille à plusieurs sur un projet, c’est toujours intéressant. Malheureusement, cela peut aussi entrainer divers problèmes. Je vais tenter de vous expliquer un obstacle qui peut vite devenir très chi*nt…
Pour présenter cette problématique, je vais prendre exemple sur ce que je développe actuellement. Le site en cours de création se base sur zend framework et nécessite une réécriture d’URL. Il faut savoir qu’Apache utilise le chemin physique1 comme base pour calculer le chemin vers le fichier réécrit sauf si on lui précise une directive RewriteBase différente. Le problème survient à cet endroit, plusieurs développeurs entrainent plusieurs machines et donc plusieurs configurations différentes!
La solution de base est que chaque personne utilisant un alias Apache définit un RewriteBase. Cependant, cela veut dire qu’a chaque nouvelle version du fichier .htaccess il faut redéfinir celui-ci.
La réponse la plus simple consiste à utiliser un RewriteCond sur l’hostname du serveur et bien entendu à l’utiliser lors de l’accès aux tests locaux ou non …
Exemple de configuration :
- nom du serveur : grummfy
- URL appelée : http://grummfy/serveur/dev/projet/example.com/… (Si vous utilise http://localhost/ la directive HTTP_HOST vaudra localhost)
- ALIAS : /serveur/ => /media/data/serveur/
Le fichier .htacccess contiendra ceci :
SetEnv APPLICATION_ENV development
php_value session.auto_start 0
php_flag magic_quotes_gpc off
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
RewriteCond %{HTTP_HOST} grummfy
RewriteRule ^.*$ /serveur/dev/projet/example.com/index.php [NC,L]
RewriteRule ^.*$ index.php [NC,L]
Le fait d’utiliser le rewrite flag « L » permet de sortir de la réécriture d’URL. Si le hostname du serveur n’est pas grummfy il appliquera la règle par défaut, à savoir tenter de trouver index.php dans /media/data/serveur/dev/projet/example.com/ comme si on avait effectuer un appel depuis http://media/data/serveur/dev/projet/example.com/
- physical-directory-path ↩
Tags : apache, trucs et astuces, url rewriting, web
Durant le développement du projet b-box j’ai rencontré un problème avec mon menu. Ce menu est présent sous forme de ListActivity (comprenant une ListView), était trié selon un ordre alphabétique qui est susceptible de changer puisque l’application peut-être traduite.
Au début, j’ai essayé diverses méthodes, mais les id de position étant perdus… pas moyen de savoir à quoi correspond quoi.
J’ai donc du trouver une solution, solution que je vous présente.
But
Le but est de créer un menu sous forme de liste (ListView) dont chaque élément est cliquable et permet de récupérer l’id du clic. Cet id servant à lancer une autre Activity, par exemple.
Exemple
Tout d’abord la classe Menu :
package org.android.bbox; import java.util.Comparator; public class Menu { private int id; private String label; public Menu(int id, String label) { this.id = id; this.label = label; } public String getLabel() { return this.label; } public int getId() { return this.id; } public static Menu[] factory(String[] menus) { Menu[] menu = new Menu[menus.length]; for(int i = 0; i < menus.length; i++) { menu[ i ] = new Menu(i, menus[ i ]); } return menu; } public static Comparator getComparator() { return new Comparator(){ @Override public int compare(Menu m1, Menu m2) { return m1.getLabel().compareTo(m2.getLabel()); } }; } public String toString() { return this.getLabel(); } }
Et la classe de l’activité :
// ... public void onCreate(Bundle savedInstanceState) { //... Menu[] m = Menu.factory(getResources().getStringArray(R.array.main_list_array));//récupération d'un tableau de string et création d'un tableau de Menu ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, m);//création de l'adaptateur permettant l'affichage adapter.sort(Menu.getComparator());//tri du menu ListView myList = (ListView) findViewById(android.R.id.list); myList.setAdapter(adapter);//ajotu du menu à la ListView myList.setOnItemClickListener(this); //... } @Override public void onItemClick(AdapterView parent, View view, int position, long id) { System.out.print(position); System.out.print(" | "); System.out.print(parent.getItemAtPosition(position)); System.out.print(" | "); System.out.print(parent.getItemAtPosition(position).getClass()); System.out.print(" | "); System.out.print(((Menu)parent.getItemAtPosition(position)).getId()); System.out.print(" | "); System.out.println(id); //... } // ...
Remarque : la méthode toString permet l’affichage de l’élément dans la liste.
Tags : android, programmation, Projet, trucs et astuces
Dans Google code il y a la possibilité d’utiliser un gestionnaire de version tel que subversion (svn) ou mercurial (hg). C’est bien pratique, mais malheureusement, de base, rien n’est prévu pour prévenir (excepté par flux RSS) les gens de ces mises à jour. Cependant, Google code permet d’utiliser un webhook en post commit.
Qu’est-ce qu’un webhook?
Un webhook c’est un « crochet web », c’est-à-dire une URL a appelée après (avant ou pendant) une action X. Dans notre cas, après chaque commit une URL est appelée.
Utilisation
Voici un exemple de code que j’utilise pour plusieurs de mes projets :
<?php // project name $projects = array('mon-super-projet'); // google code webhook key $keys = array( 'b-box' => 'Top-Secret_key_fourni_par_google-dans-l-adminsitration' ); //user agent from google code $useragent = 'Google Code Project Hosting (+http://code.google.com/p/support/wiki/PostCommitWebHooks)'; //email of all owner (eg. project chief) $owners = array('vous@example.com'); //email of all team members except owners $users = array('toi@example.com'); //sender of email $sender = 'WebHook mailer<webmaster@exemple.com>'; //---------------------------------------------------------------------- $project = (isset($_GET['p']))?$_GET['p']:''; $revision = (isset($_GET['r']))?intval($_GET['r']):-99; $data = file_get_contents('php://input'); $digest = (isset($_SERVER['HTTP_GOOGLE_CODE_PROJECT_HOSTING_HOOK_HMAC']))?$_SERVER['HTTP_GOOGLE_CODE_PROJECT_HOSTING_HOOK_HMAC']:''; //---------------------------------------------------------------------- /** * Send a mail * @param string $from email of the sender : sample@example.com or "name"<sample@example.com>; * @param array $to [a] => list of email [cc], [bcc] (hidden), ... * @param string $subject * @param string $body * @return bool true if success */ function mailer($from, array $to, $subject, $body) { if (empty($to)) { return false; } $headers = 'From: ' . $from . "\n"; $a = ''; if (isset($to['a']) && !empty($to['a'])) { $a = implode(',', $to['a']); } if (isset($to['bcc']) && !empty($to['bcc'])) { $headers .= 'Bcc: ' . implode(',', $to['bcc']) . "\n"; } if (isset($to['cc']) && !empty($to['cc'])) { $headers .= 'Cc: ' . implode(',', $to['cc']) . "\n"; } $headers .= 'MIME-Version: 1.0' . "\n"; $headers .= 'Content-Type: text/plain; charset="UTF-8"' . "\n"; $headers .= 'Content-Transfer-Encoding: 8bit' . "\n"; $headers .= 'X-Mailer: PHP/' . phpversion(); return mail($a, '[webhook]' . $subject, $body, $headers); } function failed($test_id, $msg) { global $sender, $owners; $msg .= "\n--\nWebHook mail from the Google code project"; mailer($sender, array('bcc' => $owners), 'failed test #' . $test_id, $msg); die('KO'); } function get_ip() { return (isset($_SERVER['HTTP_X_FORWARDED_FOR']))?$_SERVER['HTTP_X_FORWARDED_FOR']:(isset($_SERVER['HTTP_CLIENT_IP']))?$_SERVER['HTTP_CLIENT_IP']:$_SERVER['REMOTE_ADDR']; } //---------------------------------------------------------------------- if ($useragent != $_SERVER['HTTP_USER_AGENT']) { // failed 1 failed(1, 'User agent is bad : ' . htmlspecialchars($_SERVER['HTTP_USER_AGENT']) . "\n\nFrom : " . get_ip()); } elseif (empty($project) || !in_array($project, $projects)) { // failed 2 failed(2, 'No project set : ' . htmlspecialchars($project) . "\n\nFrom : " . get_ip()); } else { $hmac = hash_hmac('md5', $data, $keys[ $project ]); $data = json_decode($data, true); if (empty($digest) || $digest != $hmac) { // failed 3 failed(3, 'Bad digest : ' . $digest . ' vs ' . $hmac . "\n\nFrom : " . get_ip()); } elseif (intval($data['revision_count']) != count($data['revisions'])) { // failed 4 failed(4, 'Bad count : ' . count($data['revisions']) . ' vs ' . intval($data['revision_count']) . "\n\nFrom : " . get_ip()); } else { $mail_body = ''; foreach($data['revisions'] as $_revision) { $mail_body .= 'Revision : ' . "\t" . htmlentities($_revision['revision']) . ' from ' . htmlentities($_revision['author']) . ' at ' . date('Y-m-d H:i', intval($_revision['timestamp'])) . "\n"; $mail_body .= 'Added : ' . "\t" . implode("\n\t\t", htmlentities($_revision['added'])) . "\n"; $mail_body .= 'Modified : ' . "\t" . implode("\n\t\t\t", htmlentities($_revision['modified'])) . "\n"; $mail_body .= 'Removed : ' . "\t" . implode("\n\t\t\t", htmlentities($_revision['removed'])) . "\n\n"; // $mail_body .= 'URL : ' . "\t\t" . htmlentities($_revision['url']) . "\n\n"; $mail_body .= 'Message : ' . "\t" . htmlentities($_revision['message']) . "\n\n\n"; // $_revision['path_count']; } $mail_body .= "\n--\nWebHook mail from the Google code project : " . $project . "\nhttp://code.google.com/p/" . $project . "/\n"; mailer($sender, array('bcc' => $owners + $users), '[' . $project . ']New revision #' . $revision, $mail_body); } } exit('OK'); # EOF
Plus d’info : PostCommitWebHooks
Tags : découverte, PHP, programmation, script, trucs et astuces, web
PHP 5.3 ajoute une notion intéressante : les espaces de nom (ou namespace en anglais). Les espaces de nom permettent de séparer différents … « espace« , permettant ainsi d’avoir deux classe portant le même nom. Idéal pour l’utilisation de framework mais aussi de « l’isolation » de certains composants. Voyons voir comment créer un chargeur automatique (ou autoloader) comprenant les espaces de nom.
Si vous êtes sous Ms Windows, aucun problème un simple spl_autoload_register(); suffit. Malheureusement, sous *nix un bug existe il faudra donc implémenté une solution maison.
Le code
Ce code provient du « PHP Standards Working Group » :
function autoload($className) { $className = ltrim($className, '\\'); $fileName = ''; $namespace = ''; if ($lastNsPos = strripos($className, '\\')) { $namespace = substr($className, 0, $lastNsPos); $className = substr($className, $lastNsPos + 1); $fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR; } $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; require $fileName; }
Pour l’utiliser, il faut définir deux choses :
- Ne pas oublier de modifier l’include path si nécessaire.
- Ajouter cette fonction au chargeur de classes présent.
L’exemple
Voici un exemple un peu plus complet.
index.php
<?php set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__) . '/lib/');//on ajoute le dossier lib dans l'include path spl_autoload_register();//sur windows ceci devrait suffire . //le code pour les autres //---------------------------------------------------------- function autoload($className) { $className = ltrim($className, '\\'); $fileName = ''; $namespace = ''; if ($lastNsPos = strripos($className, '\\')) { $namespace = substr($className, 0, $lastNsPos); $className = substr($className, $lastNsPos + 1); $fileName = str_replace('\\', DIRECTORY_SEPARATOR, $namespace) . DIRECTORY_SEPARATOR; } $fileName .= str_replace('_', DIRECTORY_SEPARATOR, $className) . '.php'; require $fileName; } spl_autoload_register('autoload'); //---------------------------------------------------------- //fin du code de fix use grummfy\test\Test; Test::sayHello(); \grummfy\std\Test::sayHello(); # EOF
./lib/grummfy/test/Test.php
<?php namespace grummfy\test;//pour rappel ceci doit-être la première instruction php (et on ne doit pas avoir de HTML avant) echo 'Je suis inclus (' . __FILE__ . ')!'; class Test { public static function sayHello() { echo 'Bonjour depuis ' . __CLASS__; } } # EOF
./lib/grummfy/std/Test.php
<?php namespace grummfy\std; echo 'Je suis inclus (' . __FILE__ . ')!'; class Test { public static function sayHello() { echo 'Bonjour depuis ' . __CLASS__; } } # EOF
Le résultat devrait être :
Je suis inclus (/.../lib/grummfy/test/Test.php)!
Bonjour depuis grummfy\test\Test
Je suis inclus (/.../lib/grummfy/std/Test.php)!
Bonjour depuis grummfy\std\Test
Tags : namespace, PHP, programmation, web
Il arrive que lors de l’écriture d’un nombre complexe de règle de réécriture d’URL (URL rewriting), des erreurs se produisent sans pour autant être compréhensibles. Je vous propose donc de regarder comment déboguer cela à travers un exemple pratique.
Exemple
Prenons une règles qui vérifierait que seul certains type de caractère sont autorisés.
La réécriture quant à elle se fait sur toute URL.
Ajoutons un document 403 personnalisé
RewriteEngine on
#
RewriteCond %{THE_REQUEST} !^[A-Z]{3,9}\ [a-zA-Z0-9\.\+_/\-\?\=\&]+\ HTTP/ [NC]
RewriteRule .* - [F,NS,L]
#
#if not a dir or a file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#
RewriteRule ^(.*)$ index.php?p=$1 [QSA,L]
ErrorDocument 403 /erreur/403
Testons l’URL http://localhost/test:s et on obtient un beau :
Forbidden
You don’t have permission to access /test:s on this server.
Additionally, a 500 Internal Server Error error was encountered while trying to use an ErrorDocument to handle the request.
Les logs d’erreurs d’Apache vous diront certainement quelque chose du genre :
[error] [client 127.0.0.1] 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.
Passage en mode debug de Apache
Modifions la règle de log du site courant (soit dans /etc/apache2/sites-available/default soit dans /etc/apache2/apache.conf ou l’équivalent suivant votre configuration ou OS) et modifions la directive « LogLevel warn » en « LogLevel debug ». Ceci ne change rien dans notre cas, mais parfois cela s’avère utile…
Ajoutons ensuite les log1 de réécriture d’url (moi je l’ai ajouter dans /etc/apache2/mods-available/rewrite.conf puis j’ai fait un a2enmod rewrite (car le fichier .conf n’existait pas) et enfin j’ai relancer Apache) :
<IfModule mod_rewrite.c>
RewriteLog "/var/log/apache2/rewrite.log"
RewriteLogLevel 9
</IfModule>
Maintenant si vous aller voir dans error.log vous aurez :
[error] [client 127.0.0.1] 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.
[debug] core.c(3063): [client 127.0.0.1] r->uri = /…/erreur/403
[debug] core.c(3069): [client 127.0.0.1] redirected from r->uri = /…/erreur/403
[debug] core.c(3069): [client 127.0.0.1] redirected from r->uri = /…/erreur/403
[debug] core.c(3069): [client 127.0.0.1] redirected from r->uri = /…/erreur/403
[debug] core.c(3069): [client 127.0.0.1] redirected from r->uri = /…/erreur/403
[debug] core.c(3069): [client 127.0.0.1] redirected from r->uri = /…/erreur/403
[debug] core.c(3069): [client 127.0.0.1] redirected from r->uri = /…/erreur/403
[debug] core.c(3069): [client 127.0.0.1] redirected from r->uri = /…/erreur/403
[debug] core.c(3069): [client 127.0.0.1] redirected from r->uri = /…/erreur/403
[debug] core.c(3069): [client 127.0.0.1] redirected from r->uri = /…/erreur/403
[debug] core.c(3069): [client 127.0.0.1] redirected from r->uri = /…/test:s
Donc on voit que la redirection s’effectue correctement mais qu’il « n’accroche » pas. Regardons donc les logs de la réécriture d’URL (rewrite.log) :
/initial] (3) [perdir /.../] strip per-dir prefix: /…/test:s -> test:s
/initial] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘test:s’
/initial] (4) [perdir /.../] RewriteCond: input= » pattern=’200′ => not-matched
/initial] (3) [perdir /.../] strip per-dir prefix: /…/test:s -> test:s
/initial] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘test:s’
/initial] (4) [perdir /.../] RewriteCond: input=’GET /…/test:s HTTP/1.1′ pattern=’!^[A-Z]{3,9}\ [a-zA-Z0-9\.\+_/\-\?\=\&]+\ HTTP/’ [NC] => matched
/initial] (2) [perdir /.../] forcing responsecode 403 for /…/test:s
/initial/redir#1] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#1] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#1] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#1] (4) [perdir /.../] RewriteCond: input=’403′ pattern=’200′ => not-matched
/initial/redir#1] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#1] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#1] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#1] (4) [perdir /.../] RewriteCond: input=’GET /…/test:s HTTP/1.1′ pattern=’!^[A-Z]{3,9}\ [a-zA-Z0-9\.\+_/\-\?\=\&]+\ HTTP/’ [NC] => matched
/initial/redir#1] (2) [perdir /.../] forcing responsecode 403 for /…/erreur
/initial/redir#2] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#2] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#2] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#2] (4) [perdir /.../] RewriteCond: input=’403′ pattern=’200′ => not-matched
/initial/redir#2] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#2] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#2] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#2] (4) [perdir /.../] RewriteCond: input=’GET /…/test:s HTTP/1.1′ pattern=’!^[A-Z]{3,9}\ [a-zA-Z0-9\.\+_/\-\?\=\&]+\ HTTP/’ [NC] => matched
/initial/redir#2] (2) [perdir /.../] forcing responsecode 403 for /…/erreur
/initial/redir#3] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#3] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#3] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#3] (4) [perdir /.../] RewriteCond: input=’403′ pattern=’200′ => not-matched
/initial/redir#3] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#3] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#3] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#3] (4) [perdir /.../] RewriteCond: input=’GET /…/test:s HTTP/1.1′ pattern=’!^[A-Z]{3,9}\ [a-zA-Z0-9\.\+_/\-\?\=\&]+\ HTTP/’ [NC] => matched
/initial/redir#3] (2) [perdir /.../] forcing responsecode 403 for /…/erreur
/initial/redir#4] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#4] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#4] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#4] (4) [perdir /.../] RewriteCond: input=’403′ pattern=’200′ => not-matched
/initial/redir#4] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#4] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#4] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#4] (4) [perdir /.../] RewriteCond: input=’GET /…/test:s HTTP/1.1′ pattern=’!^[A-Z]{3,9}\ [a-zA-Z0-9\.\+_/\-\?\=\&]+\ HTTP/’ [NC] => matched
/initial/redir#4] (2) [perdir /.../] forcing responsecode 403 for /…/erreur
/initial/redir#5] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#5] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#5] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#5] (4) [perdir /.../] RewriteCond: input=’403′ pattern=’200′ => not-matched
/initial/redir#5] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#5] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#5] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#5] (4) [perdir /.../] RewriteCond: input=’GET /…/test:s HTTP/1.1′ pattern=’!^[A-Z]{3,9}\ [a-zA-Z0-9\.\+_/\-\?\=\&]+\ HTTP/’ [NC] => matched
/initial/redir#5] (2) [perdir /.../] forcing responsecode 403 for /…/erreur
/initial/redir#6] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#6] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#6] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#6] (4) [perdir /.../] RewriteCond: input=’403′ pattern=’200′ => not-matched
/initial/redir#6] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#6] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#6] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#6] (4) [perdir /.../] RewriteCond: input=’GET /…/test:s HTTP/1.1′ pattern=’!^[A-Z]{3,9}\ [a-zA-Z0-9\.\+_/\-\?\=\&]+\ HTTP/’ [NC] => matched
/initial/redir#6] (2) [perdir /.../] forcing responsecode 403 for /…/erreur
/initial/redir#7] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#7] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#7] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#7] (4) [perdir /.../] RewriteCond: input=’403′ pattern=’200′ => not-matched
/initial/redir#7] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#7] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#7] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#7] (4) [perdir /.../] RewriteCond: input=’GET /…/test:s HTTP/1.1′ pattern=’!^[A-Z]{3,9}\ [a-zA-Z0-9\.\+_/\-\?\=\&]+\ HTTP/’ [NC] => matched
/initial/redir#7] (2) [perdir /.../] forcing responsecode 403 for /…/erreur
/initial/redir#8] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#8] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#8] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#8] (4) [perdir /.../] RewriteCond: input=’403′ pattern=’200′ => not-matched
/initial/redir#8] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#8] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#8] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#8] (4) [perdir /.../] RewriteCond: input=’GET /…/test:s HTTP/1.1′ pattern=’!^[A-Z]{3,9}\ [a-zA-Z0-9\.\+_/\-\?\=\&]+\ HTTP/’ [NC] => matched
/initial/redir#8] (2) [perdir /.../] forcing responsecode 403 for /…/erreur
/initial/redir#9] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#9] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#9] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#9] (4) [perdir /.../] RewriteCond: input=’403′ pattern=’200′ => not-matched
/initial/redir#9] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#9] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#9] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#9] (4) [perdir /.../] RewriteCond: input=’GET /…/test:s HTTP/1.1′ pattern=’!^[A-Z]{3,9}\ [a-zA-Z0-9\.\+_/\-\?\=\&]+\ HTTP/’ [NC] => matched
/initial/redir#9] (2) [perdir /.../] forcing responsecode 403 for /…/erreur
/initial/redir#10] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#10] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#10] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#10] (4) [perdir /.../] RewriteCond: input=’403′ pattern=’200′ => not-matched
/initial/redir#10] (3) [perdir /.../] add path info postfix: /…/erreur -> /…/erreur/403
/initial/redir#10] (3) [perdir /.../] strip per-dir prefix: /…/erreur/403 -> erreur/403
/initial/redir#10] (3) [perdir /.../] applying pattern ‘.*’ to uri ‘erreur/403′
/initial/redir#10] (4) [perdir /.../] RewriteCond: input=’GET /…/test:s HTTP/1.1′ pattern=’!^[A-Z]{3,9}\ [a-zA-Z0-9\.\+_/\-\?\=\&]+\ HTTP/’ [NC] => matched
/initial/redir#10] (2) [perdir /.../] forcing responsecode 403 for /…/erreur
En gros, nous avions une boucle de redirection. Pour l’éviter ajoutons,d ans le .htaccess, une condition qui dira de ne pas rentrer dans le bloc, s’il y a une erreur 403 :
RewriteEngine on
#
RewriteCond %{ENV:REDIRECT_STATUS} !403
RewriteCond %{THE_REQUEST} !^[A-Z]{3,9}\ [a-zA-Z0-9\.\+_/\-\?\=\&]+\ HTTP/ [NC]
RewriteRule .* - [F,NS,L]
#
#if not a dir or a file
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#
RewriteRule ^(.*)$ index.php?p=$1 [QSA,L]
ErrorDocument 403 /erreur/403
Maintenant tout fonctionne comme prévu!
La fin
Pour finir, ceci montre encore l’importance des logs lors de la rencontre de problème. S’il y a moyen penser a les activer, cela simplifie franchement la tâche de débogage que cela soit pour Apache mais aussi pour tout projet informatique.
Un dernier conseil, pensez a désactiver le mode debug de Apache une fois fini!
S’il y avait un site a conseiller sur ce sujet (en dehors du manuel Apache) je vous renverrait vers askapache
- Si le fichier ne se créer pas tout seul penser à le créer ↩
Tags : apache, deboguage, serveur, url rewriting, web
Cet article présente rapidement l’URL rewriting et ce qu’est SEO pour arriver au cœur du sujet, à savoir, la problématique de la réécriture d’URL : la duplication de contenu. Pourquoi la duplication de contenu est gênante et surtout comment l’éviter sont expliqué dans la suite! Lire le reste de l’article »
Tags : apache, référencement, SEO, url rewriting, web
Commentaires récents