How to insert Last-Modified date in response header?

2.8k Views Asked by At

I am trying to add a last-modified date to the html source code of the pages served by our CMS (Jahia) so that it appears as an attribute in the response header.

This is needed for our search engine indexation.

I have tried adding in the head tag the following syntaxes but none allow a modified date to appear in the response headers:

<meta name="dcterms.modified" content="Mon, 09 Apr 2018 11:41:11 GMT">
<meta name="DCTERMS.modified" content="Mon, 09 Apr 2018 11:41:11 GMT">      
<meta http-equiv="last-modified" content="Mon, 09 Apr 2018 11:41:11 GMT">   
<meta http-equiv="Last-Modified" content="Mon, 09 Apr 2018 11:41:11 GMT">   

(these dates are resolved from the fmt:formatDate pattern = "EEE, dd MMM yyyy HH:mm:ss z").

Am I incorrectly assuming that a meta tag added inside the head tag can be added to the header? I read on the W3Schools site that the only attributes for http-equiv are

<meta http-equiv="content-type|default-style|refresh"> 

so that is probably why that syntax doesn't work (although I can find references to it on the web).

Thanks in advance for your help.

2

There are 2 best solutions below

0
On

Following help from the Jahia support team I added a filter class with source code to add the last modified date to the response headers and added the class to the configuration.

  • First you have to add a spring configuration. You can put it in a xml file in \src\main\resources\META-INF\spring

    <bean id="ResponseNewestModifFilter"   class="org.jahia.modules.lastmodif.filters.ResponseNewestModifFilter">
    <property name="priority" value="12" />
    <property name="description" value="Set Last Modif date in response header"/>
    <property name="applyOnModes" value="live,preview" />
    <property name="applyOnConfigurations" value="page" />
    </bean>
    
  • then add the filter class (inherits from AbstractFilter class) that uses the addDateHeader method,

    package org.jahia.modules.lastmodif.filters;
    import javax.jcr.RepositoryException;
    import org.jahia.modules.lastmodif.taglib.NewestLastModifTag;
    import org.jahia.services.render.RenderContext;
    import org.jahia.services.render.Resource;
    import org.jahia.services.render.filter.AbstractFilter;
    import org.jahia.services.render.filter.RenderChain;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class ResponseNewestModifFilter extends AbstractFilter {
    
    private static final Logger logger = LoggerFactory
            .getLogger(ResponseNewestModifFilter.class);
    
    @Override
    public String execute(String previousOut, RenderContext renderContext,
            Resource resource, RenderChain chain) throws Exception {
        try {
            if (renderContext.getResponse().getHeader("Last-Modified") != null) {
                renderContext.getResponse().setDateHeader(
                        "Last-Modified",
                        NewestLastModifTag.getNewestLastModifDateOfPage(
                                resource.getNode()).getTime());
            } else {
                renderContext.getResponse().addDateHeader(
                        "Last-Modified",
                        NewestLastModifTag.getNewestLastModifDateOfPage(
                                resource.getNode()).getTime());
            }
        } catch (RepositoryException ex) {
            logger.error("Error set Last-Modified reponse header", ex);
        }
        return previousOut;
       }
    }
    

This class makes reference to a custom taglib (NewestLastModifTag) which ensures that all subnodes are queried to get the last modified date

package org.jahia.modules.lastmodif.taglib;

import java.util.Calendar;

import javax.jcr.RepositoryException;

import org.jahia.services.content.JCRNodeIteratorWrapper;
import org.jahia.services.content.JCRNodeWrapper;

public class NewestLastModifTag {

    public static java.util.Date getNewestLastModifDateOfPage(org.jahia.services.content.JCRNodeWrapper node) throws RepositoryException {

        if (node.hasNodes()) {
            return getSubnodesWithNewerDate(node, node.getProperty("jcr:lastModified").getDate()).getTime();
        }
        return node.getProperty("jcr:lastModified").getDate().getTime();
    }

    private static Calendar getSubnodesWithNewerDate(JCRNodeWrapper node, Calendar date) throws RepositoryException {

        JCRNodeIteratorWrapper nodes = node.getNodes();
        while (nodes.hasNext()) {
            JCRNodeWrapper snode = (JCRNodeWrapper)nodes.next();
            if (snode.isNodeType("jnt:page")) {
                continue;
            }
            if (snode.hasProperty("jcr:lastModified") && snode.getProperty("jcr:lastModified").getDate().after(date)) {
                date = snode.getProperty("jcr:lastModified").getDate();
            }
            date = getSubnodesWithNewerDate(snode, date);
        }
        return date;
    }

}
1
On

You can include any metadata into the head html produced by Jahia for your pages. Here is an example of an html output from one of our page:

<meta name="dcterms.created" content="Mon May 26 08:06:56 CEST 2018" />
<meta name="dcterms.modified" content="Tue Oct 30 10:40:43 CET 2018" />
<meta name="dcterms.issued " content="Wed Oct 31 09:09:53 CET 2018" />

In order to retrieve them, you need to use the current page node:

<c:set var="pageNode" value="${jcr:getParentOfType(currentNode, 'jnt:page')}"/>
<c:if test="${empty pageNode}">
    <c:choose>
        <c:when test="${jcr:isNodeType(renderContext.mainResource.node, 'jnt:page')}">
            <c:set var="pageNode" value="${renderContext.mainResource.node}"/>
        </c:when>
        <c:otherwise>
            <c:set var="pageNode" value="${jcr:getParentOfType(renderContext.mainResource.node, 'jnt:page')}"/>
        </c:otherwise>
    </c:choose>
</c:if>

According to the Jahia API, you can retrieve the following page properties:

<c:set var="dateOfCreation" value="${pageNode.creationDateAsDate}" />
<c:set var="dateOfLastModification" value="${pageNode.lastModifiedAsDate}" />
<c:set var="dateOfLastPublication" value="${pageNode.lastPublishedAsDate}" />

And then output them into your component view or template:

<c:if test="${!empty dateOfCreation}"><meta name="dcterms.created" content="${fn:escapeXml(dateOfCreation)}" /></c:if>
<c:if test="${!empty dateOfLastModification}"><meta name="dcterms.modified" content="${fn:escapeXml(dateOfLastModification)}" /></c:if>
<c:if test="${!empty dateOfLastPublication}"><meta name="dcterms.issued " content="${fn:escapeXml(dateOfLastPublication)}" /></c:if>