如何在php中访问nginx虚拟目录


How to make nginx virtual directories accessible in php?

假设我有一个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.comserver.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']中提供的值。你还没有指定要遵守的规则,所以这里有一个建议。

按此顺序测试:

  1. 根据RFC2396使用PHP的Validate Filter的有效URL:使用cURL进行测试,对HTTP响应代码响应TRUE<400,其他值为FALSE
  2. (host.)example.com/path(缺少协议):假设HTTP协议,按照#1进行测试
  3. host.example.com(仅限主机名):与#2相同
  4. example.com(仅限域):测试为#2,然后测试为www.example.com
  5. 任何其他:失败

如果这对你来说有意义,那么下面的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.phpjscss和其他内容匹配。

如果你有任何问题,请告诉我。希望这能有所帮助。