This question already has answers here:
How to remove the querystring and get only the URL?
(16 answers)
Closed 3 years ago.
Is there a simple way to get the requested file or directory without the GET arguments? For example, if the URL is http://example.com/directory/file.php?paramater=value I would like to return just http://example.com/directory/file.php. I was surprised that there is not a simple index in $_SERVER[]. Did I miss one?
Edit: #T.Todua provided a newer answer to this question using parse_url.
(please upvote that answer so it can be more visible).
Edit2: Someone has been spamming and editing about extracting scheme, so I've added that at the bottom.
parse_url solution
The simplest solution would be:
echo parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
Parse_url is a built-in php function, who's sole purpose is to extract specific components from a url, including the PATH (everything before the first ?). As such, it is my new "best" solution to this problem.
strtok solution
Stackoverflow: How to remove the querystring and get only the url?
You can use strtok to get string before first occurence of ?
$url=strtok($_SERVER["REQUEST_URI"],'?');
Performance Note:
This problem can also be solved using explode.
Explode tends to perform better for cases splitting the sring only on a single delimiter.
Strtok tends to perform better for cases utilizing multiple delimiters.
This application of strtok to return everything in a string before the first instance of a character will perform better than any other method in PHP, though WILL leave the querystring in memory.
An aside about Scheme (http/https) and $_SERVER vars
While OP did not ask about it, I suppose it is worth mentioning:
parse_url should be used to extract any specific component from the url, please see the documentation for that function:
parse_url($actual_link, PHP_URL_SCHEME);
Of note here, is that getting the full URL from a request is not a trivial task, and has many security implications. $_SERVER variables are your friend here, but they're a fickle friend, as apache/nginx configs, php environments, and even clients, can omit or alter these variables. All of this is well out of scope for this question, but it has been thoroughly discussed:
https://stackoverflow.com/a/6768831/1589379
It is important to note that these $_SERVER variables are populated at runtime, by whichever engine is doing the execution (/var/run/php/ or /etc/php/[version]/fpm/). These variables are passed from the OS, to the webserver (apache/nginx) to the php engine, and are modified and amended at each step. The only such variables that can be relied on are REQUEST_URI (because it's required by php), and those listed in RFC 3875 (see: PHP: $_SERVER ) because they are required of webservers.
please note: spaming links to your answers across other questions is not in good taste.
You can use $_SERVER['REQUEST_URI'] to get requested path. Then, you'll need to remove the parameters...
$uri_parts = explode('?', $_SERVER['REQUEST_URI'], 2);
Then, add in the hostname and protocol.
echo 'http://' . $_SERVER['HTTP_HOST'] . $uri_parts[0];
You'll have to detect protocol as well, if you mix http: and https://. That I leave as an exercise for you. $_SERVER['REQUEST_SCHEME'] returns the protocol.
Putting it all together:
echo $_SERVER['REQUEST_SCHEME'] .'://'. $_SERVER['HTTP_HOST']
. explode('?', $_SERVER['REQUEST_URI'], 2)[0];
...returns, for example:
http://example.com/directory/file.php
php.com Documentation:
$_SERVER — Server and execution environment information
explode — Split a string by a string
parse_url — Parse a URL and return its components (possibly a better solution)
Solution:
echoparse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
Here is a solution that takes into account different ports and https:
$pageURL = (#$_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://';
if ($_SERVER['SERVER_PORT'] != '80')
$pageURL .= $_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].$_SERVER['PHP_SELF'];
else
$pageURL .= $_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'];
Or a more basic solution that does not take other ports into account:
$pageURL = (#$_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://';
$pageURL .= $_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'];
I actually think that's not the good way to parse it. It's not clean or it's a bit out of subject ...
Explode is heavy
Session is heavy
PHP_SELF doesn't handle URLRewriting
I'd do something like ...
if ($pos_get = strpos($app_uri, '?')) $app_uri = substr($app_uri, 0, $pos_get);
This detects whether there's an actual '?' (GET standard format)
If it's ok, that cuts our variable before the '?' which's reserved for getting datas
Considering $app_uri as the URI/URL of my website.
$uri_parts = explode('?', $_SERVER['REQUEST_URI'], 2);
$request_uri = $uri_parts[0];
echo $request_uri;
You can use $_GET for url params, or $_POST for post params, but the $_REQUEST contains the parameters from $_GET $_POST and $_COOKIE, if you want to hide the URI parameter from the user you can convert it to a session variable like so:
<?php
session_start();
if (isset($_REQUEST['param']) && !isset($_SESSION['param'])) {
// Store all parameters received
$_SESSION['param'] = $_REQUEST['param'];
// Redirect without URI parameters
header('Location: /file.php');
exit;
}
?>
<html>
<body>
<?php
echo $_SESSION['param'];
?>
</body>
</html>
EDIT
use $_SERVER['PHP_SELF'] to get the current file name or $_SERVER['REQUEST_URI'] to get the requested URI
Not everyone will find it simple, but I believe this to be the best way to go around it:
preg_match('/^[^\?]+/', $_SERVER['REQUEST_URI'], $return);
$url = 'http' . ('on' === $_SERVER['HTTPS'] ? 's' : '') . '://' . $_SERVER['HTTP_HOST'] . $return[0]
What is does is simply to go through the REQUEST_URI from the beginning of the string, then stop when it hits a "?" (which really, only should happen when you get to parameters).
Then you create the url and save it to $url:
When creating the $url... What we're doing is simply writing "http" then checking if https is being used, if it is, we also write "s", then we concatenate "://", concatenate the HTTP_HOST (the server, fx: "stackoverflow.com"), and concatenate the $return, which we found before, to that (it's an array, but we only want the first index in it... There can only ever be one index, since we're checking from the beginning of the string in the regex.).
I hope someone can use this...
PS. This has been confirmed to work while using SLIM to reroute the URL.
I know this is an old post but I am having the same problem and I solved it this way
$current_request = preg_replace("/\?.*$/","",$_SERVER["REQUEST_URI"]);
Or equivalently
$current_request = preg_replace("/\?.*/D","",$_SERVER["REQUEST_URI"]);
It's shocking how many of these upvoted/accepted answers are incomplete, so they don't answer the OP's question, after 7 years!
If you are on a page with URL like: http://example.com/directory/file.php?paramater=value
...and you would like to return just: http://example.com/directory/file.php
then use:
echo $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'];
Why so complicated? =)
$baseurl = 'http://mysite.com';
$url_without_get = $baseurl.$_SERVER['PHP_SELF'];
this should really do it man ;)
I had the same problem when I wanted a link back to homepage. I tried this and it worked:
<a href="<?php echo $_SESSION['PHP_SELF']; ?>?">
Note the question mark at the end. I believe that tells the machine stop thinking on behalf of the coder :)
Related
This question already has answers here:
How to remove the querystring and get only the URL?
(16 answers)
Closed 3 years ago.
Is there a simple way to get the requested file or directory without the GET arguments? For example, if the URL is http://example.com/directory/file.php?paramater=value I would like to return just http://example.com/directory/file.php. I was surprised that there is not a simple index in $_SERVER[]. Did I miss one?
Edit: #T.Todua provided a newer answer to this question using parse_url.
(please upvote that answer so it can be more visible).
Edit2: Someone has been spamming and editing about extracting scheme, so I've added that at the bottom.
parse_url solution
The simplest solution would be:
echo parse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
Parse_url is a built-in php function, who's sole purpose is to extract specific components from a url, including the PATH (everything before the first ?). As such, it is my new "best" solution to this problem.
strtok solution
Stackoverflow: How to remove the querystring and get only the url?
You can use strtok to get string before first occurence of ?
$url=strtok($_SERVER["REQUEST_URI"],'?');
Performance Note:
This problem can also be solved using explode.
Explode tends to perform better for cases splitting the sring only on a single delimiter.
Strtok tends to perform better for cases utilizing multiple delimiters.
This application of strtok to return everything in a string before the first instance of a character will perform better than any other method in PHP, though WILL leave the querystring in memory.
An aside about Scheme (http/https) and $_SERVER vars
While OP did not ask about it, I suppose it is worth mentioning:
parse_url should be used to extract any specific component from the url, please see the documentation for that function:
parse_url($actual_link, PHP_URL_SCHEME);
Of note here, is that getting the full URL from a request is not a trivial task, and has many security implications. $_SERVER variables are your friend here, but they're a fickle friend, as apache/nginx configs, php environments, and even clients, can omit or alter these variables. All of this is well out of scope for this question, but it has been thoroughly discussed:
https://stackoverflow.com/a/6768831/1589379
It is important to note that these $_SERVER variables are populated at runtime, by whichever engine is doing the execution (/var/run/php/ or /etc/php/[version]/fpm/). These variables are passed from the OS, to the webserver (apache/nginx) to the php engine, and are modified and amended at each step. The only such variables that can be relied on are REQUEST_URI (because it's required by php), and those listed in RFC 3875 (see: PHP: $_SERVER ) because they are required of webservers.
please note: spaming links to your answers across other questions is not in good taste.
You can use $_SERVER['REQUEST_URI'] to get requested path. Then, you'll need to remove the parameters...
$uri_parts = explode('?', $_SERVER['REQUEST_URI'], 2);
Then, add in the hostname and protocol.
echo 'http://' . $_SERVER['HTTP_HOST'] . $uri_parts[0];
You'll have to detect protocol as well, if you mix http: and https://. That I leave as an exercise for you. $_SERVER['REQUEST_SCHEME'] returns the protocol.
Putting it all together:
echo $_SERVER['REQUEST_SCHEME'] .'://'. $_SERVER['HTTP_HOST']
. explode('?', $_SERVER['REQUEST_URI'], 2)[0];
...returns, for example:
http://example.com/directory/file.php
php.com Documentation:
$_SERVER — Server and execution environment information
explode — Split a string by a string
parse_url — Parse a URL and return its components (possibly a better solution)
Solution:
echoparse_url($_SERVER["REQUEST_URI"], PHP_URL_PATH);
Here is a solution that takes into account different ports and https:
$pageURL = (#$_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://';
if ($_SERVER['SERVER_PORT'] != '80')
$pageURL .= $_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'].$_SERVER['PHP_SELF'];
else
$pageURL .= $_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'];
Or a more basic solution that does not take other ports into account:
$pageURL = (#$_SERVER['HTTPS'] == 'on') ? 'https://' : 'http://';
$pageURL .= $_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'];
I actually think that's not the good way to parse it. It's not clean or it's a bit out of subject ...
Explode is heavy
Session is heavy
PHP_SELF doesn't handle URLRewriting
I'd do something like ...
if ($pos_get = strpos($app_uri, '?')) $app_uri = substr($app_uri, 0, $pos_get);
This detects whether there's an actual '?' (GET standard format)
If it's ok, that cuts our variable before the '?' which's reserved for getting datas
Considering $app_uri as the URI/URL of my website.
$uri_parts = explode('?', $_SERVER['REQUEST_URI'], 2);
$request_uri = $uri_parts[0];
echo $request_uri;
You can use $_GET for url params, or $_POST for post params, but the $_REQUEST contains the parameters from $_GET $_POST and $_COOKIE, if you want to hide the URI parameter from the user you can convert it to a session variable like so:
<?php
session_start();
if (isset($_REQUEST['param']) && !isset($_SESSION['param'])) {
// Store all parameters received
$_SESSION['param'] = $_REQUEST['param'];
// Redirect without URI parameters
header('Location: /file.php');
exit;
}
?>
<html>
<body>
<?php
echo $_SESSION['param'];
?>
</body>
</html>
EDIT
use $_SERVER['PHP_SELF'] to get the current file name or $_SERVER['REQUEST_URI'] to get the requested URI
Not everyone will find it simple, but I believe this to be the best way to go around it:
preg_match('/^[^\?]+/', $_SERVER['REQUEST_URI'], $return);
$url = 'http' . ('on' === $_SERVER['HTTPS'] ? 's' : '') . '://' . $_SERVER['HTTP_HOST'] . $return[0]
What is does is simply to go through the REQUEST_URI from the beginning of the string, then stop when it hits a "?" (which really, only should happen when you get to parameters).
Then you create the url and save it to $url:
When creating the $url... What we're doing is simply writing "http" then checking if https is being used, if it is, we also write "s", then we concatenate "://", concatenate the HTTP_HOST (the server, fx: "stackoverflow.com"), and concatenate the $return, which we found before, to that (it's an array, but we only want the first index in it... There can only ever be one index, since we're checking from the beginning of the string in the regex.).
I hope someone can use this...
PS. This has been confirmed to work while using SLIM to reroute the URL.
I know this is an old post but I am having the same problem and I solved it this way
$current_request = preg_replace("/\?.*$/","",$_SERVER["REQUEST_URI"]);
Or equivalently
$current_request = preg_replace("/\?.*/D","",$_SERVER["REQUEST_URI"]);
It's shocking how many of these upvoted/accepted answers are incomplete, so they don't answer the OP's question, after 7 years!
If you are on a page with URL like: http://example.com/directory/file.php?paramater=value
...and you would like to return just: http://example.com/directory/file.php
then use:
echo $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['SERVER_NAME'].$_SERVER['PHP_SELF'];
Why so complicated? =)
$baseurl = 'http://mysite.com';
$url_without_get = $baseurl.$_SERVER['PHP_SELF'];
this should really do it man ;)
I had the same problem when I wanted a link back to homepage. I tried this and it worked:
<a href="<?php echo $_SESSION['PHP_SELF']; ?>?">
Note the question mark at the end. I believe that tells the machine stop thinking on behalf of the coder :)
I've recently run into a bug in PHP 7.1 which seems to have come back after being fixed in PHP 5.4.7
The problem is simply that if you pass a url to parse_url() and the url doesn't have a scheme it will return the whole url as if it's just a path. For example:
var_dump(parse_url('google.co.uk/test'))
Result:
array(1) { ["path"]=> string(12) "google.co.uk/test" }
While in reality here it should split into its domain and path.
I run parse_url a few ten million times a day as part of url decryption / encryption functionality. I'm looking for a fast way to fix this edgecase bug or have a reliable alternative to parse_url.
Edit:
Thanks for the helpful responses, here's the solution I used in the end, I hope it helps someone. I won't submit it as an answer because I already marked someone else as correct (which they are) which allowed me to write this.
$parsedUrl = parse_url($uri);
// if the uri has no scheme, it won't think there's a host and will give bad results
if ($parsedUrl !== false && !isset($parsedUrl['host'])) {
// double slash prepended will parse $uri as if it has a schema and no schema will be in the result
$parsedUrl = parse_url('//' . $uri);
}
if ($parsedUrl === false) {
throw new MalformedUrlException('Malformed URL: ' . $uri);
}
// use parsed url as needed
parse_url needs to have information if the given string is the beginning of a url.
this is why parse_url('//domain/path') works -> it will just not output any schema.
now to describe the problem you want to be solved: php would need to know every domain there is and to then be able to decide if this is what the user wanted (basically impossible)
Take for example the following url: 'http://whois.domaintools.com/test.at' -> if I only pass the path it will write 'test.at' -> is this now a path or domain?
I have (maybe) an unusual issue with using __FILE__ in a file within a file.
I created a snippet of code (in the php 5 my server mandates) to take elements of the current filename and put it into a variable to use later. After some headache, I got it working totally fine. However, I realized I didn't want to have to write it every time and realized "oh no, if I include this it's only going to work on the literal filename of the include". If I wanted to grab the filename of the page the user is looking at, as opposed to the literal name of the included file, what's the best approach? Grab the URL from the address bar? Use a different magic variable?
EDIT1: Example
I probably should have provided an example in the first draft, pfft. Say I have numbered files, and the header where the include takes place in is 01header.php, but the file it's displayed in is Article0018.html. I used:
$bn = (int) filter_var(__FILE__, FILTER_SANITIZE_NUMBER_INT);
…to get the article number, but realized it would get the 1 in the header instead.
EDIT2: Temporary Solution
I've """solved""" the issue by creating a function to get the URL / URI and putting it into the variable $infile, and replaced all former appearances of __FILE__ with $infile, like so:
function getAddress() {
$protocol = $_SERVER['HTTPS'] == 'on' ? 'https' : 'http';
return $protocol.'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];}
$infile = urlencode(getAddress());
$bn = (int) filter_var($infile, FILTER_SANITIZE_NUMBER_INT);
echo "$bn";
So if the file the user is looking at is called "005-extremelynormalfile.html", I can display the number 5 inside the page, e.g., to say it's article number five.
While it's not as bad as I initially thought based on your description your code is still very fragile, and really only works by accident. If you have any other digits or hyphens it's going to go wrong, as below.
$infile = 'https://example-123.com/foo/42/bar/005-extremelynormalfile.html?x=8&y=9';
var_dump(
filter_var($infile, FILTER_SANITIZE_NUMBER_INT),
(int)filter_var($infile, FILTER_SANITIZE_NUMBER_INT)
);
Output:
string(12) "-12342005-89"
int(-12342005)
Sanitize functions are a blunt instrument for destroying data, and should only ever be used as a last resort when all other good sense has failed.
You need to use a proper parsing function to parse the url into its component parts, and then a simple regular expression to get what you want out of the filename.
function getIdFromURL($url) {
$url_parts = parse_url($url);
$path = $url_parts['path'];
$path_parts = explode('/', $path);
$filename = end($path_parts);
if( preg_match('/^(\d+)/', $filename, $matches) ) {
return (int)$matches[1];
}
return null;
}
var_dump(
getIdFromURL($infile)
);
Lastly, a lot of people are tempted to cram as much logic as possible into a regular expression. If I wanted to the above could be a single regex, but it would also be rigid, unreadable, and unmaintainable. Use regular expressions sparingly, as there's nearly always a parser/library that already does what you want, or the majority of it.
Quickly threw together a function that gets the url from the page as a variable, and replaced all occurrences of __FILE__ with that variable, and it worked correctly. Assuming the user cannot edit the URL / URI in any way, this should work well enough.
As a novice and beginner php learner, I'm using the Code-Canyon Premium URL Shortner script and done 2 days of research. Unfortunately I am unable to resolve my issue.
The url shorten script is urlencoding the API url that it sends to the script, In doing this it is replacing the & symbols with & causing the url to not work correctly on the final destination page.
I have tried to use preg_replace, str_replace and also tried to use urldecode on the destination page but none of these seem to work. Here is my current script:
$makeshort = "http://mywebsite.com/email/quote.php?quoteid=$visitor&customertype=fhbs";
$mkshrt = str_replace("/&/","%26",$makeshort);
$short = "http://shorturl.com/api?&api=REMOVED&format=text&url=".urlencode($mkshrt);
// Using Plain Text Response
$api_url = $short;
$res= #file_get_contents($api_url);
if($res)
$shorturl = $res;
$shorty = json_decode($shorturl);
$shorturl = $shorty->{'short'};
echo $shorturl;
Note: Where you see &format=text in the api url, I have tried to use it with and without the &format=text however this makes no difference what so ever.
I am hoping that there could be a simple and quick way to resolve this issue as I am only passing over 2 variables and its the second variable that is being displayed like this:
mywebsite.com/email/quote.php?quoteid=01234567890&customertype=fhbs
So the customertype variable is the one being messed up due to the amp; symbol.
I sincerely hope someone with the expertise could advise me on the best approach or even a simple way to resolve this issues as I really am at my whits end! MY knowledge is not good enough to research the exact key phrases in order to point myself in the right direction.
Thanks for your time in reading this and I hope someone would be kind enough to help me out here.
I know the feeling as i myself am just becoming to terms with coding and developing.
I personally would solve this by one of two ways, If you have tried to already use htmlspecialchars or htmlentities along with urldecode then the most simple and quickest way to achieve this would be to read the URL string then replace the &symbol with the & using str_replace and do either a meta refresh of the page or `header location redirect
Here is what i mean with a breif example however one must stress that some extra security maybe needed and this is ONLY a quick fix not a secure stable and permanent fix, Though one could play with this and maybe work something out for your own circumstances.
$url = "http://". $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
if(strstr($url, "&")){
$url = "http://". $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
$url = str_replace('&', '&', $url);
echo "<meta http-equiv='refresh' content='0;URL=$url'>";
exit;
}
Alternative way with header location:
$url = "http://". $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
if(strstr($url, "&")){
$url = "http://". $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
$url = str_replace('&', '&', $url);
header("Location: $url");
exit();
}
This will totally remove any & symbols from the url and replace them with &.
You can also play around with this to remove even more from the url string and replace things like / or forbidden words.
An example of the output will look like this:
Original url causing the problems:
http://mywebsite.com/email/quote.php?quoteid=1234567890&customertype=fhbs
New url after the script has executed and refreshed the page:
http://mywebsite.com/email/quote.php?quoteid=1234567890&customertype=fhbs
As you can see from the hyperlinked text above, The ampersand breaks the string and everything after that is not read correctly but when this script executes and refreshes the page the url will be just like the second hyperlink thus making the url work for what you require.
NOTE: THIS IS NOT A SECURE WAY OF DOING THINGS AND MAY NO BE IDEAL FOR YOUR CIRCUMSTANCES, THIS IS JUST AN IDEA AND HOPE THIS HELPS!
Thanks.
I am trying to fetch a variable address from my current URL using JRequest::getVar('address') method.
But if the address value has a (#) character, the part after the # character is not retrieved.
I understand that URI is a combination of query + fragment and the part after a hash symbol is treated as a fragment.
I have tried to use urlencode method but it still doesn't solve the problem.
Can anyone please tell me how to solve the issue?
What is the problem with using urlencode? It should replace # with %23 and all should be well. You can try JRequest::getVar(str_replace('#', '%23', 'address')) which should do the trick. Can you post an example URL that doesn't get properly urlencoded?
I guess you will have to replace the hash-symbol on your own. For example:
str_replace($the_url, '#', '-');
I don't know, where exactly you have to do that, because I don't know how the Joomla!-Framework handles links and urls. But I am sure, that someone else can help here any further...
Encode the Hash in the URL with a %23 replacement
http://twitter.com/home?status=I+believe+in+%23love
"I believe in #love"
The part after # is never sent to Apache/PHP, and can therefore not be retrieved by a PHP script. What you need to do, is to url encode the ADDRESS parameter of the URL.
test.com/index.php?ADDRESS=<?= urlencode('101 Street #6 City') ?>
That code will generate the following url
test.com/index.php?ADDRESS=101+Street+%236+City
Now on this URL, you can retrieve address with JRequest::getVar('ADDRESS')
Check this Joomla doc out. You can retrieve what Joomla call the 'fragment' by doing:
$uri = 'http://fredbloggs:itsasecret#www.example.com:8080/path/to/Joomla/index.php?task=view&id=32#anchorthis';
$u =& JURI::getInstance( $uri );
echo 'Fragment is ' . $u->getFragment();