We currently have a full Angular project running in a sub-dir on our server and a physical "device" using a hardcoded URL to send a user to that page.
I'm looking for some kind of way to "intercept" the request via a PHP script first to (for example, not the real purpose) see if the requested "ID" param for that browser page has enabled the option to view the browser page or if it has been configured by the user to return a 406 HTTP response (for example).
Currently:
- ..com/app/routing-view?id=1234 => Angular view -> fetch info
Idea:
- ..com/app/routing-view?id=1234 => PHP-script -> isValid => forward to angular and do a normal 'webview' -> fetch info
- ..com/app/routing-view?id=2889 => PHP-script -> notValid => HTTP code
I thought about having a .htaccess "intercept" the url and forward it to a .php file. Do the magic and checks there, and then forward the browser to the original url, but to "bypass" the previous interceptor.
It's about that last part that I'm currently having issues. Because it's Angular and it is using paths, I can't just say "okay, redirect to index.html instead of index.php" because it would need to be something like ..com/app/routing-view?id=1234 (and the index.html is located in the /app directory.
I don't want to add PHP code to the original Angular-index file if that could be avoided.
Am I looking at this right or would there be a different, more efficient way to tackle this?
The reason for all this is that I want to (for example) return a different HTTP code or different headers to the device instead of a 200 html header response even if the ID turned out to be disabled or something like that.
Got it to work via a simple .htaccess, a parameter and an "interceptor" script. Quite simple and basic really, not sure why my brain didn't go this route before posting my question.
Added the .htaccess to the root of the Angular application with the following code.
RewriteEngine On
# Check if the request has been intercepted before (via URL parameter)
RewriteCond %{QUERY_STRING} !(^|&)intercepted=true
# .. If not, rewrite the page to use the interceptor script (only if it matches the route).
RewriteRule ^my-route dir-of-script/extra/interceptor.php?url=https://%{HTTP_HOST}%{REQUEST_URI}?%{QUERY_STRING} [L,QSA]
# Other stuff for rewriting the Angular routes etc
...
Added a /dir-of-script/extra/interceptor.php like-script that parses the URL from the GET parameter, fetches the info, does the checks and depending on the result, returns the output or redirects the page and let it through.
This adds a ..&intercepted=true parameter to the original URL so that the .htaccess doesn't intercept it again.
This seems to be working like a charm (for my situation). The only "downside" is that this counts as a redirect and not just a rewrite when it was allowed to go through. Will look further into it, to maybe let the PHP script "serve" the Angular content instead of redirecting to it.
Related
I want to make user-friendly API for my service. I am trying to make it like Discord API - https://example.com/api/accounts/<account ID>/<stuff>/, some expected link examples below:
https://example.com/api/accounts/1234567890/data/
https://example.com/api/accounts/1234567890/inventory/
https://example.com/api/accounts/1234567890/servers/
I tried to make some htaccess tricks, but without any result - website got corrupted (just white page without anything) or account ID was considered as folder (HTTP 404, because I don't want those IDs as folders).
Thank you in advance for your response
Edit 1:
File structure can be really any, I just want it working. But most expected by me would be
api
- accounts
- data
- inventory
- ...
- server (example)
- game (example)
Edit 2:
My API is OOP - so I can call it from any place. I just need to get data and create new object and call some functions. In my bad-looking API, link was like: https://example.com/api/accounts/data.php?id=123456789 and in that script I call $stuff = new StuffObj($id, $other, $stuff, $from, $post); and function like $stuff->execute();. But with new API I can just make GET var, like action and in switch choose what object to use.
In my bad-looking API, link was like: https://example.com/api/accounts/data.php?id=123456789
In that case, to implement a "pretty" URL of the form /api/accounts/<id>/data/, you would do something like the following using mod_rewrite in your /api/.htaccess file:
Options -MultiViews
RewriteEngine On
RewriteRule ^accounts/(\d+)/data/$ accounts/data.php?id=$1 [L]
To make this more "generic", to rewrite a URL of the form /api/accounts/<id>/<action>/ to /api/accounts/<action>.php?id=<id>, assuming <action> would only consist of lowercase letters then you could change the above RewriteRule to read:
RewriteRule ^accounts/(\d+)/([a-z]+)/$ accounts/$2.php?id=$1 [L]
Although in your file structure you appear to have "subdirectories"(?) of the /accounts directory that also match the basename of the .php file? If so, this could be problematic, hence why I have disabled MutliViews above.
But with new API I can just make GET var, like action
Yes, you could - and would perhaps be preferable - everything is managed by a single entry point (eg. index.php - but you can call it anything your like) - However, you need to be specific and decide on this before implementing the "pretty URL" - which is really just cosmetic fluff. In fact, if this is just an API, do you need to implement a "pretty URL" at all?
I would like to be able to use jQuery $.post with url segments as follows:
www.mysite.com/stats/user1
www.mysite.com/stats is the landing page, with this code on it:
var user = //get user1 from the url;
$.post('stats.php', {username : user}, function(results){...});
The username should be posted to a PHP backend which then does some database querying.
Is this possible? I might be able to use .htaccess to redirect users from stats/user1 to stats/, but I don't have much experience in this area.
Many thanks in advance for your help.
EDIT
In response to Loopo's answer:
I can use .htaccess to rewrite incoming URLs as follows:
RewriteRule ^/stats/(.*)$ stats.php?username=$1 [L].
This would allow me to enter a URL such as mysite.com/stats/user123, which the server would interpret as mysite.com/stats?username=user123
In stats.php can I then use $user = $_GET['username']?
It seems you are mixing some concepts up.
If you want to pass data to a webserver, you can do it in two ways; POST or GET. (There is also PUT and DELETE but we'll ignore that here.)
If you are using a GET request, the data is in the URL, normally in a format like
mysite.com/mypage.php?param1=value1¶m2=value2....
the slashes normally act as a path separator to tell the webserver where to look for the resource that answers the request.
mysite.com/myapp/myfolder/resources/logo.png
would tell the server where to find and then send the file logo.png to the client.
If you want to have parameters in the path, you can also use redirection (.htaccess) to have virtual resources.
as in your example.
www.mysite.com/stats/user1
there is no stats folder with a script for every user.
You'll have to tell your webserver when someone asks for some path that looks like
/stats/<something>
the request should be served by some script (probably 'stats.php') and the parameters that are passed to the script will be <something>
in your .htaccess this might look like:
RewriteRule ^/stats/(.*)$ stats.php/$1 [L]
In a POST request the parameters are not visible in the url.
So your stats.php would have to be called without the username in the URL, but instead in the POST variables, i.e. in your case POSTing to stats.php/user1 and then including the username again in the POST variables is redundant.
So your stats.php could deal with a POST request by reading in the parameters and creating/updating a new user with the values provided in the POST parameters, while dealing with GET requests by returning the user's stats as they are now.
What I am describing is REST, see also
.htacesss
RewriteCond %{REQUEST_URI} ^/api/(.+)$
RewriteRule ^api/(.+)$ /index.php?api=%1 [QSA,L]
example ajax url request:
'http://hostname.com/api/ext/list.php?query=de'
I want to be able to redirect urls in this format to the following
index.php?api={requested_filename}¶m1=value1¶m2=value2 ...
because the whole site is processed through a bootstrap process in index.php which has a routing part loading configs, templates etc...
When I try a jquery code for example, the POST data is lost after redirect.
$.ajax({
url: '/api/contact.php',
type: 'POST',
data: {
email: $("#contactEmail").val(),
name: $("#contactName").val(),
message: $("#contactMessage").val()
// etc ...
}
});
I've read that you cannot preserve data on a http redirect. But how do all the frameworks avoid that? I've coded in many, and every one is bootstraped through the index.php and there are rewrite rules in the .htaccess file for enabling pretty urls. So in Yii for example, I would call an url "api/uploads/latests.json" with some POST data and the controllers on the backend would receive that data. What am i missing here?
note: I've tested the [P] mod_rewrite parameter, and i think that this server doesn't have mod_proxy enabled.
There is a difference between a rewrite and a redirect.
Rewrite is an apache (and other servers) module that will follow a set of cond/rules to map a requested url to files on the server (ex: a bootstrap rewrites all urls to a single file, usually index.php. A mvc might map /model/controller/view uri to an index.php that calls the appropriate mvc files).
A redirect actually changes the page you are on. Someone requests page A.php and that page says "what you are looking for is on B.php" and so your browser goes to B.php.
A rewrite will preserve post parameters because the url doesn't change. A rewrite will just change the script being requested, but to the browser it looks like the page still exists at the requested url.
A redirect will not preserve post parameters because the server will redirect you to another page completely.
What it appears you are trying to do is a rewrite, not a redirect. You should have no problems getting the post parameters.
To fix this, how are you checking in index.php that there are no post parameters? Are you sure the controller you are expecting is getting called?
All POST data is lost on redirect. There is no way to preserve it via htaccess rewrite/redirect rules.
The redirect (all 301,302,303) received by the client (all major browsers I know) is treated as a new url to make a GET request to. Browsers won't automatically tack on old post parameters to this URL--even if the source of the redirect was a POST request.
The only way I've every found around this is to do the rewrite inside code and covert the POST parametes to GET parameters and stick them on the end of the new url. In php you then issue a header location change (or whatever redirect call your library of choice uses):
header("Location: http://www.example.com/?my_old_post_args=123");
exit;
for any one have this problem i have the sam problem and i use
some thing like this
RewriteRule ^services/MainService/(.*)$ http://193.9.162.91/mobile-feed/mobile.list.news.images.php?original_request=$1 [R=301,L]
this will not work with ajax post i have to chnage the RewriteRule to
RewriteRule ^services/MainService/(.*)$ http://193.9.162.91/mobile-feed/mobile.list.news.images.php?original_request=$1 [QSA,L]
this work
and in the php file i have
$inputJSON = file_get_contents('php://input');
$input= json_decode( $inputJSON, TRUE ); //convert JSON into array
print_r($input);
this is my first post so go easy on me.
Basically I am doing some rewrites in my htaccess file to change my made up search friendly URLs into actual URLs, and for the most part they are working. For instance this:
http://www.negativeworld.org/7849/news/nintendo-download-for-may-24-2012
Will turn into this:
http://www.negativeworld.org/article.php?id=7849
Just fine... IF that article exists. If the article doesn't exist, the php code uses this:
header("Location: boarderror.php");
exit;
To bring the user to boarderror.php. This works fine if it the user gets there directly on article.php and the id is bad, but when I am trying to do the htaccess redirect from a search friendly url and the id is bad, the htaccess redirect just hangs for awhile before giving me this message: "The page isn't redirecting properly".
What I want is for it to go to my boarderror.php page when there is a bad id. So basically I want my htaccess page to take a server friendly URL, switch to the true URL, and well... just let go at that point, and the PHP will take it from there. Here is my htaccess line that does the switch:
RewriteRule ^([0-9]+)/(news|review|editorial|podcast)/(.*)$ /article.php?id=$1 [L]
What am I doing wrong? (BTW I realize that if I set up all of my search friendly URLs correctly there should never be a bad id anyway, but I want to be on the safe side...)
Your thoughts aren't wrong. For a wrong ID there is a double redirection which is OK. The problem is how the second redirection happens. Try
header("Location: http://www.negativeworld.org/boarderror.php");
or
header("Location: /boarderror.php");
With your redirection the browser is trying http://www.negativeworld.org/9999/news/boarderror.php (being 9999 the wrong ID) which falls in an endless redirection loop that the browser cuts after 10 tries.
The redirect rule is fine, the issue is in your header function call. When you only provide a file name, the header redirect will send the user to the file in the same folder, much like creating an html link using only the filename.
Let's say i try to load http://www.negativeworld.org/99999/news/nintendo-download-for-may-24-2012 and that id is invalid. In this case it would send send the user to http://www.negativeworld.org/99999/news/boarderror.php which triggers the redirect again and gets stuck in an infinite loop (or would if the browser wasn't smart enough to stop requesting the same URL over and over again).
Per RFC 2616 the location header should provide an absolute URI, so you should do something like this:
header("Location: http://www.negativeworld.org/boarderror.php");
exit;
I am working with PHP5.3.6 on Windows 2008R2.
In Wordpress, I can set all kinds of friendly URLs which ultimately route to one PHP page. From the outside, it looks like many pages, but is only one.
In the web.config file (or .htaccess) file, there is only one instruction as opposed to having one entry per page/article.
This means that somewhere PHP is looking at the URL, comparing it to the database (where the article titles exist) and then routing transparently to the page.
All of this is transparent to the end user.
How is this accomplished in a non wordpress PHP site?
Here's a related answer that touches on how to do that. In brief, you'll want to check the $_SERVER['REQUEST_URI'] and just parse that.
Here's a simple example of parsing the request (MVC routers are usually configurable, and can route and match for many different URI structures):
If your format is something like news/article-slig you can do this (example code, there are less rigid ways to do this):
list($section, $slug) = explode('/', trim($_SERVER['REQUEST_URI'], '/'));
At this point your PHP script knows how to interpret the request. If this were a full blown MVC application, the router would load the matching controller and pass the request data to it. If you're just doing a simple single page script, loading some data, then your DB calls would follow.
If the request is invalid, then a simple header() call can notify the browser:
header('HTTP/1.0 404 Not Found');
And any data output would be the content of your 404 page.
I can't vouch for wordpress, one method I have used is to redirect 404's in .htaccess to index.php and then have that file sort by parsing:
$sub = $_SERVER['SERVER_NAME'];
$file = $_SERVER['REQUEST_URI'];
$sub can be used to mask non existant subdomains to a specific file. $file can be used in a switch or if clause to include / redirect based on file name.
Obviously, you need to make sure that the alias' are not actual files in your doc root.
Its called Routing(you can also check info about Front Controller pattern). You can write your own implementation by redirecting all your requests to single file using server settings and parse request in this file. You can also check, for example, Zend_Controller_Router docs and sources to understand how it works.
http://framework.zend.com/manual/en/zend.controller.router.html
http://framework.zend.com/manual/en/zend.controller.html