Zend Framework

_redirect() needs to use absolute URIs?

Details

  • Type: Bug Bug
  • Status: Resolved Resolved
  • Priority: Trivial Trivial
  • Resolution: Fixed
  • Affects Version/s: 0.7.0
  • Fix Version/s: 1.0.0
  • Component/s: Zend_Controller
  • Labels:
    None

Description

According to section 14.30 in RFC 2616 when specifying the "Location" response header it should contain an absolute URI. When _redirect() in Zend_Controller_Action prepends the base URI to the redirect URI it only adds the absolute path, not the schema/hostname/etc.

Activity

Hide
Bill Karwin added a comment -

Assign to Matthew.

Show
Bill Karwin added a comment - Assign to Matthew.
Hide
Matthew Weier O'Phinney added a comment -

While I appreciate the 'why' behind this request, I'm wondering about the necessity. Server's send back a Host header as part of the response, which is why most clients can redirect using relative URLs. Additionally, I'm not entirely certain that we can rely on $_SERVER['HTTP_HOST']/$_SERVER['SERVER_NAME'] and $_SERVER['HTTPS'] to assemble the FQDN – these may be tampered with, or left unpopulated by a given SAPI implementation.

If you can provide details on instances when a relative URL redirect does not work, I'll definitely reconsider.

Show
Matthew Weier O'Phinney added a comment - While I appreciate the 'why' behind this request, I'm wondering about the necessity. Server's send back a Host header as part of the response, which is why most clients can redirect using relative URLs. Additionally, I'm not entirely certain that we can rely on $_SERVER['HTTP_HOST']/$_SERVER['SERVER_NAME'] and $_SERVER['HTTPS'] to assemble the FQDN – these may be tampered with, or left unpopulated by a given SAPI implementation. If you can provide details on instances when a relative URL redirect does not work, I'll definitely reconsider.
Hide
Alex Adriaanse added a comment -

I don't remember any practical problems caused by this, so if you decide not to worry about this then that's fine with me. I am just reporting this from a correctness standpoint. If I do come across actual problems I will post more information here.

Show
Alex Adriaanse added a comment - I don't remember any practical problems caused by this, so if you decide not to worry about this then that's fine with me. I am just reporting this from a correctness standpoint. If I do come across actual problems I will post more information here.
Hide
Matthew Weier O'Phinney added a comment -

Great. I'm going to resolve the issue as 'not an issue', but I won't close it yet. I had some discussion with a few of my colleagues, and there are some definite issues with implementing this cleanly cross-platform, so unless we see a clear use case, we'd rather not delve into those issues quite yet.

Thanks for the report!

Show
Matthew Weier O'Phinney added a comment - Great. I'm going to resolve the issue as 'not an issue', but I won't close it yet. I had some discussion with a few of my colleagues, and there are some definite issues with implementing this cleanly cross-platform, so unless we see a clear use case, we'd rather not delve into those issues quite yet. Thanks for the report!
Hide
Marek Augustyn added a comment -

I have problems using _redirect() on server provided by home.pl (hosting company in Poland). They use their custom http server and emulate mod_rewrite for it. Things works perfectly until I use mod_rewrite to redirect all requests to bootstrap file, and then try to redirect to different path using _redirect() - default behavior with ZendFramework.
When server receives relative redirect request from php, it resolves its target (being still the same bootstrap index.php file because of rewriting) and send internally request to this file again without changing the path in the uri - the server doesn't send header "Location" to the browser.
The unwanted result of this action is unchanged path in URI, ie. when I redirect from /test/of/redirect/ to /test using header "Location: /test/", after redirection the script still gets the old path "/test/of/redirect/".
When I use redirection using absolute URI, redirection works right.

To make things work i did a dirty hack in metod _redirect() of Zend_Controller_Action (0.9.1):

// If relative URL, decide if we should prepend base URL
        if ($prependBase && !preg_match('|^[a-z]+://|', $url)) {
            $request = $this->getRequest();
            if ($request instanceof Zend_Controller_Request_Http) {
                $base = $request->getBaseUrl();
                if (('/' != substr($base, -1)) && ('/' != substr($url, 0, 1))) {
                    $url = $base . '/' . $url;
                } else {
                    $url = $base . $url;
                }
                # THE HACK:
                $url = 'http://'.$this->getRequest()->getServer('HTTP_HOST').$url;
            }
        }

I asked my hosting company about that and I received an answer:

Please consider that server behaviour is correct, that is, location is passed in the right way.
If you want to change location (URI), please use absolute redirections (301, 302)

Considering RFC 2616 mentioned above, they are perfectly right.

Is there a better way than the dirty hack to make absolute redirections using _redirect()?

Will this issue be considered in future versions od ZendFramework?

Show
Marek Augustyn added a comment - I have problems using _redirect() on server provided by home.pl (hosting company in Poland). They use their custom http server and emulate mod_rewrite for it. Things works perfectly until I use mod_rewrite to redirect all requests to bootstrap file, and then try to redirect to different path using _redirect() - default behavior with ZendFramework. When server receives relative redirect request from php, it resolves its target (being still the same bootstrap index.php file because of rewriting) and send internally request to this file again without changing the path in the uri - the server doesn't send header "Location" to the browser. The unwanted result of this action is unchanged path in URI, ie. when I redirect from /test/of/redirect/ to /test using header "Location: /test/", after redirection the script still gets the old path "/test/of/redirect/". When I use redirection using absolute URI, redirection works right. To make things work i did a dirty hack in metod _redirect() of Zend_Controller_Action (0.9.1):
// If relative URL, decide if we should prepend base URL
        if ($prependBase && !preg_match('|^[a-z]+://|', $url)) {
            $request = $this->getRequest();
            if ($request instanceof Zend_Controller_Request_Http) {
                $base = $request->getBaseUrl();
                if (('/' != substr($base, -1)) && ('/' != substr($url, 0, 1))) {
                    $url = $base . '/' . $url;
                } else {
                    $url = $base . $url;
                }
                # THE HACK:
                $url = 'http://'.$this->getRequest()->getServer('HTTP_HOST').$url;
            }
        }
I asked my hosting company about that and I received an answer:
Please consider that server behaviour is correct, that is, location is passed in the right way. If you want to change location (URI), please use absolute redirections (301, 302)
Considering RFC 2616 mentioned above, they are perfectly right. Is there a better way than the dirty hack to make absolute redirections using _redirect()? Will this issue be considered in future versions od ZendFramework?
Hide
Bart Blaszczyk added a comment -

This issue hasn't been resolved yet... It makes the Redirector helper useless without some hacks for servers with such redirection implementation as in home.pl. Why don't you modify the Redirector so that it always uses absolute redirects finding the protocol and server name dynamically and prepending them to the destination URL?

Show
Bart Blaszczyk added a comment - This issue hasn't been resolved yet... It makes the Redirector helper useless without some hacks for servers with such redirection implementation as in home.pl. Why don't you modify the Redirector so that it always uses absolute redirects finding the protocol and server name dynamically and prepending them to the destination URL?
Hide
Matthew Weier O'Phinney added a comment -

Re-opening per user requests

Show
Matthew Weier O'Phinney added a comment - Re-opening per user requests
Hide
Matthew Weier O'Phinney added a comment -

I've added an option to the Redirector, _useAbsoluteUri, that will attempt to create an absolute URI from the URI path created via the various redirect methods in the Redirector. Turn it on with:

$this->_helper->redirector->setUseAbsoluteUri(true);

It uses $_SERVER['HTTP_HOST'], $_SERVER['SERVER_PORT'], and $_SERVER['HTTPS'] to create the absolute URI.

I'm not turning it on by default as HTTP_HOST is not always set, and could cause odd behaviour for some installations.

Please test, and let me know if it resolves the issue.

Show
Matthew Weier O'Phinney added a comment - I've added an option to the Redirector, _useAbsoluteUri, that will attempt to create an absolute URI from the URI path created via the various redirect methods in the Redirector. Turn it on with:
$this->_helper->redirector->setUseAbsoluteUri(true);
It uses $_SERVER['HTTP_HOST'], $_SERVER['SERVER_PORT'], and $_SERVER['HTTPS'] to create the absolute URI. I'm not turning it on by default as HTTP_HOST is not always set, and could cause odd behaviour for some installations. Please test, and let me know if it resolves the issue.
Hide
Matthew Weier O'Phinney added a comment -

No feedback from users; marking as fixed.

Show
Matthew Weier O'Phinney added a comment - No feedback from users; marking as fixed.

People

Vote (0)
Watch (4)

Dates

  • Created:
    Updated:
    Resolved: