Bonjour

je bloque sur une règle de réécriture et d'encodage dans un script ajax / php pour un petit moteur de recherche
J'ai une règle de réécriture pour mon site :

RewriteEngine on
RewriteRule ([a-zA-Z0-9\-]+)_([0-9]+)\.html index.php?page=$1&id=$2 [N]
RewriteRule ([a-zA-Z0-9\-]+)_([a-zA-Z0-9&îïùéè@.\s|%20\-]+)\.html index.php?page=$1&search=$2 [N]
RewriteRule ([a-zA-Z0-9\-]+)\.html index.php?page=$1 [L]


J'envoie les données de mon formulaire de recherche via une requête ajax. J'encode le contenu de ma recherche dans un encodeURIComponent
function search_article(article) {
    let article_clean = article.replace(/[`²!#$%^&*()_|+\=;'",<>£µ§\{\}\[\]\\\/]/gi, '');
    if (article_clean !== article) {
        document.getElementById('search-bar').value = article_clean;
    } else {
        let result_article = document.getElementById('result_article');
        if (article.length === 0 || article === ' ') {
            result_article.innerHTML = '';
        } else {
            let xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    result = xhr.responseText;
                    console.log(result);
                    result_article.innerHTML = xhr.responseText;
                }
            };
            console.log(encodeURIComponent(article));
            xhr.open('GET', 'recherche-article_' + encodeURIComponent(article) + '.html');
            xhr.send();
        }


et je récupère le tout dans un script php, je teste, cherche dans ma bdd et renvoie un résultat à afficher dans une div. A mon niveau c'est déjà un exploit, mais je rencontre un problème que je n'arrive pas à résoudre. A la base en javascript je "nettoie" (comme je peux) ma recherche en virant un maximum de caractère qui posait problème (je faisais la recherche pour un annuaire, donc que des noms / prénoms pas de caractères spéciaux), j'ai bien les espaces qui s'affichent avec les %20 et ça fonctionne. Mais par exemple si je mets un ? qui devient %3F, alors la règle mal faite de mon RewriteRule me renvoie direct sur une erreur 403 (je présume que c'est mon htaccess qui met le bazarre)...
Comment fait-on dans cette règle pour laisser les réencodage des caractères spéciaux passer vers mon script php ?
Merci
Bonjour,
La réécriture me permet d'appeler une page HTML au lieu du PHP, mais j'appelle bien une page PHP qui récupère l'id par GET, effectue la recherche et affiche via le JavaScript le résultat. Je ne l'ai pas mis, l'erreur étant une erreur 403 c'est au niveau serveur que ça plante et uniquement pour certains caractères donc ça vient de mes règles d'écriture URL. J'encode ma variable pour la transmettre par l'URL, mais je ne trouve pas sur le web (et sincèrement je n'arrive pas à comprendre) comment on peut ajouter (autoriser) certains caractères encodés par encodeURIComponent...
Modérateur
Bonjour,

Tu veux dire que c'est index.php qui est le script php qui est exécuté pour effectuer la recherche  ???

Amicalement,
désolé, je n'ai peut-être pas donné assez d'explication. Oui la réécriture renvoie toutes les pages sur index.php qui appelle systématiquement l'autoloader qui voit l'index page dans le GET et charge le bon fichier php qui contient la méthode de la classe qui fait ce qu'il y a à faire et qui elle même appelle après le php qui affiche le résultat. C'est une structure MVC. Le truc qui me bloque c'est que la règle d'écriture simple à la base index.php?page=variablepage&id=varid je l'ai fait évoluer vers une version index.php?page=varpage&search=texte pour passer mon texte de recherche vers la méthode de recherche.
Comme je suis une bille en règle (regex ?), j'ai eu beau chercher sur le web et je n'ai pas compris/trouvé le moyen de contrôler réellement cette règle de réécriture.
J'ai donc récupéré la règle simple de réécriture pour les pages ([a-zA-Z0-9\-]+)_([0-9]+)\.html index.php?page=$1&id=$2 et je l'ai complétée maladroitement par un enrichissement de quelques caractères &îïùéè@.\s|%20\- en lisant des articles sur le net. Je nettoie en amont avec le javascript au fur et à mesure de la saisier, sauf que comme c'est de la bidouille je me retrouve bloqué quand j'encode mon texte avec encodeURIComponent par exemple un point d'interrogation se transforme en %3F qui n'est pas accepté par ma règle et me renvoie un 403 qui est bien le forbidden du serveur (enfin c'est comme ça que je le comprends). Je n'arrive pas à ajouter et surtout comprendre comment ajouter par exemple %3F pour qu'il ne soit pas filtré (et par extension d'autres "encodages").
Merci
Modifié par _Lolo (20 Mar 2021 - 14:36)
Modérateur
Bonjour,

Que de bidouilles ! Résultat : tu essaies de faire du MVC mais en fin de compte, tu ne sais plus où tu en es.

1) Selon moi, il n'y a pas de bonnes raisons quand on fait de l'AJAX de passer par une adresse html qui va être ré-écrite par APACHE en un fichier index.php avec en plus des données après un ?, qui lui même va exécuter (enfin) le script php qui fait la recherche. Autant mettre directement l'url du script php qui fait la recherche comme paramètre de la fonction xhr.open().

Il y a peut-être des gens considérés comme forts qui s'amusent à faire ça, mais si j'avais à les noter, je leur mettrais sans problème un zéro juste pour leur apprendre à faire des codes clairs qu'on a une chance de pouvoir maintenir sans perdre une après-midi à changer ne serait-ce qu'une virgule quand on passe derrière eux.

2) Ce serait mieux d'utiliser la méthode POST plutôt que la méthode GET, et ce sera d'autant plus facile si tu fais comme en 1).

3) Le ? pose problème avec la méthode GET parce que c'est un caractère qui a une signification particulière dans une url. Il faut donc se méfier.

4) As-tu essayé de remplacer
RewriteRule ([a-zA-Z0-9\-]+)_([a-zA-Z0-9&îïùéè@.\s|%20\-]+)\.html index.php?page=$1&search=$2 [N]

par
RewriteRule ([a-zA-Z0-9\-]+)_(.+)\.html index.php?page=$1&search=$2 [N]


5) Si on avait un exemple de ce que peut contenir la variable article quand ça échoue, ça serait mieux. Si ça se trouve, tu cherches dans la mauvaise direction.

6) Attention, la longueur d'un nom de fichier est limité, la longueur d'une url aussi (et tout ça dépend de la machine hôte).

Amicalement,
Modifié par parsimonhi (20 Mar 2021 - 18:08)
Merci beaucoup
Pas de soucis, je suis débutant en la matière et ne me suis jamais considéré comme fort ! Et effectivement là comme je l'indiquais cela relevait plus de la bidouille.
La recherche se fait au niveau du titre des articles, donc par exemple "qui sommes-nous ?" (qui pose problème)
Après avoir modifié comme tu me le suggérais la ligne RewriteRule (ce qui en plus est beaucoup plus logique vu que c'est sur une recherche textuelle ...), ça ne change rien : Failed to load resource: the server responded with a status of 403 (Forbidden)
Moralité, l'erreur n'est effectivement pas celle que je pensais (!), j'ai pour la recherche sans le ? la réponse ok et le lien de la page appelée est recherche-article_qui%20sommes-nous.html alors que ça ne fonctionne pas avec le ? et le lien de la page appelée qui renvoie l'erreur 403 http://localhost/MVC-object/recherche-article_qui%20sommes-nous%3F.html
Je ne sais pas pourquoi... Mais je vais surtout suivre tous les conseils que tu m'as donné et reprendre via un script en direct + en POST
Encore merci pour ce temps précieux passé à corriger mes erreurs et mon manque de connaissances.
Modérateur
Bonjour,

Je viens de faire le test suivant qui marche très bien. J'affiche la page search.php dans un navigateur, et je clique sur le bouton "Cherche". Cela déclenche bien la requête ajax qui exécute le script index.php qui lui-même renvoie ce qu'il a trouvé dans $_GET['page'] et $_GET['search'], à savoir "recherche-article" et "qui sommes-nous?". Ça marche avec ou sans point d'interrogation à la fin de "qui sommes-nous".

Ton problème est donc bien ailleurs.

1) .htaccess
RewriteEngine on
RewriteRule ([a-zA-Z0-9\-]+)_([0-9]+)\.html index.php?page=$1&id=$2 [N]
RewriteRule ([a-zA-Z0-9\-]+)_(.+)\.html index.php?page=$1&search=$2 [N]
RewriteRule ([a-zA-Z0-9\-]+)\.html index.php?page=$1 [L]


2) Script search.php
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="utf-8">
</head>
<body>
<input id="search_string" value="qui sommes-nous?">
<button onclick="search_article()">Cherche</button>
<div id="result_article"></div>
<script>
function search_article() {
	let article = document.getElementById('search_string').value;
	let xhr = new XMLHttpRequest();
	let result_article = document.getElementById('result_article');
	xhr.onreadystatechange = function () {
		if (xhr.readyState === 4 && xhr.status === 200) {
			result = xhr.responseText;
			console.log(result);
			result_article.innerHTML = result;
		}
	};
	xhr.open('GET', 'recherche-article_' + encodeURIComponent(article) + '.html');
	xhr.send();
}
</script>
</body>
</html>


3) script index.php
<?php
if(isset($_GET['page'])) echo $_GET['page'];
echo "<br>";
if(isset($_GET['search'])) echo $_GET['search'];
?>


Amicalement,
Modifié par parsimonhi (20 Mar 2021 - 20:15)
Bon, j'ai encore bidouillé et ma solution n'est pas celle que tu me préconises : je passe par un POST, mais je n'appelle pas mon script php en direct... Je n'arrives pas à récupérer mes classes sans mon autoloader quand j'attaque directement sur un fichier php pour effectuer ma recherche (je m'y perds un peu). Dans mon script php de recherche je fais appel à des méthodes de ma classe Article pour rechercher dans ma bdd. Et j'ai bien compris que c'était complètement c.. d'appeler le script de recherche php par la réécriture de l'URL via la page index.php et l'autoader et compagnie.
Bref, donc du coup, j'en suis à utiliser POST et il prend bien tout, j'ai mis dans mon js pour l'AJAX :
xhr.open('POST', 'recherche-article.html',true);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(JSON.stringify(search_article));

et pour mon PHP je récupère le POST par
$data = json_decode(file_get_contents("php://input"));
Salut,
C'est en effet un peu compliqué pour pas grand'chose ton histoire. Cependant ta dernière piste est un peu meilleure.

Un appel AJAX en POST se fait toujours de la même manière et pas comme tu fais. Il faut vraiment envoyer ta requête comme un formulaire et pas en JSON.


xhr.open('POST', 'recherche-article.html',true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send('search=' + encodeURIComponent(search_article));


Et pour récupérer côté serveur :

$data = $_POST['search'];


Il faut faire toutes les vérifications nécessaires mais le principe est là.
Merci, c'est un gros projet et je commence à fatiguer je crois ... et tout seul c'est un peu compliqué de vérifier qu'on fait selon la bonne méthode. Souvent ça marche mais il faudrait faire autrement...
J'ai rectifié et ça fonctionne, forcément ! Malheureusement il faut que j'avance pour commencer à remplir la base de données par les personnes qui vont l'exploiter. Je reviendrai après sur mes histoires d'appel direct sans passer par la réécriture via ma règle de l'htaccess. Peut être avec une tête un peu plus reposée... on va dire résolu, en partie !
Merci beaucoup pour votre aide précieuse