9

假设我有一个 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 我不确定这里是否正确使用了虚拟目录这个术语。我只想做我在别处看到的。

4

5 回答 5

11
location / {
    rewrite ^/(.*)$ /index.php?q=$1
}

location = /index.php {
    #Do your normal php passing stuff here now
}

那是你要找的吗?

作为第二个问题的答案,您可以在 php.ini 中解析协议。Nginx 不需要这样做。要解析url,可以使用parse_url函数

于 2012-07-20T01:46:27.657 回答
7
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


于 2012-07-20T15:55:38.040 回答
7

好吧,matzahboy 和 VBart 已经提供了 nginx 配置摘录,它们正确地向您展示了如何将 URL 重写为 GET 变量。但为了使用它,您必须解释$_GET['q']. 您还没有指定要遵循的规则,所以这里有一个建议。

要按此顺序进行测试:

  1. 根据RFC2396使用 PHP 的 Validate Filter 的有效 URL:使用 cURL 进行测试,对 HTTP 响应代码 < 400 响应 TRUE,对其他任何内容响应 FALSE。
  2. (host.)example.com/path (missing protocol):假设 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 实现了分析策略,例如:

  • http://example.com/https://www.example.net/foo/bar,
  • 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 处理的位分开编码。

于 2012-07-20T03:47:08.770 回答
3

使用 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' 值。这会默认方案的值,以便您以后可以执行类似的操作

$info['scheme'] . '://' . $info['path'];

这将导致http://google.com/

希望这能回答您的全部问题。

于 2012-07-23T08:13:49.867 回答
2

你想过重写吗?我只知道 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其他内容匹配。

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

于 2012-07-21T15:27:02.220 回答