假设我有一个web服务器(nginx)server.com
,其中我只有一个php文件index.php
(没有目录结构)。我希望能够访问server.com之后的任何内容。这将是一个url结构。例如server.com/google.com、server.com/yahoo.com.au等…
一个例子是http://whois.domaintools.com/google.com
(他们没有一个名为/google.com的目录,对吧?)
Q1:如何从index.php访问"server.com"之后的内容
Q2:我可以从这样的URL获取协议吗?例如server.com/http://www.google.com
或server.com/https://www.google.com
PS我不确定这里是否正确使用了虚拟目录这个术语。我只想做我在其他地方看到的事。
location / {
rewrite ^/(.*)$ /index.php?q=$1
}
location = /index.php {
#Do your normal php passing stuff here now
}
这就是你想要的吗?
作为第二个问题的答案,您可以在php中解析协议。Nginx不需要这么做。要解析url,可以使用parse_url
函数
location / {
try_files $uri @dynamic;
}
location @dynamic {
fastcgi_pass backend;
include fastcgi_params;
fastcgi_param PATH_INFO $uri;
fastcgi_param SCRIPT_NAME /index.php;
fastcgi_param SCRIPT_FILENAME /absolute/path/to/index.php;
}
fastcgi_params
文件与nginx 捆绑在一起
$ cat fastcgi_params
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
#fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
您可以使用PHP中内置的$_SERVER
数组访问所有这些fastcgi环境参数。http://php.net/manual/en/reserved.variables.server.php
- http://wiki.nginx.org/Pitfalls
- http://nginx.org/r/try_files
- http://nginx.org/r/fastcgi_param
- http://nginx.org/r/location
- http://nginx.org/r/include
- http://nginx.org/en/docs/http/ngx_http_core_module.html#variables
好吧,matzahboy和VBart已经提供了nginx配置摘录,正确地向您展示了如何将URL重写为GET变量。但是为了使用它,您必须解释$_GET['q']
中提供的值。你还没有指定要遵守的规则,所以这里有一个建议。
按此顺序测试:
- 根据RFC2396使用PHP的Validate Filter的有效URL:使用cURL进行测试,对HTTP响应代码响应TRUE<400,其他值为FALSE
- (host.)example.com/path(缺少协议):假设HTTP协议,按照#1进行测试
- host.example.com(仅限主机名):与#2相同
- example.com(仅限域):测试为#2,然后测试为www.example.com
- 任何其他:失败
如果这对你来说有意义,那么下面的index.php可能会让你开始:
<?php
function http_response($url) {
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_NOBODY, TRUE); // remove body
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$head = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (!$head) {
return FALSE;
}
if ($httpCode < 400) {
return $url;
} else {
return FALSE;
}
}
function test_string($q) {
if (filter_var($q, FILTER_VALIDATE_URL)) {
// Matches RFC2396, so let's generate a hit.
return http_response($q);
}
elseif (preg_match('/^([a-z0-9][a-z0-9-]+'.)+[a-z]{2,}(:[0-9]+)?'/.+$/', $q)) {
// Matches: (host.)example.com/path
return http_response("http://" . $q);
}
elseif (preg_match('/^([a-z0-9][a-z0-9-]+'.){2,}[a-z]{2,}$/', $q)) {
// Matches: host.example.com
return http_response("http://" . $q . "/");
}
elseif (preg_match('/^([a-z0-9][a-z0-9-]+'.)+[a-z]{2,}$/', $q)) {
// Matches: example.com
$ret=http_response("http://" . $q . "/");
if ($ret === FALSE) {
return http_response("http://www." . $q . "/");
} else {
return $ret;
}
}
else {
return FALSE;
}
}
$q = $_GET['q'];
//$q = $argv[1]; // for command-line testing
$url = test_string($q);
if ($url === FALSE) {
printf("<p>The URL <strong>%s</strong> is invalid.</p>'n", $q);
} else {
printf("<p>The URL is <strong>%s</strong>.</p>'n", $url);
}
我并不认为这是最漂亮或最安全的代码,但至少它实现了对提供的URL的分析策略,如:
- CCD_ 10
http://example.com/example.org/foo/bar
或http://example.com/example.org
请注意,cURL的gopher支持可能会被破坏,并且上面的代码不支持其他协议(不返回HTTP响应代码)。如果你需要支持HTTP和HTTPS以外的协议,请在你的问题中这样说,我会相应地调整PHP。
具体来说,如果您想检查http://example.com/ping://host.example.net
,这并不难,但它必须与cURL处理的位分开编码。
使用matzahboy的nginx代码:
location / {
rewrite ^/(.*)$ /index.php?q=$1
}
以及以下PHP代码:
$basis = array(
'scheme' => 'http',
);
$info = array_merge( $base, parse_url( 'www.google.com' ) );
print_r( $info );
它将返回类似于example.com/google.com或example.com的内容/http://google.com/
Array ( [scheme] => http [path] => www.google.com )
请注意,$base数组包含"http"的"scheme"值。这将默认scheme的值,以便您以后可以执行类似的操作
$info['scheme'] . '://' . $info['path'];
这将导致http://google.com/
希望这能回答你的全部问题。
你想过重写吗?我只知道Apache的规则。在Apache中,我会这样做:
RewriteCond $1 !^(index'.php|js|css|admin|images|img|png|robots'.txt|sitemap'.xml|sitemap'.xml'.gz|sitemap'.kml|robots'.txt|javascripts|style.css)
RewriteRule ^(.*)$ index.php/?page=$1 [L]
这将把所有内容传递给$_GET['page']
(PHP),除非URL中的任何内容与index.php
、js
、css
和其他内容匹配。
如果你有任何问题,请告诉我。希望这能有所帮助。