以下是我的网站目录结构:
htdocs/
My-Project/
.htaccess
public/
css/
img/
img.jpg
js/
index.php
...(other stuff)
我想使用.htaccess文件检查请求的路径是否为public /目录中的文件(类似于从express.static中的目录中提供静态文件)。如果是,则提供服务,否则将请求转发到/index.php。
SubProblem1:仅提供公共目录中的文件,否则路由到index.php
SubProblem2:从公共目录提供这些文件,而不需要URL中的“公共”
因此,/My-Project/img/img.jpg
应该重写为/My-Project/public/img/img.jpg
,而/My-Project/notexisting.file
或/My-Project/test
应该重写为/My-Project/index.php
。
到目前为止,这是我的主意:
RewriteEngine On
#Block 1
#Condition: File exists in public directory
RewriteCond %{DOCUMENT_ROOT}/My-Project/public/$1 -f
RewriteRule ^(.*)$ public/$1 [L]
#Block 2
#Condition: File doesn't exist in public directory
RewriteCond %{DOCUMENT_ROOT}/My-Project/public/$1 !-f
RewriteRule ^(.*)$ index.php [L,QSA]
当Block 1
独立时->解决了SubProblem2,但是一旦添加了Block 2
来解决SubProblem1,则每个请求都将重写为index.php。为什么会这样呢? 为什么第二个RewriteCond无法正常工作?
答案 0 :(得分:0)
这是我使用的:
#include <stdio.h>
#include <stdlib.h>
#define LENGTH 5
enum Types {
CHAR,
INT,
FLOAT
};
typedef struct {
void *data;
int type;
} Type;
#define FMT_CHAR "%c"
#define FMT_INT "%d"
#define FMT_FLOAT "%f"
#define MAX_FORMATTED_LEN 100 // TODO: adjust this: put the maximum length of a printed float or int
char *fmt_type(char *buffer, Type *t);
#define FMT_TYPE(t) fmt_type((char [MAX_FORMATTED_LEN+1]){""}, t)
char *fmt_type(char *buffer, Type *t) {
switch(t->type) {
case CHAR:
sprintf(buffer, FMT_CHAR, *((char *)t->data));
break;
case INT:
sprintf(buffer, FMT_INT, *((int *)t->data));
break;
case FLOAT:
sprintf(buffer, FMT_FLOAT, *((float *)t->data));
break;
default:
printf("Wrong type: %d. Panicking.", t->type);
exit(-1);
}
return buffer;
}
int main()
{
int i0 = 3, i1 = 421;
float f0 = 2.5;
char c0 = 'H', c1 = 'a';
Type a = { &i0, INT };
Type b = { &f0, FLOAT };
Type c = { &c0, CHAR };
Type d = { &i1, INT };
Type e = { &c1, CHAR };
Type *array[LENGTH] = { &a, &b, &c, &d, &e };
//printf("Random entry: %s\n", FMT_TYPE(array[rand() % LENGTH]));
// the following is just for testing:
int i = 0;
for (i = 0; i < LENGTH; i++) {
printf("entry: %s\n", FMT_TYPE(array[i]));
}
}
如果需要,请更新我的apache虚拟主机配置:
RewriteEngine On
# The following rule tells Apache that if the requested filename
# exists, simply serve it.
RewriteCond %{REQUEST_FILENAME} -s [OR]
RewriteCond %{REQUEST_FILENAME} -l [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^.*$ - [NC,L]
# The following rewrites all other queries to index.php. The
# condition ensures that if you are using Apache aliases to do
# mass virtual hosting, the base path will be prepended to
# allow proper resolution of the index.php file; it will work
# in non-aliased environments as well, providing a safe, one-size
# fits all solution.
RewriteCond %{REQUEST_URI}::$1 ^(/.+)(.+)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
RewriteRule ^(.*)$ %{ENV:BASE}index.php [NC,L]
然后在<VirtualHost *:80>
ServerName awesome.scot
ServerAlias localhost
DocumentRoot /var/www/html/public
<Directory "/var/www/html">
DirectoryIndex index.php
FallbackResource /index.php
Options -Indexes +FollowSymLinks
AllowOverride FileInfo All
Require all granted
</Directory>
ProxyPassMatch ^/(.*\.php)$ fcgi://php:9000/var/www/html/public/$1
</VirtualHost>
中,我添加了/etc/hosts
,所以现在我使用127.0.0.1 awesome.scot
在浏览器中访问我的网站
请注意vhost conf中的两个文件夹,一个是站点根目录,一个是公共目录。
如果您尚未打开虚拟主机,请尝试一下!取消注释apache conf中的vhosts行,然后进入额外的文件夹并配置您的vhost,然后重新启动!
答案 1 :(得分:0)
第二个RewriteCond不能按我预期的那样工作,因为一旦Block1重写了请求,Block2中的$ 1就不会包含与Block1中相同的信息。
想象一下,我们有URI /My-Project/img/img.jpg
。
在 Block1 中,$1
将是img/img.jpg
。因为此文件存在,所以将满足RewriteCondition,并且新URI将为My-Project/public/img/img.jpg
。
现在是 Block2 :由于重写了URI,此处将$1
定义为public/img/img.jpg
。因此,RewriteCondition将检查URL MyProject/public/public/img/img.jpg
下是否存在任何现有文件。当然不是。因此,无论以前是否进行过重写,始终都会满足RewriteCondition,并且每个请求都将被重写为index.php。
RewriteEngine On
RewriteCond %{DOCUMENT_ROOT}/My-Project/public/$1 -f
RewriteRule ^(.*)$ public/$1 [L]
RewriteCond %{THE_REQUEST} \s/My-Project/public/ [NC,OR]
RewriteCond $1 !^public/
RewriteRule ^(.*)$ index.php [L]