I created a blank new project on Angular 4 (with angular-cli) in order to try to use it with PHP Routes, I'm using Phroute Fast route.
Before trying this I used to call the whole file with a param to call a specific function, like this:
angular service
apiGet(): any {
return this._http.get('api/server/user.php?action=getUser');
}
I tried to install the Phroute but it didn't worked, when I try to call it like the code bellow, I get the following error:
apiGet(): any {
return this._http.get('api/user');
}
GET http://localhost/api/index.php net::ERR_TOO_MANY_REDIRECTS
Folder structure:
api/
server/ (used to call files with extensions)
vendor/
index.php
index.html
bundle.js
[..other angular files..]
index.php
require 'vendor/autoload.php';
function processInput($uri) {
$uri = implode('/', array_slice(
explode('/', $_SERVER['REQUEST_URI']), 3
));
return $uri;
}
function processOutput($response){
echo json_encode($response);
}
$router = new Phroute\RouteCollector(new Phroute\RouteParser);
$router->get('user', function(){
return 'Hello, PHRoute!';
});
$dispatcher = new Phroute\Dispatcher(router);
try {
$response = $dispatcher->dispatch($_SERVER['REQUEST_METHOD'], processInput($_SERVER['REQUEST_URI']));
} catch (Phroute\Exception\HttpRouteNotFoundException $e) {
var_dump($e);
die();
} catch (Phroute\Exception\HttpMethodNotAllowedException $e) {
var_dump($e);
die();
}
processOutput($response);
.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} api
RewriteRule ^ /api/index.php [L,R]
# This code needs to be used in order to enable refresh
# and redirects on the Angular routes
RewriteBase /
RewriteRule ^index.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
Note: Keep in mind I'm very new to this PHP route concept, so any other advice is also welcome!
So I'd like to know how do I properly configure this to make it work? I didn't found any tutorial on this topic, so it was very confusing to me.
Related
I have a very simple Slim app that works fine on my Ubuntu machine but I get an error 500 when I deploy it to a Hostgator shared account using a subdomain.
I suspect the problem lies in my .htaccess file.
The structure of my files is:
project/
├──api/
│ ├── .htaccess
│ ├── services.php
├──src/
├──vendor/
My Slim app (services.php):
<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
require_once '../src/vendor/autoload.php';
$c = new \Slim\Container();
$c['notFoundHandler'] = function ($c) {
return function ($request, $response) use ($c) {
return $c['response']
->withStatus(404)
->withHeader('Content-Type', 'text/html')
->write('Invalid endpoint');
};
};
$app = new \Slim\App($c);
$app->post('/myEndpoint', function (Request $request, Response $response, array $args) {
if($request->getHeader("key") != null && $request->getHeader("key")[0] == "123456789="){
$reqdata = $request->getParsedBody();
$data = $reqdata['data'];
return json_encode('{"data":'.$data.',"response":"OK","errorcode":"0"}');
} else {
return '{"data":"","response":"Access denied","errorcode":"9999"}';
}
});
$app->run();
My .htaccess file:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . services.php [QSA,L]
</IfModule>
# Use PHP71 as default
AddHandler application/x-httpd-php71 .php
<IfModule mod_suphp.c>
suPHP_ConfigPath /opt/php71/lib
</IfModule>
I created a subdomain (api.mydomain.com) with project/api/ as document root.
When I make a POST request in my local installation to
127.0.0.1/api/services.php/myEndpoint
works as expected and returns the data. However, when I make the same request to my Hostgator subdomain:
api.mydomain.com/services.php/myEndpoint
I get the error 500.
Note that if I add a simple test.php file to my api/ directory that only prints something, e.g.
<?php
echo "OK"
?>
and I go to api.mydomain.com/test.php, it works fine and prints the string.
What do I need to change or add in my .htaccess for my slim app to work?
I solved it by doing two things:
I moved my project folder to public_html, created again the subdomain and pointed it to the project directory.
I updated my .htaccess file IfModule mod_rewrite.c section. It now looks like this:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ services.php [QSA,L]
</IfModule>
The difference with the previous one is I added this line:
RewriteBase /
And this one:
RewriteRule . services.php [QSA,L]
updated to this:
RewriteRule ^ services.php [QSA,L]
I got the .htaccess fixes here:
https://discourse.slimframework.com/t/deploy-slim-project-to-hostgator-using-subdomain/3187/7
This piece of code was from an example at heroku. But except the route /, anything else I add does not work. It shows 404:
The requested URL /e was not found on this server.
$app->match('/', function(Symfony\Component\HttpFoundation\Request $request) use ($app) {
return $app['twig']->render('index.twig');
});
$app->match("/dump", function(Symfony\Component\HttpFoundation\Request $request) use ($app) {
return new Response('Thank you for your feedback!', 201);
})->bind("dump");
$app->get("/t", function() use ($app) {
return new Response('Thank you for your feedback!', 201);
})->bind("t");
$app->get("/d", function() {
return new Response('Thank you for your feedback!', 201);
})->bind("d");
$app->get("/e", function() {
return new Response('Thank you for your feedback!', 201);
});
$app->run();
Edit 1
I deployed it directly on heroku server (heroku auto build on each push to master branch)
Edit 2
my workspace:
bin\worker.php
www\index.php <== the snippet is from this file
www\list.php
apache_app.conf
app.php <== basic init, return Silex\Application $app
Procfile
The content of apache_app.conf is copied from this link.
RewriteEngine On
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^app\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L]
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .? - [L]
RewriteRule .? %{ENV:BASE}/app.php [L]
I figured that I need to change the apache config somehow, but I don't understand htaccess syntax.
For apache2, you can add a .htaccess file within "/web"
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
#RewriteBase /path/to/app
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
</IfModule>
and set your Procfile as:
web: vendor/bin/heroku-php-apache2 web/
For nginx, create a nginx conf file with content:
location / {
# try to serve file directly, fallback to rewrite
try_files $uri #rewriteapp;
}
location #rewriteapp {
# rewrite all to index.php
rewrite ^(.*)$ /index.php/$1 last;
}
location ~ ^/(index|index_dev)\.php(/|$) {
try_files #heroku-fcgi #heroku-fcgi;
internal;
}
and set Procfile as:
web: vendor/bin/heroku-php-nginx -C server_conf/nginx.conf web/
It's very simple, just install apache :
composer require apache-pack
I had the same issue, and it stumped me for weeks... to the point where I just started using / as my only route and adding other capability through passed-in variables. Drove me up the wall.
I finally had the need to fix it for real, and after a few hours found this post:
https://laracasts.com/discuss/channels/laravel/laravel-v5415-on-heroku-all-routes-but-not-working
TL/DR; I had duplicated a (correctly working) heroku repo to create my new one, and somewhere along the way my web/.htaccess file got deleted. I replaced it, and everything works like a charm.
For me the provided test also worked well (I'm using PHP): if eaxmple.com/ROUTE doesn't work, but example.com/index.php/ROUTE does work... you have an .htaccess problem.
Also, for reference, here's my entire .htaccess file:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
Hopefully this saves someone some searching...
it's my first post, so tell me if i've done something wrong.
i'm trying to understand logic of big routers on github and frameworks.
I understand to routers that works like this:
folder structure:
*controllers/Home.php
*index.php
index.php file, orientation code:
$uri = www.xyz.com/home/default/param;
# get parts from url
$parts = explode("/", $uri);
# call controller
$controller_class = "controller_namespace\\".$parts[0];
$controller = new $controller_class;
call_user_func_array(array($controller, $parts[1]), $parts[2]);
.htaccess file:
Options -MultiViews
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
so on page www.xyz.com/home/default/param is called controller class home and func. default with params, in filestructure you are still on index.php file, only different controller classes is being called by url.
So, routers that i want understand works like:
class Home{
Router::get("/default", function(){
echo 'Hello';
});
Router::Dispatch();
}
From code that i found on github here etc. i think, the Router loads all the functions from controller and execute that one which match the url ...huh?
Q:
How i can execute the controller class above, when im still on index.php?
My Code
RewriteRule ^walls/([0-9a-zA-Z-_]+) display.php?art_nm=$1 [NC,L]
What i get is:
website.com/walls/i_love_coding
what i need is:
website.com/i_love_coding
You probably should use the front controller pattern. Basically, you give every request to your front controller which decide what to do.
.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . /index.php [L]
</IfModule>
Then, use your "front controller" to forward request to correct script according to $_SERVER['REQUEST_URI'].
index.php
<?php
$name = trim($_SERVER['REQUEST_URI'], '/');
$page = find_page_by_name($name);
if ($page) {
require $page;
} else {
require __DIR__.'/errors/404.php';
}
Be carrefully in the find_page_by_name function to not return the path of an unauthorized file; you should ensure your path is within a specific directory (see realpath and strpos).
For example, an attacker could try to get http://example.com/../../etc/passwd !!!
For more complex routing, you should probably try a micro-framework like Silex or Slim.
I have an index.php file in /api folder on my server. And I'm beginning with Slim and I'm trying to make a REST api.
So in my index.php I've got this:
$app->get('/', function() use ($db) {
echo "Get";
});
$app->post('/', function() use ($db) {
echo "Post";
});
$app->get('/test', function() use ($db) {
echo "Test";
});
And in my .htaccess file, as it was downloaded:
RewriteEngine On
# Some hosts may require you to use the `RewriteBase` directive.
# If you need to use the `RewriteBase` directive, it should be the
# absolute physical path to the directory that contains this htaccess file.
#
# RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
If I make a GET call to ../api/ I've got "Get", the post call works fine too, but if I make .../api/test call I've got a 500 Internal Server error.
What am I doing wrong?
Thank you!