web-dev-qa-db-fra.com

Le codage d'URL des liens externes mène à '% 3F' et '% 3D' sur le serveur Nginx

J'ai un problème avec mon serveur. J'ai reçu quatre liens entrants vers différents sites de ma page Web dynamique, qui ressemblent à ceci: 

myurl.com/default/Site%3Fid%3D13

Ils devraient ressembler à ceci: 

myurl.com/default/Site?id=13

Je sais que ces %3F sont une séquence d'échappement du signe ? et que le %3D est une séquence d'échappement du signe égal. Mais je reçois une erreur 400 lorsque j'utilise ces liens. Que puis-je faire à ce sujet?

Les quatre liens sont destinés à différents sites et j'imagine qu'avec le temps, il y aura plus de liens comme celui-là. Donc, une solution pour tous serait parfaite.

12
user3082653

Une question identique a été posée sur la liste de diffusion nginx-ru il y a environ un an:

http://mailman.nginx.org/pipermail/nginx-ru/2013-Février/050200.html

La réponse la plus utile, par un Nginx, Inc, employé/développeur, Валентин артенев:

http://mailman.nginx.org/pipermail/nginx-ru/2013-Février/050209.html

Сли запрос приходит в таком виде, то это уже не параметры, et имя запрошенноо о. En savoir plus, l'emplacement et les conditions de l'hôtel.

Traduction:

Si la demande se présente sous cette forme, il ne s'agit plus des arguments, mais du nom du fichier demandé. Une autre chose est que, comme documenté, la correspondance d'emplacement est effectuée par rapport à un URI normalisé.

Sa solution suggérée, traduite dans l'exemple de la question ici à SO, serait alors:

location /default/Site? {
    rewrite \?(.*)$ /default/Site?$1? last;
}

location = /default/Site {
    [...]
}
8
cnst

L'exemple suivant redirige toutes les demandes d'aspect incorrect (définies comme ayant ? dans le nom de fichier demandé - codé en tant que %3F dans la demande) vers des requêtes d'aspect moins incorrect, indépendamment de l'URL.

(Veuillez noter que, comme il est conseillé à juste titre ailleurs, vous ne devriez pas obtenir ces liens mal formés en premier lieu, utilisez-le donc en dernier recours - uniquement lorsque vous ne pouvez pas corriger les liens mal formés autrement, et vous savez que de telles demandes sont tentées par des agents valides.)

server {
    listen      [::]:80;
    server_name localhost;

    rewrite     ^/([^?]*)\?(.*)$    /$1?$2?     permanent;
    location / {
        return  200 "id is $arg_id\n";
    }
}

Ceci est un exemple de la façon dont cela fonctionnerait - lorsqu'une demande qui ressemble à une erreur est rencontrée, une tentative de correction est effectuée avec une réponse 301 Moved Permanently avec un en-tête de réponse Location supposément correct, ce qui obligerait le navigateur à réémettre automatiquement la demande à l'emplacement nouvellement fourni. :

opti# curl -6v "http://localhost/default/Site%3Fid%3D13"
* About to connect() to localhost port 80 (#0)
*   Trying ::1...
* connected
* Connected to localhost (::1) port 80 (#0)
> GET /default/Site%3Fid%3D13 HTTP/1.1
> User-Agent: curl/7.26.0
> Host: localhost
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: nginx/1.4.1
< Date: Wed, 15 Jan 2014 17:09:25 GMT
< Content-Type: text/html
< Content-Length: 184
< Location: http://localhost/default/Site?id=13
< Connection: keep-alive
<
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.4.1</center>
</body>
</html>
* Connection #0 to Host localhost left intact
* Closing connection #0

Notez qu'aucune tentative de correction n'est effectuée sur les requêtes correctes:

opti# curl -6v "http://localhost/default/Site?id=13"
* About to connect() to localhost port 80 (#0)
*   Trying ::1...
* connected
* Connected to localhost (::1) port 80 (#0)
> GET /default/Site?id=13 HTTP/1.1
> User-Agent: curl/7.26.0
> Host: localhost
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.4.1
< Date: Wed, 15 Jan 2014 17:09:30 GMT
< Content-Type: application/octet-stream
< Content-Length: 9
< Connection: keep-alive
<
id is 13
* Connection #0 to Host localhost left intact
* Closing connection #0
1
cnst

Le URL est parfaitement valide. Les caractères échappés qu'il contient ne sont que des échappés. Ce qui est parfaitement bien.

Le but est que vous puissiez réellement avoir un nom de requête (dans la plupart des cas correspondant au nom de fichier sur le disque) qui est Site?id=13 et non pas Site et le reste en tant que chaîne de requête.

Je considérerais comme une mauvaise pratique d’avoir des caractères dans un nom de fichier qui le rend nécessaire. Cependant, dans les arguments d'URL, cela peut très bien être nécessaire.

Néanmoins, l'URL de la demande est valide et ne correspond probablement pas à ce que vous souhaitez. Ce qui suggère par conséquent que vous devriez corriger l'erreur chaque fois que quelqu'un a choisi la mauvaise URL en premier lieu.

Je ne comprends pas vraiment pourquoi vous obtenez une erreur 400; vous devriez plutôt obtenir une erreur 404. Mais cela dépend de votre configuration.

Il existe également des cas, en particulier avec nginx, qui impliquent généralement de transmettre des URL entières et des parties d'URL sur plusieurs niveaux (par exemple, les mandataires inversés, la correspondance d'expressions régulières à partir de l'URL et leur utilisation en tant que variables, etc.) où une telle erreur peut se produire. Mais pour vérifier cela et le corriger, il nous faudrait en savoir plus sur votre configuration.

0
The Surrican