You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Eric SCHAEFFER <es...@posterconseil.com> on 2000/01/18 17:51:04 UTC

Proposal - HTTP headers processor

Hi,

After a short discussion with Stefano, I send to you a proposal  for sending
HTTP headers dynamically :

I write a small processor (based on the code of the DCPProcessor class) that
looks for a pi (mime is <?http-redirect href="..."?>) and if it finds it,
sends an HTTP redirect header to the client and stops the Cocoon processing
process.
To stop Cocoon, my processor just returns 'null' (and I modified the Engine
class to stop if null was returned).

What do you think about such a processor ? It can be a good feature to add
to Cocoon (I needed http redirect). I think that this processor could also
send other HTTP headers (as expiration times by example).

The only problem raised by this processor is the way to stop Cocoon. Stefano
suggested me to use a 'StopProcessingSignal'. It's surelly better than
returning 'null'...

Eric.

PS : my 'redirect' processor


package org.apache.cocoon.processor.redirect;

import java.io.*;
import java.util.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.w3c.dom.*;
import org.apache.cocoon.framework.*;
import org.apache.cocoon.processor.*;

/**
 * A processor that performs HTTP redirects.
 *
 * @author <a href="mailto:eschaeffer@posterconseil.com">Eric SCHAEFFER</a>
 * @version $Revision: 0.1 $ $Date: 2000/01/14 12:00:00 $
 */

public class RedirectProcessor extends AbstractActor implements Processor,
Status {

    private static final String REDIRECT_PI = "http-redirect";
    private static final String HREF_ATTRIBUTE = "href";

    private Document m_document;

    /**
     * Process the DOM tree.
     */
    public Document process(Document document, Dictionary parameters) throws
Exception {
        this.m_document = document;

        HttpServletRequest request =
(HttpServletRequest)parameters.get("request");
        HttpServletResponse response =
(HttpServletResponse)parameters.get("response");

        /*
        * Process the document
        */
        String redirectURL = doProcess(document);

        /*
        * if find <?http-redirect?> tag,
        * send HTTP redirect and return null document to stop processing
        */
        if (redirectURL != null) {
            response.sendRedirect(redirectURL);
            return null;
        }

        /*
        * else, return the document
        */
        return document;
    }

    public boolean hasChanged(Object context) {
        return true;
    }

    public String getStatus() {
        return "Redirect Processor";
    }

    private String doProcess(Node node) {
        short nodeType = node.getNodeType();

        switch (nodeType) {

            case Node.ELEMENT_NODE:

            case Node.DOCUMENT_NODE:
                Node[] children = getChildren(node);

                String redirectURL;
                for (int i = 0; i < children.length; i++) {
                    redirectURL = doProcess(children[i]);
                    if (redirectURL != null) {
                        return redirectURL;
                    }
                }

                break;

            case Node.PROCESSING_INSTRUCTION_NODE:
                Node parent = node.getParentNode();
                ProcessingInstruction pi = (ProcessingInstruction) node;

                try {
                    String target = pi.getTarget();

                    if (target.equals(REDIRECT_PI)) {
                        return processObject(pi);
                    }
                } catch (Exception e) {
                    String message = e.getMessage();
                    String className = e.getClass().getName();

                    StringWriter sw = new StringWriter();
                    PrintWriter pw = new PrintWriter(sw, true);
                    e.printStackTrace(pw);
                    Text errorText = this.m_document.createTextNode(
                        "{Redirect Error: " +
                        className + ": " +
                        message + "}\n" +
                        sw.toString()
                    );

                    parent.replaceChild(errorText, pi);
                }

                break;
        }

        return null;
    }

    private String processObject(ProcessingInstruction pi) throws Exception
{

        Hashtable attributes = new Hashtable();
        parseAttributes(pi.getData(), attributes);

        String redirectURL = (String) attributes.get(HREF_ATTRIBUTE);
        if (redirectURL == null) {
            // URL missing
            throw new Exception("Missing HREF in redirect definition");
        }

        return redirectURL;
    }

    private void parseAttributes(String data, Hashtable attributes) {
        int length = data.length();
        char[] chars = data.toCharArray();

        try {
            for (int index = 0; index < length; index++) {

                /* Skip leading blanks */
                while (index < length && chars[index] <= ' ') {
                    index++;
                }

                /* Get variable name */
                StringBuffer nameBuffer = new StringBuffer();

                while (index < length
                       &&!(chars[index] == '=' || chars[index] <= ' ')) {
                    nameBuffer.append(chars[index++]);
                }

                String name = nameBuffer.toString();

                // Skip blanks
                while (index < length && chars[index] <= ' ') {
                    index++;
                }

                /* Get variable value */
                if (chars[index++] != '=') {
                    throw new Exception("Invalid attribute name: '" + name
                                        + "'");
                }

                // Skip blanks
                while (index < length && chars[index] <= ' ') {
                    index++;
                }

                if (chars[index++] != '"') {
                    throw new Exception("Invalid attribute value for '"
                                        + name + "'");
                }

                StringBuffer valueBuffer = new StringBuffer();

                while (index < length && chars[index] != '"') {
                    valueBuffer.append(chars[index++]);
                }

                String value = valueBuffer.toString();

                if (index == length || chars[index] != '"') {
                    throw new Exception("Unterminated string '" + value
                                        + "' in attribute '" + name + "'");
                }

                // Store name/value pair
                attributes.put(name, value);
            }
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }

    private Node[] getChildren(Node node) {
        NodeList nodeList = node.getChildNodes();
        int childCount = nodeList.getLength();
        Node[] children = new Node[childCount];

        for (int i = 0; i < childCount; i++) {
            children[i] = nodeList.item(i);
        }

        return children;
    }

}


_______________________________________

Eric SCHAEFFER
eschaeffer@posterconseil.com

POSTER CONSEIL
118 rue de Tocqueville
75017 PARIS
FRANCE
Tel. : 33-140541058
Fax : 33-140541059
_______________________________________



Re: Proposal - HTTP headers processor

Posted by "Marcelo F. Ochoa" <mo...@exa.unicen.edu.ar>.
Eric SCHAEFFER wrote:

> Hi,
>
> After a short discussion with Stefano, I send to you a proposal  for sending
> HTTP headers dynamically :
>
> I write a small processor (based on the code of the DCPProcessor class) that
> looks for a pi (mime is <?http-redirect href="..."?>) and if it finds it,
> sends an HTTP redirect header to the client and stops the Cocoon processing
> process.
> To stop Cocoon, my processor just returns 'null' (and I modified the Engine
> class to stop if null was returned).

>
>
> What do you think about such a processor ? It can be a good feature to add
> to Cocoon (I needed http redirect). I think that this processor could also
> send other HTTP headers (as expiration times by example).

   In my experience of OraclePLSQL Producer, I need this header:
WWW-authenticate: basic realm="String Realms"   (ask to user DB
username/password)
    Set-Cookie: "cookie spec"  (Definition of client side cookies)
    Status: "Status info"  (Definition of status line of browser)
   All header needs extra information like HTML page (probable a XML page
transformed to HTML page with XSL procesor).

>
>
> The only problem raised by this processor is the way to stop Cocoon. Stefano
> suggested me to use a 'StopProcessingSignal'. It's surelly better than
> returning 'null'...

>
>
> Eric.
>

   Marcelo.