5

I have a contact form, which I'm showing from CMS page. Like described at method: http://inchoo.net/ecommerce/magento/contact-form-in-magento/

CMS page url is: customer-service-contact. I also redefined standard Mage_Contacts module. Now I need when somebody opens:

http://{website}/customer-service-contact/

he should be redirected to:

https://{website}/customer-service-contact/

I know about trick at xml:

<frontend>
    <secure_url>
        <contacts>/contacts/</contacts>
    </secure_url>
</frontend>

But if I change it to url customer-service-contact, it's not working.

How to implements this?

6

The https redirection does not work for cms pages because the Router that matches the cms pages (Mage_Cms_Controller_Router) does not check if some page should be secure.
Here is a little workaround to achieve this. It involves changing the router for the cms pages.
You will have to create a module. Let's call it Easylife_Secure:
For this you will need the following files:
app/etc/modules/Easylife_Secure.xml - the declaration file

<?xml version="1.0"?>
<config>
    <modules>
        <Easylife_Secure>
            <active>true</active>
            <codePool>local</codePool>
            <depends>
                <Mage_Core />
                <Mage_Cms /><!-- should depend on Mage_Cms -->
            </depends>
        </Easylife_Secure>
    </modules>
</config>

app/code/local/Easylife/Secure/Controller/Router.php - your new router

<?php
class Easylife_Secure_Controller_Router extends Mage_Cms_Controller_Router
{
    public function match(Zend_Controller_Request_Http $request)
    {
        if (!Mage::isInstalled()) {
            Mage::app()->getFrontController()->getResponse()
                ->setRedirect(Mage::getUrl('install'))
                ->sendResponse();
            exit;
        }

        $identifier = trim($request->getPathInfo(), '/');

        $condition = new Varien_Object(array(
            'identifier' => $identifier,
            'continue'   => true
        ));
        Mage::dispatchEvent('cms_controller_router_match_before', array(
            'router'    => $this,
            'condition' => $condition
        ));
        $identifier = $condition->getIdentifier();

        if ($condition->getRedirectUrl()) {
            Mage::app()->getFrontController()->getResponse()
                ->setRedirect($condition->getRedirectUrl())
                ->sendResponse();
            $request->setDispatched(true);
            return true;
        }

        if (!$condition->getContinue()) {
            return false;
        }

        $page   = Mage::getModel('cms/page');
        $pageId = $page->checkIdentifier($identifier, Mage::app()->getStore()->getId());
        if (!$pageId) {
            return false;
        }
        //this line checks if the page should be secure
        $this->_checkShouldBeSecure($request, '/'.$identifier);
        $request->setModuleName('cms')
            ->setControllerName('page')
            ->setActionName('view')
            ->setParam('page_id', $pageId);
        $request->setAlias(
            Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS,
            $identifier
        );

        return true;
    }
    protected function _checkShouldBeSecure($request, $path = '')
    {

        if (!Mage::isInstalled() || $request->getPost()) {
            return;
        }

        if ($this->_shouldBeSecure($path) && !$request->isSecure()) {
            $url = $this->_getCurrentSecureUrl($request);
            if ($request->getRouteName() != 'adminhtml' && Mage::app()->getUseSessionInUrl()) {
                $url = Mage::getSingleton('core/url')->getRedirectUrl($url);
            }

            Mage::app()->getFrontController()->getResponse()
                ->setRedirect($url)
                ->sendResponse();
            exit;
        }
    }
    protected function _shouldBeSecure($path)
    {
        return substr(Mage::getStoreConfig('web/unsecure/base_url'), 0, 5) === 'https'
            || Mage::getStoreConfigFlag('web/secure/use_in_frontend')
                && substr(Mage::getStoreConfig('web/secure/base_url'), 0, 5) == 'https'
                && Mage::getConfig()->shouldUrlBeSecure($path);
    }
    protected function _getCurrentSecureUrl($request)
    {
        if ($alias = $request->getAlias(Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS)) {
            return Mage::getBaseUrl('link', true).ltrim($alias, '/');
        }

        return Mage::getBaseUrl('link', true).ltrim($request->getPathInfo(), '/');
    }
}

The method match is the same as the one in the cms router, it just has one line that checks if the path should be secure. The rest of the methods are copied from the standard router. app/code/local/Easylife/Secure/etc/config.xml - the configuration file

<?xml version="1.0"?>
<config>
    <modules>
        <Easylife_Secure>
            <version>0.0.1</version>
        </Easylife_Secure>
    </modules>
    <global>
        <events>
            <controller_front_init_routers>
                <observers>
                    <cms><!-- change the cms router -->
                        <class>Easylife_Secure_Controller_Router</class>
                        <method>initControllerRouters</method>
                    </cms>
                </observers>
            </controller_front_init_routers>
        </events>
    </global>
    <frontend>
        <secure_url><!-- list here your secure pages. one slash (/) and the page identifier -->
            <customer_service_contact>/customer-service-contact</customer_service_contact>
        </secure_url>
    </frontend>
</config>

Clear the cache and you are done.
[EDIT]
This small extension works for the general case, for all cms pages, I added it here for 'posterity', but I agree with Alex on this. For your specific case, you should use the standard contacts page and customize its template or with additional blocks

  • What advantage is there to overriding the entire module? Why not utilize the event 'cms_controller_router_match_before'? The only caveat to this is in EE and to make sure your event fires AFTER enterprise_cms's event that hooks into the same one. – Ian Mar 20 '14 at 16:58
  • @Ian. I did't say that this is the best solution. It is the only one I could think of. Feel free to add an other one. – Marius Mar 21 '14 at 7:20
  • The event was the first place I thought of looking at your code. I was just wondering if there was a specific reason NOT to. Good solution, gave me a great starting place to springboard off of. – Ian Mar 21 '14 at 18:02
  • @marius How you prevent the redirect loop with this solution? I have the problem that when the standard router is called in this line $this->_checkShouldBeSecure($request, '/'.$module.'/'.$controller.'/'.$action); I get a redirect from https to http because $module, $controller and $action is /cms/page/view and this is not set as secure_url in my module therefore is redirected back to http – lloiacono Mar 1 '16 at 15:15
  • @lloiacono. I don't know how you can avoid that. I never encountered it. It worked nicely for me. Maybe something changed in the past 2.5 years since I wrote this. – Marius Mar 1 '16 at 15:17
2

It is not really the URL which is matched against the XML path frontend/secure_url but the module-controller-action path. In your case this would be /cms/page/view. If you insert /cms/page/view all CMS pages would be delivered via HTTPs.

The test is happening in Mage_Core_Model_Config::shouldUrlBeSecure which is called from Mage_Core_Model_Url::getSecure() like this:

$pathSecure = Mage::getConfig()->shouldUrlBeSecure('/' . $this->getActionPath());

Possible solutions:

  • Write a module which modifies this check and adds for example the page ID or something unique

  • Customize the contacts page via other means (you could use the standard /contacts and add variable CMS content via static blocks).

1

I tried Marius solution and I got a redirect loop since my Router is redirecting to HTTPS here:

$this->_checkShouldBeSecure($request, '/'.$identifier);

This fires a new request for https then again my new Router gets called but this time there is no need to redirect since is already in HTTPS so then this code is executed:

$request->setModuleName('cms')
    ->setControllerName('page')
    ->setActionName('view')
    ->setParam('page_id', $pageId);

After this the next router that is called is Standard router but this time since the $request object has a Module a Controller and an Action when this line is executed (app/code/local/Mage/Core/Controller/Varien/Router/Standard.php Line:181):

//checking if this place should be secure
$this->_checkShouldBeSecure($request, '/'.$module.'/'.$controller.'/'.$action);

I get redirected to HTTP because of this (Line 429):

} elseif (!$this->_shouldBeSecure($path) && $request->isSecure()) {
    // Redirect user from HTTPS to HTTP if the site doesn't need to be secure
    $url = $this->_getCurrentUnsecureUrl($request);

    Mage::app()->getFrontController()->getResponse()
        ->setRedirect($url, 301)
        ->sendResponse();
    exit;

And then all starts over, and this is the redirect loop.

What I did to solve this is not nice :( and I hope someone can provide a better solution. I added this method in my new Router:

protected function preventSecureToNonSecureRedirect($cmsPageIdentifier)
{
    if (Mage::getConfig()->shouldUrlBeSecure($cmsPageIdentifier)) {
        Mage::getConfig()->setNode('frontend/secure_url/cms_page', '/cms/page/view', true);
    }
}

And then I'm calling this method in my new Router just before returning true in the match method:

$request->setModuleName('cms')
    ->setControllerName('page')
    ->setActionName('view')
    ->setParam('page_id', $pageId);
$request->setAlias(
    Mage_Core_Model_Url_Rewrite::REWRITE_REQUEST_PATH_ALIAS,
    $identifier
);

$this->preventSecureToNonSecureRedirect('/'.$identifier);
return true;

By the way I'm using magento 1.9.1.0, your comments are appreciated

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.