Reputation: 11121
Let's say I have a web server (nginx) server.com
where I have only one php file index.php
(there is no directory structure). I want to be able to access anything after server.com. It will be an url structure. For example server.com/google.com, server.com/yahoo.com.au etc...
An example would be http://whois.domaintools.com/google.com
(They don't have a directory that's called /google.com, right?)
Q1: How can I access whatever is after 'server.com' from index.php
Q2: Can I get the protocol from such URL? For example server.com/http://www.google.com
or server.com/https://www.google.com
PS I'm not certain if the term virtual directory is used here correctly. I just want to do what I saw somewhere else.
Upvotes: 9
Views: 2083
Reputation: 163
Have you thought of rewrites? I know only Apache's rules. In Apache I would do it this way:
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]
This will pass everything on to $_GET['page']
(PHP) except if anything in the URL matches index.php
, js
, css
and others.
If you have any questions, let me know. Hope this helped.
Upvotes: 2
Reputation: 46856
Well, matzahboy and VBart have already contributed nginx configuration excerpts that correctly show you how to rewrite the URL to a GET variable. But in order to USE this, you have to interpret the value provided in $_GET['q']
. You haven't specified the rules you want to follow, so here's a suggestion.
To be tested in this order:
If that makes sense to you, then the following index.php may get you started:
<?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);
}
I don't claim that this is the prettiest or most secure code, but at least it implements an analysis strategy for supplied URLs like:
http://example.com/https://www.example.net/foo/bar
,http://example.com/example.org/foo/bar
orhttp://example.com/example.org
Note that cURL's gopher support may be broken, and other protocols (which do not return HTTP response codes) are not supported by the code above. If you need to support protocols other than HTTP and HTTPS, please say so in your question and I'll adjust the PHP accordingly.
Specifically, if you want to be able to check http://example.com/ping://host.example.net
it wouldn't be hard, but it would have to be coded separately from the bit handled by cURL.
Upvotes: 7
Reputation: 15110
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;
}
The fastcgi_params
file is bundled with 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;
And you have access to all these fastcgi environment parameters using built-in $_SERVER
array in PHP. http://php.net/manual/en/reserved.variables.server.php
Upvotes: 7
Reputation: 4752
Using matzahboy's nginx code:
location / {
rewrite ^/(.*)$ /index.php?q=$1
}
along with the following PHP code:
$basis = array(
'scheme' => 'http',
);
$info = array_merge( $base, parse_url( 'www.google.com' ) );
print_r( $info );
Which will return something like this for example.com/google.com or example.com/http://google.com/
Array ( [scheme] => http [path] => www.google.com )
Note that the $base array contains the 'scheme' value of 'http'. This defaults the value of scheme so that you can later do something like
$info['scheme'] . '://' . $info['path'];
which would result in http://google.com/
Hope this answers your full question.
Upvotes: 3
Reputation: 3024
location / {
rewrite ^/(.*)$ /index.php?q=$1
}
location = /index.php {
#Do your normal php passing stuff here now
}
Is that what you were looking for?
As an answer to your second question, you can parse the protocol in php. Nginx doesn't need to do that. To parse the url, you can use the parse_url
function
Upvotes: 11