A login function writes a couple of session variables after successful authentication and then redirects to itself to print a welcome message (the view changes based on authentication status). This works fine with debug >= 0.
Now, when I add a CakeLog::write() to that same login function, it stops working with debug = 0 and an empty page is displayed. It continues working with debug > 0.
According to the Apache logs, the white page is the result of an error 500 following a POST request.
What does CakeLog::write() do apart from writing to a log file?
'Session', 'Security' and 'Auth' components are involved, but I do not call the requirePost method.
CakeLog::write() returns true if successful but catching the return code doesn't change the issue that further code execution is interrupted. I have to reload the white page in order to continue (i.e. replace the POST with a GET request).
Here is the users_controller's login:
function login(){
[if form contains data do some LDAP checking...]
if($permission>0){
$this->Session->write('logname', $samaccountname);
$this->Session->write('logperm', $permission);
[...]
// Here is where it blocks. Without this line debug=0 is okay
$result = CakeLog::write('log', $samaccountname);
$this->Auth->login();
// the Auth redirect target is set in the app_controller to allow jumping right
// to the originally intended URL, usually it redirects to itself
$this->redirect($this->Auth->redirect());
}
}
And this is the app_controller's beforeFilter:
function beforeFilter(){
$this->Security->blackHoleCallback = 'showErrorPage';
$this->Security->requireAuth();
$this->Security->requireSecure();
if($this->Session->read('logperm') < 1 && $this->here != '/users/login'){
$this->Auth->redirect($this->here); // store chosen URL
$this->redirect('/users/login');
}
if($this->Session->read('logperm') == 3)
$this->Auth->allow('*');
elseif[...]
}
This is a long shot, but 'log' is not a valid log type so you could try again with something like 'notice'.
The only other thing I can think of is that the log file directory is not writeable by PHP. You could check that also.
Thanks #François, that pointed me into the right direction.
It was necessary to set
Configure::write('log', true);
to ensure that message and error logging works even if debug=0 (added this in bootstrap).
By the way the 1.3 cookbook exlicitely states that logging is enabled by default even if debug=0. That might be a glitch in the documentation.
Related
I built a Web App using PHP and Laravel. I've tested the app relentlessly for a long time now and everything works great on my local computer. In my .env file, AppDebug is set to true and in the documentation, it says to make sure on a LIVE hosting/production environment that it should be set to false. After setting it to false, the problem is now, my client is going through the app himself to test it out and when he creates a Game, which is just a simple Form with a few input fields and clicks the Submit button, he gets a 500 Server error. The weird thing is that the game is still being inserted into the database, even though he receives this error. If I put the AppDebug back to true, there is no 500 error message anymore and everything works as it should, but I cannot leave it set to true. And a 500 server error is not giving me enough of a description in order for me to debug this. So how can I debug this. Do errors in Laravel get logged somewhere that would be more descriptive in the error?
What I generally use is Telescope: https://laravel.com/docs/6.x/telescope
You have to change some things to get the errors in production:
In telescopeServiceProvider change this:
Telescope::filter(function (IncomingEntry $entry) {
if ( $this->app->isLocal()) {
return true;
}
...
}
To this:
Telescope::filter(function (IncomingEntry $entry) {
return true; //this will prevent the condition of checking if is in local
if ( $this->app->isLocal()) {
return true;
}
...
}
But, you can see all the errors in /storage/logs as the others stated
Cheers!
I'm quite new to cakephp and trying to debug a code from someone else.
The problem is I get a never ending request, despite the fact that both view and crontroller seem to run properly. I even tryed to add an exit; in both of them or even introduce a syntax error in the controller, the request never ends and the browser keeps trying to load the page endlessly.
Here is the code of the controller :
public function categories()
{
file_put_contents("/tmp/logfile.log",time()." categories bla\n", FILE_APPEND);
$catData = $this->SpecificKeywordCategorie->find('all');
$modelnameLessValues = array();
foreach($catData as $singleCat)
{
$modelnameLessValues[] = $singleCat['SpecificKeywordCategorie'];
}
$this->set('categories',$modelnameLessValues);
file_put_contents("/tmp/logfile.log",time()." categories end blu\n", FILE_APPEND);
}
and the view code "categories.ctp :
<?php
file_put_contents("/tmp/logfile.log","view json ".json_encode($categories),FILE_APPEND);
print(json_encode($categories));
file_put_contents("/tmp/logfile.log","view json before exit",FILE_APPEND);
exit;
?>
all the file_put_contents entries are written in the logfile. but the exit seems to be ignored and if I do a request in a browser it never ends...
Same thing happens if I add a syntax error on controller or view. (of course, in this case, log entries are not written)
I know nothing about cakephp internals, but php scripts running outside it are running well on same apache instance.
Any idea where to look to find where this infinite request comes from ?
We are running cakephp 2.2.3
I have noticed a few websites such as hypem.com show a "You didnt get served" error message when the site is busy rather than just letting people wait, time out or refresh; aggravating what is probably a server load issue.
We are too loaded to process your request. Please click "back" in your
browser and try what you were doing again.
How is this achieved before the server becomes overloaded? It sounds like a really neat way to manage user expectation if a site happens to get overloaded whilst also giving the site time to recover.
Another options is this:
$load = sys_getloadavg();
if ($load[0] > 80) {
header('HTTP/1.1 503 Too busy, try again later');
die('Server too busy. Please try again later.');
}
I got it from php's site http://php.net/sys_getloadavg, altough I'm not sure what the values represent that the sys_getloadavg returns
You could simply create a 500.html file and have your webserver use that whenever a 50x error is thrown.
I.e. in your apache config:
ErrorDocument 500 /errors/500.html
Or use a php shutdown function to check if the request timeout (which defaults to 30s) has been reached and if so - redirect/render something static (so that rendering the error itself cannot cause problems).
Note that most sites where you'll see a "This site is taking too long to respond" message are effectively generating that message with javascript.
This may be to do with the database connection timing out, but that assumes that your server has a bigger DB load than CPU load when times get tough. If this is the case, you can make your DB connector show the message if no connection happens for 1 second.
You could also use a quick query to the logs table to find out how many hits/second there are and automatically not respond to any more after a certain point in order to preserve QOS for the others. In this case, you would have to set that level manually, based on server logs. An alternative method can be seen here in the Drupal throttle module.
Another alternative would be to use the Apache status page to get information on how many child processes are free and to throttle id there are none left as per #giltotherescue's answer to this question.
You can restrict the maximum connection in apache configuration too...
Refer
http://httpd.apache.org/docs/2.2/mod/mpm_common.html#maxclients
http://www.howtoforge.com/configuring_apache_for_maximum_performance
This is not a strictly PHP solution, but you could do like Twitter, i.e.:
serve a mostly static HTML and Javascript app from a CDN or another server of yours
the calls to the actual heavy work server-side (PHP in your case) functions/APIs are actually done in AJAX from one of your static JS files
so you can set a timeout on your AJAX calls and return a "Seems like loading tweets may take longer than expected"-like notice.
You can use the php tick function to detect when a server isn't loading for a specified amount of time, then display an error messages. Basic usage:
<?php
$connection = false;
function checkConnection( $connectionWaitingTime = 3 )
{
// check connection & time
global $time,$connection;
if( ($t = (time() - $time)) >= $connectionWaitingTime && !$connection){
echo ("<p> Server not responding for <strong>$t</strong> seconds !! </p>");
die("Connection aborted");
}
}
register_tick_function("checkConnection");
$time = time();
declare (ticks=1)
{
require 'yourapp.php' // load your main app logic
$connection = true ;
}
The while(true) is just to simulate a loaded server.
To implement the script in your site, you need to remove the while statement and add your page logic E.G dispatch event or front controller action etc.
And the $connectionWaitingTime in the checkCOnnection function is set to timeout after 3 seconds, but you can change that to whatever you want
I want to be able to validate a form to check if a website/webpage exists. If it returns a 404 error then that definitely shouldn't validate. If there is a redirect...I'm open to suggestions, sometimes redirects go to an error page or homepage, sometimes they go to the page you were looking for, so I don't know. Perhaps for a redirect there could be a special notice that suggests the destination address to the user.
The best thing I found so far was like this:
$.ajax({url: webpage ,type:'HEAD',error:function(){
alert('No go.');
}});
That has no problem with 404's and 200's but if you do something like 'http://xyz' for the url it just hangs. Also 302 and the like trigger the error handler too.
This is a generic enough question I would like a complete working code example if somebody can make one. This could be handy for lots of people to use.
It sounds like you don't care about the web page's contents, you just want to see if it exists. Here's how I'd do it in PHP - I can stop PHP from taking up memory with the page's contents.
/*
* Returns false if the page could not be retrieved (ie., no 2xx or 3xx HTTP
* status code). On success, if $includeContents = false (default), then we
* return true - if it's true, then we return file_get_contents()'s result (a
* string of page content).
*/
function getURL($url, $includeContents = false)
{
if($includeContents)
return #file_get_contents($url);
return (#file_get_contents($url, null, null, 0, 0) !== false);
}
For less verbosity, replace the above function's contents with this.
return ($includeContents) ?
#file_get_contents($url) :
(#file_get_contents($url, null, null, 0, 0) !== false)
;
See http://www.php.net/file_get_contents for details on how to specify HTTP headers using a stream context.
Cheers.
First you need to check that the page exists via DNS. That's why you say it "just hangs" - it's waiting for the DNS query to time out. It's not actually hung.
After checking DNS, check that you can connect to the server. This is another long timeout if you're not careful.
Finally, perform the HTTP HEAD and check the status code. There are many, many, many special cases you have to consider here: what does a "temporary internal server error" mean for the page existing? What about "permanently moved"? Look into HTTP status codes.
I've just written a simpler version using PHP:
function url_check($url) {
$x = #fopen($url,"r");
if ($x) {
$reply = 1;
fclose($x);
} else {
$reply = 0;
}
return $reply;
}
Obviously $url is the test URL, returns true (1) or false (0) depending on URL existence.
Maybe you could combine domain checker, and jQuery, domain checker (PHP) can respond 1 or 0 for non-existent domains.
eg. http://webarto.com/snajper.php?domena=stackoverflow.com , will return 1, you can use input blur function to check for it instantly.
I'm looking for a way to prevent unauthorised users from viewing pages without, lets say, wrapping everything in an if authed { show page } else { show error}
My website is currently setup like:
index.php
require_once __WEBROOT__ . '/templates/default/header.tmpl';
require_once content('p');
require_once __WEBROOT__ . '/templates/default/footer.tmpl';
content()
function content($GETvar)
{
$content = '';
$root = __WEBROOT__;
$location = 'content';
$files = scanDirRecursive($root . '/content/');
if (isset ($_GET[$GETvar]))
{
$path = str_replace('\\', '/', $_GET[$GETvar]->toHTML());
if (in_array("$root/$location/$path", $files))
{
$content = "$root/$location/$path";
}
else
{
$content = $root . '/templates/default/errors/404.php';
}
}
else
{
$content = __WEBROOT__ . '/content/home.php';
}
return $content;
}
This works nicely. When I was playing around with auth options, I chucked in a 'return' at the top of 'content' page. Which ended up preventing the content page from loading but keeping the template in tact (unlike a die()).
So I was wondering, is this safe? Or is there an error occurring that I'm not seeing...
Use the front controller pattern. Instead of having all your pages as individual PHP files, have a single "point of entry".
Basically, have your index.php file work like index.php?p=foo where foo defines what page to show. This way, all your requests will go through index.php, and you can include all your access checking in a single place. Remember to be careful to not allow including arbitrary files though - a common beginner mistake with this approach.
However, as pointed out, you may wish to research how frameworks like Cake or Zend perform this job.
Require a login page which sets a session variable with, say, the userid. Then on every page, call a function to check for authorization. It could probably be put in the header if it considers both the page and the user.
If no user is logged in, or they aren't allowed for the page, redirect to the login page—it would be nice to add a message saying they can't use the page they requested without logging in.
Logging out should clear the session variables. Also, if there is to be a session timeout, record the timestamp in a session variable at times which reset the timeout.
Why to reinvent the wheel? Every php framework have it's acl module, where you can set security policy with minimal amount of coding. Take a look at cakephp or in google acl framework...
don't do a if logged in do this {} else {complain,} just redirect them to the login page if they aren't identified then die();
I've found it convenient to simply throw an Exception for such things. There are several strategies, but one might involve a scenario like:
function show_content()
{
if( ! $user_is_allowed_to_see_this_content ) {
throw new Exception('This user may not see this content', 403);
}
// Continue on with the content code
}
By default, this will simply error out, but you can use the set_exception_handler() function to define what specifically happens when the exception is thrown. This lets you define the "what to do when stuff goes wrong" logic in a separate place from your content-handling code, which I find makes things tidier.
For example:
function custom_exception_handler( Exception $exception )
{
// Log the Exception
error_log( $exception->getMessage(), 0 );
// Return the generic "we screwed up" http status code
header( "HTTP/1.0 500 Internal Server Error" );
// return some error content
die("We're sorry. Something broke. Please try again.");
}
// Now tell php to use this function to handle un-caught exceptions
set_exception_handler('custom_exception_handler');
It's worth noting that this is a good general-purpose way to handle all logical failure events, and not just authentication failures. File-not-found exceptions, validation exceptions, database query exceptions, demand-throttling exceptions; these can all be handled in the same way and in the same place.