Zend_Controller_Request::setRedirect() does not seem to work? - zend-framework

i am not sure if calling setRedirect from the resource object is the best way. but i wonder why this does not seem to do anything. i have this in a predispatch controller plugin
function preDispatch(Zend_Controller_Request_Abstract $req) {
...
if (!$acl->isAllowed($role, $resource, $privilege)) {
...
$res = $this->_response;
$res->setRedirect('/error/?error-handler=unauthorized', 403);
}
}
if u prefer the whole code, get it #pastebin

setRedirect() does not stop the dispatchloop from executing. To do the redirect you have to send the headers and exit the process.
$res->setRedirect('/error/?error-handler=unauthorized', 403);
$res->sendHeaders();
exit();
A better way would be to use the Redirector Zend_Controller_Action_HelperBroker::getStaticHelper('Redirector')->gotoUrl()

Related

Perl catalyst controller redirect not working

I have looked over this code and I can not understand the weirdness it exhibits. For a lack of understanding all I know
$c->res->redirect('qbo/home');
is being ignored, in favor of the redirect in the following if else condition. In other words, I always end up at the OAuthentication website.
If I block comment out the else condition I end up where I want to go qbo/home
sub index :Path :Args(0) {
my ($self, $c) = #_;
# Check to see if we have QBO::OAuth object in our user's session
# Create new object in session if we don't already have one
if(!($c->session->{qbo})) {
$c->log->info('Creating QBO::OAuth, save in user session');
$c->session->{qbo} = QBO::OAuth->new(
consumer_key => 'qyprddKpLkOclitN3cJCJno1fV5NzcT',
consumer_secret => 'ahwpSghVOzA142qOepNHoujyuHQFDbEzeGbZjEs3sPIc',
);
}
# Now we set our object variable to the session old or new
my $qbo = $c->session->{qbo};
######### GOTO 'qbo/home' ##########
$c->res->redirect('qbo/home');
####################################
if($c->req->params->{oauth_token}) {
$c->log->info('Now Redirect to access_endpoint');
# Get realmId and save it to our QBO::OAuth object in user session
$qbo->realmId($c->req->params->{realmId});
# Call QBO::OAuth->request_access_token
my $r = $qbo->request_access_token($c->req->params->{oauth_verifier});
$c->res->redirect('qbo/home');
} else {
my $callback = 'http://www.example.com/qbo';
# Request a token
my $r = $qbo->request_token($callback);
if($qbo->has_token) {
#Continue on down, Redirect to auth_user_endpoint
$c->res->redirect($qbo->auth_user_endpoint . '?oauth_token=' . $qbo->token);
}
}
}
Seems I am missing some basic fundamental about how this works. Any clues appreciated
From the fine manual...
This is a convenience method that sets the Location header to the redirect destination, and then sets the response status. You will want to return or $c->detach() to interrupt the normal processing flow if you want the redirect to occur straight away.
Note also the warning on that manual page about redirecting to a relative URL - you shouldn't do it. For your use-case, I'd recommend getting into the habit of using:
return $c->res->redirect($c->uri_for('qbo/home'));
or
$c->res->redirect($c->uri_for('qbo/home')) && $c->detach();
depending on your preference.

Slim Framework - Using a GET route

I'm absolutely new to Slim Framework. I'm working on an Webservice that should provide an interface between an Android App and a Web-Application. I used the Slim Documentation to make my first steps and now I want to create a simple GET route, to receive information from the App. Here is what I have so far:
require 'Slim/Slim.php';
\Slim\Slim::registerAutoloader();
$name_outside = '';
$app = new \Slim\Slim();
$app->get('/session/program_name/:name', function ($name) use($app) {
$name_outside = $name;
echo $name;
});
$app->run();
echo $name_outside;
I need to access the variable :name outside the function, but what I get is nothing. What I am doing wrong here?
Btw: I know that GET-routes usually are used to list existing resources, but for my simple case, I decided to use it that way.
Fix your code to hold name as args parameters ,then you can get in in Your function
require 'Slim/Slim.php';
\Slim\Slim::registerAutoloader();
$name_outside = '';
$app = new \Slim\Slim();
$app->get('/session/program_name/{name}', function ($args) use($app) {
$name_outside = $args['name'];
echo $args['name'];
});
$app->run();
To acess the $name_outside inside the function context you pass it.
$app->get('/session/program_name/:name', function ($name) use($app, &$name_outside) {
$name_outside = $name;
echo $name;
});
But perhaps you're using Slim in a wrong way. Why you have to access the variable outside of your route?
No code is execyted after the run() call. That's the way slim works, try to put a die where you're echo the variable, it isn't reachable.
You shouldn't have the need to access the context of the route outside of it this way. To transform a request or a response you use middlewares with the hooks.

Joomla setRedirect doesn't work

I have a simple Joomla controller, but I can't redirect anything.
According to the documentation:
class MyController extends MyBaseController {
function import() {
$link = JRoute::_('index.php?option=com_foo&ctrl=bar');
$this->setRedirect($link);
}
}
//The url contains & html escaped character instead of "&"
This should work, but I get a malformed URL. Is there something I'm missing here? Why is Joomla converting all the "&" characters into &'s? How am I suppose to use setRedirect?
Thank you
Alright, I fixed it. So if anyone needs it:
instead of
$link = JRoute::_('index.php?option=com_foo&ctrl=bar');
$this->setRedirect($link);
use
$link = JRoute::_('index.php?option=com_foo&ctrl=bar',false);
$this->setRedirect($link);
to make it work.
Glad you found your answer, and by the way, the boolean parameter in JRoute::_() is by default true, and useful for xml compliance. What it does is that inside the static method, it uses the htmlspecialchars php function like this: $url = htmlspecialchars($url) to replace the & for xml.
Try this.
$mainframe = &JFactory::getApplication();
$mainframe->redirect(JURI::root()."index.php?option=com_foo&ctrl=bar","your custom message[optional]","message type[optional- warning,error,information etc]");
After inspecting the Joomla source you can quickly see why this is happening:
if (headers_sent())
{
echo "<script>document.location.href='" . htmlspecialchars($url) . "';</script>\n";
}
else
{
... ... ...
The problem is that your page has probably already output some data (via echo or some other means).
In this situation, Joomla is programmed to use a simple javascript redirect. However, in this javascript redirect it has htmlspecialchars() applied to the URL.
A simple solution is to just not use Joomlas function and directly write the javascript in a way that makes more sense:
echo "<script>document.location.href='" . $url . "';</script>\n";
This works for me :)
/libraries/joomla/application/application.php
Find line 400
// If the headers have been sent, then we cannot send an additional location header
// so we will output a javascript redirect statement.
if (headers_sent())
{
echo "<script>document.location.href='" . htmlspecialchars($url) . "';</script>\n";
}
replace to
// If the headers have been sent, then we cannot send an additional location header
// so we will output a javascript redirect statement.
if (headers_sent())
{
echo "<script>document.location.href='" . $url . "';</script>\n";
}
This works!

Is it possible to read headers using Perl HTTP::Async module?

To optimize my Perl application I need to work with async HTTP requests, so I can handle other operations once the HTTP response is finish. So I believe my only option is to work with HTTP::Async module. This works fine for simple requests, but I need to catch cookie header from one response and send it with next one, so I need to read headers. My code is:
...
$async->add($request);
while ($response = $async->wait_for_next_response)
{
threads->yield(); yield();
}
$cookie = $response->header('Set-Cookie');
$cookie =~ s/;.*$//;
$request->header('Cookie' => $cookie);
...
but it's not working, as it ends with an error Can't call method "header" on an undefined value. Obviously $response is undef. How can I catch headers before $response gets undef?
while ($response = $async->wait_for_next_response)
{
threads->yield(); yield();
}
Is guaranteed not to finish until $response is false. The only false value wait_for_next_response will return is undef. You need to either extract the cookie inside the loop, or cache the last good response inside the loop.
Something like
my $last_response;
while ($response = $async->wait_for_next_response)
{
$last_response = $response;
threads->yield(); yield();
}
should work, although I'm not sure you need the loop at all. It's hard to tell without a complete program.

Zend Framework Module Based Error Handling

Zend_Controller_Plugin_ErrorHandler always forwards to ErrorController::errorAction() in the default module but i want it be module aware. For example when a exception throws it must be call the module's ErrorController like Admin_ErrorController:errorAction.
How can i do this?
Thanks.
You can create plugin that will examine your request and based on current module sets ErrorController...
<?php
class My_Controller_Plugin_ErrorControllerSwitcher extends Zend_Controller_Plugin_Abstract
{
public function routeShutdown (Zend_Controller_Request_Abstract $request)
{
$front = Zend_Controller_Front::getInstance();
if (!($front->getPlugin('Zend_Controller_Plugin_ErrorHandler') instanceof Zend_Controller_Plugin_ErrorHandler)) {
return;
}
$error = $front->getPlugin('Zend_Controller_Plugin_ErrorHandler');
$testRequest = new Zend_Controller_Request_Http();
$testRequest->setModuleName($request->getModuleName())
->setControllerName($error->getErrorHandlerController())
->setActionName($error->getErrorHandlerAction());
if ($front->getDispatcher()->isDispatchable($testRequest)) {
$error->setErrorHandlerModule($request->getModuleName());
}
}
}
Then use
$front = Zend_Controller_Front::getInstance();
$front -> registerPlugin(new My_Controller_Plugin_ErrorControllerSwitcher())
to register the plugin with the FrontController. Thanks JohnP for pointing that out.
Alternate approach may be to throw specific exceptions for each module (or functionality you need, e.g. Mymodule_MyException) and then handle them in the Default_ErrorController.