
Recientemente, nos mudamos a Nginx desde Apache. En Apache solía ser muy fácil, simplemente colocaba algunas cosas en .htaccess y listo.
RewriteEngine on
RewriteBase /
# only rewrite if the requested file doesn't exist
RewriteCond %{REQUEST_FILENAME} !-s
# pass the rest of the request into index.php to handle
RewriteRule ^(.*)$ /index.php/$1 [L]
Lo anterior fue excelente para limpiar la URL y permitir que index.php maneje todas las solicitudes. pero en Nginx necesitábamos reescribir cada URL única en el bloque de ubicación. Sin embargo, esto no es "automático" como Apache.
Algunos ejemplos de nuestro bloque de ubicación de reescritura
location / {
try_files $uri $uri/ /index.php;
}
location /p {
rewrite ^/p(?:/([a-z_]+))?$ /index.php?p=$1 last;
rewrite ^/p/all_articles/user/(.*)?$ /index.php?p=all_articles&user=$1 last;
try_files $uri $uri/ /index.php;
}
location /about_us {
rewrite ^/about_us /index.php?about_us last;
try_files $uri $uri/ /index.php;
}
location /search {
rewrite ^/search/(.*) /index.php?search=$1;
rewrite ^/search/(.*)/page/(.*)?$ /index.php?search=$1&page=$2 last;
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
lo anterior funciona bien en URL limpias, pero cuando necesitamos obtener páginas, por ejemplo
/p/all_articles/user/ABC/page/2
/index.php?p=all_articles&user=ABC&page=2
hemos tratado
rewrite ^/p/all_articles/user/(.*)/pg(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&pg=$2 last;
esto solo funciona cuando lo colocamos en un bloque de ubicación separado
location /page/all_articles {
rewrite ^/p/all_articles/user/(.*)/pg(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&pg=$2 last;
try_files $uri $uri/ /index.php;
}
y al hacerlo no dejaba
/p/todos_artículos/usuario/ABC
cargar.
Además, las páginas de resultados de búsqueda no funcionarían en absoluto.
Otro problema que encontramos está en la carpeta .htaccess.
Order deny,allow
Deny from all
Options -Indexes
En Apache, esto impediría cualquier acceso a esa carpeta y archivos, excepto al script php. Nosotros tratamos,
location /(data|img)/ {
deny all;
return 404;
}
Bloquea el acceso a la carpeta pero, si especifica el nombre del archivo, seguirá funcionando, sin negar el acceso, por ejemplo;
/data/backup_01012020.zip en apache .htaccess, solo ciertos usuarios podían acceder a esto, mientras estaban conectados. y fuera de él, Apache negará cualquier acceso. Pero bajo nginx, aunque da 404 al intentar acceder a /data/. Incluso cuando no haya iniciado sesión, le entregará el archivo backup_01012020.zip de inmediato.
Ahora no podemos entender qué podemos hacer, lo que solía ser pan comido con Apache. Nuestra aplicación está basada en PHP e index.php es capaz de manejar todas las solicitudes de URL limpias. Podría haber sido genial si Nginx simplemente pasara todas las solicitudes al índice y lo dejara manejar en lugar de muchas reescrituras y bloques de ubicación. Cualquier ayuda sería genial.
Respuesta1
Quizás te interesen las preguntas con elreescribir etiqueta, ya que contiene muchas variaciones de su problema.
Su regla de reescritura de Apache:
RewriteRule ^(.*)$ /index.php/$1 [L]
agrega el URI de solicitud completo a /index.php
. Ennginxelcaminodel URI (normalizado) está disponible en el$urivariable. Si también necesita los argumentos de la consulta, puede utilizar el$request_urien cambio.
Por lo tanto, una traducción estricta de sus reglas de reescritura sería:
location / {
# Size zero static files are served.
# I don't believe that is an issue.
try_files $uri /index.php$request_uri;
}
# If no other .php files are accessible a prefix location of '/index.php/'
# is safer.
location /index.php/ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
# Probably duplicates the contents of fastcgi-php.conf
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# include fastcgi_params;
}
Su deny
directiva sobre la /(data|img)/
ubicación no funciona, ya que está utilizando una coincidencia de prefijo, en lugar de una coincidencia de expresiones regulares:
location ~ ^/(data|img)/ {
# Only one is required
deny all;
# return 404;
}
Respuesta2
Solución para reescribir
location /search {
rewrite ^/search/(.*)/page/(.*)?$ /index.php?search=$1&page=$2 last;
rewrite ^/search/(.*) /index.php?search=$1 last;
try_files $uri $uri/ /index.php;
}
location /p/all_articles {
rewrite ^/p/all_articles/user/(.*)/page(?:/([0-9]+))?$ /index.php?p=all_articles&user=$1&page=$2 last;
rewrite ^/p/all_articles/user/(.*)?$ /index.php?p=all_articles&user=$1 last;
try_files $uri $uri/ /index.php;
}
Fíjate, todo lo que hice fue intercambiar líneas. Créditos paraRichard Smith
Gracias aPiotr P. Karwasz, para la otra solución, podría ayudar a alguien cuyo script sea 100% compatible a manejar una URL limpia por sí solo.
location / {
# Size zero static files are served.
# I don't believe that is an issue.
try_files $uri /index.php$request_uri;
}
# If no other .php files are accessible a prefix location of '/index.php/'
# is safer.
location /index.php/ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
# Probably duplicates the contents of fastcgi-php.conf
# fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# include fastcgi_params;
}
La solución anterior es un camino a seguir siempre y cuando su script funcione con una URL limpia al 100%. Aquí, no es necesario colocar cientos de bloques de ubicación de reescritura, y nginx agregará el URI de solicitud completo a /index.php, lo cual es muy interesante y útil, probablemente esta sea la solución real, pero en mi caso mi script no era 100 % compatible con esto. Aún así, esta es una solución buena e inteligente.
Solución para evitar el acceso a carpetas y archivos.
location ~ ^/(data|img)/ {
# Only one is required
deny all;
# return 404;
}
Créditos paraPiotr P. KarwaszComo señaló, deny all
algo estaba siendo anulado, al bloquear el servidor limpio resolvió el problema. También asegúrese de usar deny all;
o return 404;
pero no juntos.