I developed a REST API using php and slim, I am trying to optimize it , for a simple empty request with slim I have 56requests per second , and if I don't use slim I have 259r/s .
What Should I do to reach 259r/s with Slim
-- Index.php
use \Slim\App;
$container=include('Config/Container.php');
$app = new App($container);
$app->get('/metro',function(){
echo "metro";
});
-- container.php
$config = [
'settings' => [
'displayErrorDetails' => true,
'mode'=>'developpement',
'determineRouteBeforeAppMiddleware' => true,
'addContentLengthHeader' => false,
]
];
.htacess
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [QSA,L]
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
php_flag display_errors 1
All frameworks are by definition slower than no-code as there's more going on.
i.e.
<?php
echo 'metro';
is going to be much faster than a Slim application with this code:
use \Slim\App;
$config = include 'Config/Container.php';
$app = new App($config);
$app->get('/metro', function($request, $response){
return $response->write("metro");
});
$app->run();
This is because the Slim application is doing a lot more to enable it to respond to different URLs (routing) and handle error situations. That is the first block of code will not send back a 404 if you go to the /foo URL.
To compare, you need to make the "non-framework" version have the same functionality as the Slim version. The performance difference will be much smaller.
Related
I'm new to CakePHP. I have a website that was built by someone else in CakePHP 3.3.16. There are links to website.com/page and also website.com/page/.
What's the best way to get /page/ redirecting to /page without affecting anything else that might start with a /page/?
The route.php has this...
$routes->connect('/page/*', ['controller' => 'Page', 'action' => 'something']);
Then I have a PageController.php which has
public function something($site_id = null)
{
...
}
Will this work in the routes.php? How would I specify that this is a 301 redirect?
use Cake\Routing\RouteBuilder;
Router::scope('/', function (RouteBuilder $routes) {
$routes->redirect('/page/','http://website.com/page');
$routes->connect('/page/?*', ['controller' => 'Page', 'action' => 'something']);
});
This doesn't seem to work in the .htaccess (/page/ is displayed and not redirected)...
Redirect 301 /page/ http://website.com/page
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
</IfModule>
as a first glimpse to fix this would be instead of putting the Route::scope would be Router::connect and Router::redirect imo.
Therefore, an approach to a solution would be first doing something like this.
Router::connect('/page/*', ['controller' => 'Page', 'action' => 'something']);
And then you redirect the page with the cake command redirect:
Router::redirect('/page/','/page', array('status' => 301));
In the project that I use which is CakePhp 2.6, I always have redirected pages like this depending on the task. Sometimes you can do this type of redirects inside the Controller but it is best to avoid it for not mixing routing with programming logic.
I am using slim framework to write my own API and everything is just fine but when I add the slim-basic-auth library to secure my API and test it .... I always get this error :
Uncaught Error: Class 'Tuupola\Middleware\HttpBasicAuthentication' not found in
D:\xampp\htdocs\mydatabase\public\index.php:22
Any help with that please ?
I installed the library and use it just like in tutorial
$app->add(new Tuupola\Middleware\HttpBasicAuthentication([
"secure"=>false,
"users" => [
"userName##" => "password##" ]
]));
you are missing backslash
new Tuupola\Middleware\HttpBasicAuthentication
=>
new \Tuupola\Middleware\HttpBasicAuthentication
For anyone dealing with this issue: In addition to registering the middleware in your Middlewares.php (or where your $app = new Slim\App; is defined):
return static function (App $app, Closure $customErrorHandler): void {
<...>
$app->add(new \Tuupola\Middleware\HttpBasicAuthentication([
"users" => [
"somebody" => "passw0rd"
]
]));
};
If you're using fast CGI you must add this line to your public/.htaccess file to avoid getting 401 even with valid auth:
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
Source: https://bugs.php.net/bug.php?id=67883
It's my first using slim 3 framework skeleton project, they say
There is also a skeleton project which will give you a quick-start for a sample application, so use that if you’d rather just have
something working rather than exploring how all the moving parts
work.
In real life it so hard to integrate JSON Web Token Authentication Middleware
I try to following step by step in tutorial but still not working.
Please help me ?
this is my code
middleware.php
$app->add(new \Slim\Middleware\JwtAuthentication([
"path" => "/",
"passthrough" => "/test",
"secret" => "thisissecret"
]));
and my / route
routes.php
$app->get('/',App\MemberController::class);
but the result is like this image below, 401: Unauthorized
You are misunderstanding the parameter secret. It is not the the token. It is the secret key you use to sign the token.
It is up to you how you generate the token. There is for example an online tool. You can also generate token with PHP.
use Firebase\JWT\JWT;
$payload = [
"sub" => "user#example.com"
];
$token = JWT::encode($payload, "thisissecret", "HS256");
Before using JWT is is good idea to read this introduction.
1. Generate Token
Using firebase/php-jwt
$payload = [
"sub" => "user#example.com"
];
$token = JWT::encode($payload,'JWT-secret-key');
2. .htaccess Changes
If using Apache add the following to the .htaccess file. Otherwise PHP wont have access to Authorization: Bearer header
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
3. Middleware
$app->add(new \Slim\Middleware\JwtAuthentication([
"path" => "/api",
"passthrough" => ["/test"],
"secret" => "JWT-secret-key",
"secure" => false,
"callback" => function ($request, $response, $arguments) use ($container) {
$container["jwt"] = $arguments["decoded"];
},
"error" => function ($request, $response, $arguments) {
$data["status"] = "0";
$data["message"] = $arguments["message"];
$data["data"] = "";
return $response
->withHeader("Content-Type", "application/json")
->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
}
]));
4. Correct Request
5. Wrong Token Request
Reference Link
if you are using apache server and serve over https protocol then your .htaccess file looks like
RewriteEngine On
RewriteCond %{HTTPS} On
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [L,QSA]
# Set the headers for the restful api
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "X-Requested-With, Content-Type, Accept, Origin, Authorization"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS, DELETE, PUT, PATCH"
I need a little help(I am not a pro),
My .htaccess file looks like this:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ url.php?p1=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)/([^/]+)$ url.php?p1=$1&p2=$2 [L]
and I would like to display the content on the basis of number of parameters (on the basis of type(in future))
What I wish to know is
$p1 = $_GET['p1'];
$p2 = $_GET['p2'];
if p2 = ""
{
echo "something";
}
else
{
echo "something";
}
Will the above code work without any issue?
What all errors can occur?
Is there a better way to handle this?
How wordpress handles this?
Note: I wish to display the contents on the basis of more than 3 params and type of params as well.
Generally speaking this isn't the greatest way to go about it. It's better to use a router which basically uses a single htaccess rule to catch all requests where a file/folder doesn't exist and then send them to a single php file. That file then initializes the router which figures out what the parameters are based on patterns matched against the request URI.
For example using the symfony/routing component in index.php:
// this is our index.php
// assuming we installed with composer
// and that the vendor dir is one level up from the document root
require_once __DIR__.'/../vendor/autoload.php';
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
// Create a Route Collection
$routes = new RouteCollection();
// lets use an array to define our routes
$routeDefinitions = array(
'foo_archive' => array(
// note the {} wraped parts are params
'path' => '/foo/{p1}/{p2}',
'defaults' => array('controller' => 'foo/archive.php'),
'requirements' => array(
// not a very specific match but lets pretend this matches a
// category or something
'p1'=> '[a-z0-9-_]+',
// matches a date
'p2'=> '[0-9]{4}-[0-9]{2}-[0-9]{2}',
)
// there are other things we can add like options, a requrired host,
// or a specific HTTP mehtod (PUT, GET, POST, etc.)
),
'foo_index' => array(
'path' => '/foo',
'defaults' => array('controller' => 'foo/index.php')
);
);
// let's add our routes
$routeReflector = new \ReflectionClass('Symfony\Component\Routing\Route');
foreach ($routeDefinitions as $name => $def) {
$routes->add($name, $routeReflector->newInstanceArgs($def));
}
$context = new RequestContext($_SERVER['REQUEST_URI']);
$matcher = new UrlMatcher($routes, $context);
$parameters = $matcher->match($_SERVER['PATH_INFO']);
/* so assuming PATH_INFO matched one of our patterns and its
requirements parameters will be an array -
lets pretend PATH_INFO had: /foo/bar/2014-04-20
so we would have an array like:
array(
'controller' => 'archive.php',
'_route' => 'foo_archive',
'p1' => 'bar',
'p2' => '2014-04-20'
)
*/
$controllersDir = realpath(__DIR__ . '/controllers');
$controller = $controllersDir . '/' . $parameters['controller'];
if (file_exists($controller) {
// include our controller and let it do its work
// note that normally you would be instantiating a controller object
// here and invoking some method on it, but for ease of example lets
// just assume it a normal php file with all the logic for the page
include($controller);
} else {
// generate a 500 or 404 error depending on how you want to handle
// it
}
And then your .htaccess would be something like:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php [QSA,L]
Alternatively, if you are open to it you could use a Microframework like Silex which would wire all this up for you and give an out of the box way to do things.
Silex Example (index.php):
// assuming we installed with Composer
// and that the vendor dir is one level up from the document root
require_once __DIR__.'/../vendor/autoload.php';
$app = new Silex\Application();
// you can define routes as closures like this but normally
// I prefer to use classes... You can look at the docs for
// how to do that: http://silex.sensiolabs.org/doc/usage.html#controllers-in-classes
$app->get('/foo/{p1}/{p2}', function($p1, $p2) use($app) {
// do whatever logic you need to do to render the page
});
$app->get('/foo}', function() use($app) {
// do whatever logic you need to do to render the page
});
$app->run();
I have the following url structures in my Yii2 application
http://127.0.0.1/frontend/web/index.php?r=site%2Flogin
http://127.0.0.1/frontend/web/index.php?r=site%2Fpage2
http://127.0.0.1/frontend/web/index.php?r=site%2Fsample
http://127.0.0.1/frontend/web/index.php?r=site%2Fsignup
How can I convert that URL to something like
http://127.0.0.1/login.php
http://127.0.0.1/page2.php
http://127.0.0.1/sample.php
http://127.0.0.1/signup.php
I should remove frontend/web/index.php?r=site%2F
I tried like and it didn't work
Options -Multiviews
RewriteEngine On
RewriteBase /
# Force search engines to use http://127.0.0.1/frontend/web/
RewriteCond %{HTTP_HOST} !^http://127\.0\.0\.1/frontend/web/$
RewriteRule ^(.*) http://127.0.0.1/frontend/web/$1 [R=301,L]
# Specify search friendly URLs
RewriteRule ^login\.php$ /index.php?r=site%2Flogin [L]
I also tried like and it didn't work too.
RewriteEngine on
RewriteRule ^frontend/web/index.php?r=site%2F([^\./]+) /$1.php [L]
No need to change .htaccess to achieve this. Adjust urlManager component.
Add this to your application config:
'components' => [
'urlManager' => [
'enablePrettyUrl' => true, // Cancel passing route in get 'r' paramater
'showScriptName' => false, // Remove index.php from url
'suffix' => '.php', // Add suffix to all routes (globally)
],
// Compare requested urls to routes
'rules' => [
'login' => 'site/login',
'page2' => 'site/page2',
'sample' => 'site/sample',
'signup' => 'site/signup',
],
],
As for removing controller part from all other routes - it violates key MVC concepts.
How you define to which controller requested action belongs in that case?
And what in case of actions with the same name?
For example: http://127.0.0.1/create.php - should it load site/create or users/create?
Also I don't sure if it's good practice, but you can write comparisons to all routes the same way with rules, but all action names should be unique.
Conclusion: you can modify urls to desired view as I mentioned above, but omitting controller names is only recommended for default controller (SiteController).
Official documentation:
UrlManager
$enablePrettyUrl
$showScriptName
$suffix
$rules
Routing and URL Creation