/*
 *  Copyright 1999-2004 The Apache Software Foundation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.ajp;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.MessageBytes;
import org.apache.tomcat.util.http.BaseRequest;
import org.apache.tomcat.util.http.HttpMessages;
import org.apache.tomcat.util.http.MimeHeaders;


/**
 * Handle messages related with basic request information.
 *
 * This object can handle the following incoming messages:
 * - "FORWARD_REQUEST" input message ( sent when a request is passed from the web server )
 * - "PING REQUEST" input message (sent by the web server to determine if tomcat is not frozen,
 *                                 a PONG REPLY will be sent back)
 * - "RECEIVE_BODY_CHUNK" input ( sent by container to pass more body, in response to GET_BODY_CHUNK )
 *
 * It can handle the following outgoing messages:
 * - SEND_HEADERS. Pass the status code and headers.
 * - SEND_BODY_CHUNK. Send a chunk of body
 * - GET_BODY_CHUNK. Request a chunk of body data
 * - END_RESPONSE. Notify the end of a request processing.
 *
 * @author Henri Gomez [hgomez@apache.org]
 * @author Dan Milstein [danmil@shore.net]
 * @author Keith Wannamaker [Keith@Wannamaker.org]
 * @author Costin Manolache
 */
public class RequestHandler extends AjpHandler
{
    // XXX Will move to a registry system.
    
    // Prefix codes for message types from server to container
	public static final byte JK_AJP13_FORWARD_REQUEST   = 2;
	public static final byte JK_AJP13_SHUTDOWN          = 7;
	public static final byte JK_AJP13_PING_REQUEST      = 8;    
	public static final byte JK_AJP13_CPING_REQUEST     = 10;    

    // Prefix codes for message types from container to server
    public static final byte JK_AJP13_SEND_BODY_CHUNK   = 3;
    public static final byte JK_AJP13_SEND_HEADERS      = 4;
    public static final byte JK_AJP13_END_RESPONSE      = 5;
	public static final byte JK_AJP13_GET_BODY_CHUNK    = 6;
	public static final byte JK_AJP13_CPONG_REPLY       = 9;
	
    // Integer codes for common response header strings
    public static final int SC_RESP_CONTENT_TYPE        = 0xA001;
    public static final int SC_RESP_CONTENT_LANGUAGE    = 0xA002;
    public static final int SC_RESP_CONTENT_LENGTH      = 0xA003;
    public static final int SC_RESP_DATE                = 0xA004;
    public static final int SC_RESP_LAST_MODIFIED       = 0xA005;
    public static final int SC_RESP_LOCATION            = 0xA006;
    public static final int SC_RESP_SET_COOKIE          = 0xA007;
    public static final int SC_RESP_SET_COOKIE2         = 0xA008;
    public static final int SC_RESP_SERVLET_ENGINE      = 0xA009;
    public static final int SC_RESP_STATUS              = 0xA00A;
    public static final int SC_RESP_WWW_AUTHENTICATE    = 0xA00B;
	
    // Integer codes for common (optional) request attribute names
    public static final byte SC_A_CONTEXT       = 1;  // XXX Unused
    public static final byte SC_A_SERVLET_PATH  = 2;  // XXX Unused
    public static final byte SC_A_REMOTE_USER   = 3;
    public static final byte SC_A_AUTH_TYPE     = 4;
    public static final byte SC_A_QUERY_STRING  = 5;
    public static final byte SC_A_JVM_ROUTE     = 6;
    public static final byte SC_A_SSL_CERT      = 7;
    public static final byte SC_A_SSL_CIPHER    = 8;
    public static final byte SC_A_SSL_SESSION   = 9;
    public static final byte SC_A_SSL_KEY_SIZE  = 11; // ajp14 originally, now in ajp13 with jk 1.2/2.0
    public static final byte SC_A_SECRET        = 12;
    public static final byte SC_A_STORED_METHOD = 13;

    // Used for attributes which are not in the list above
    public static final byte SC_A_REQ_ATTRIBUTE = 10; 

    // Terminates list of attributes
    public static final byte SC_A_ARE_DONE      = (byte)0xFF;
    
    // Translates integer codes to names of HTTP methods
    public static final String []methodTransArray = {
        "OPTIONS",
        "GET",
        "HEAD",
        "POST",
        "PUT",
        "DELETE",
        "TRACE",
        "PROPFIND",
        "PROPPATCH",
        "MKCOL",
        "COPY",
        "MOVE",
        "LOCK",
        "UNLOCK",
        "ACL",
        "REPORT",
        "VERSION-CONTROL",
        "CHECKIN",
        "CHECKOUT",
        "UNCHECKOUT",
        "SEARCH",
        "MKWORKSPACE",
        "UPDATE",
        "LABEL",
        "MERGE",
        "BASELINE-CONTROL",
        "MKACTIVITY"
    };
    public static final int SC_M_JK_STORED = (byte) 0xFF;

    
    // id's for common request headers
    public static final int SC_REQ_ACCEPT          = 1;
    public static final int SC_REQ_ACCEPT_CHARSET  = 2;
    public static final int SC_REQ_ACCEPT_ENCODING = 3;
    public static final int SC_REQ_ACCEPT_LANGUAGE = 4;
    public static final int SC_REQ_AUTHORIZATION   = 5;
    public static final int SC_REQ_CONNECTION      = 6;
    public static final int SC_REQ_CONTENT_TYPE    = 7;
    public static final int SC_REQ_CONTENT_LENGTH  = 8;
    public static final int SC_REQ_COOKIE          = 9;
    public static final int SC_REQ_COOKIE2         = 10;
    public static final int SC_REQ_HOST            = 11;
    public static final int SC_REQ_PRAGMA          = 12;
    public static final int SC_REQ_REFERER         = 13;
    public static final int SC_REQ_USER_AGENT      = 14;

    // Translates integer codes to request header names    
    public static final String []headerTransArray = {
        "accept",
        "accept-charset",
        "accept-encoding",
        "accept-language",
        "authorization",
        "connection",
        "content-type",
        "content-length",
        "cookie",
        "cookie2",
        "host",
        "pragma",
        "referer",
        "user-agent"
    };

    public RequestHandler() 
    {
    }

    public void init( Ajp13 ajp14 ) {
	// register incoming message handlers
	ajp14.registerMessageType( JK_AJP13_FORWARD_REQUEST,
				   "JK_AJP13_FORWARD_REQUEST",
				   this, null); // 2
	// register outgoing messages handler
	ajp14.registerMessageType( JK_AJP13_SEND_BODY_CHUNK, // 3
				   "JK_AJP13_SEND_BODY_CHUNK",
				   this,null );
	ajp14.registerMessageType( JK_AJP13_SEND_HEADERS,  // 4
				   "JK_AJP13_SEND_HEADERS",
				   this,null );
	ajp14.registerMessageType( JK_AJP13_END_RESPONSE, // 5
				   "JK_AJP13_END_RESPONSE",
				   this,null );
	ajp14.registerMessageType( JK_AJP13_GET_BODY_CHUNK, // 6
				   "JK_AJP13_GET_BODY_CHUNK",
				   this, null );
	ajp14.registerMessageType( JK_AJP13_CPING_REQUEST,
				   "JK_AJP13_PING_REQUEST",
				   this, null); // 10
	ajp14.registerMessageType( JK_AJP13_CPONG_REPLY,
				   "JK_AJP13_PONG_REPLY",
				   this, null); // 9
    }
    
    /**
     * Send a CPONG REPLY to web server to its CPING request
     * 
     * @param ch the Ajp13 channel
     * @param outBuf the Ajp13Packet output packet to use
     */
    public int sendCPong(Ajp13 ch, Ajp13Packet outBuf)
    {
		outBuf.reset();
		outBuf.appendByte(JK_AJP13_CPONG_REPLY);
    	
    	try
    	{
			ch.send(outBuf);
    	}
    	catch (IOException ioe)
    	{
    		log("can't send pong reply");
    	}
    	
    	return (999);	// success but no need to process farther
    }
    
    // -------------------- Incoming message --------------------
    public int handleAjpMessage( int type, Ajp13 channel,
				 Ajp13Packet ajp, BaseRequest req )
	throws IOException
    {
	switch( type ) {
	case RequestHandler.JK_AJP13_FORWARD_REQUEST:
	    return decodeRequest(channel, channel.hBuf, req );
		
	default:
	    return UNKNOWN;
	}
    }
    
    /**
     * Parse a FORWARD_REQUEST packet from the web server and store its
     * properties in the passed-in request object.
     *
     * @param req An empty (newly-recycled) request object.
     * @param msg Holds the packet which has just been sent by the web
     * server, with its read position just past the packet header (which in
     * this case includes the prefix code for FORWARD_REQUEST).
     *
     * @return 200 in case of a successful decoduing, 500 in case of error.  
     */
    protected int decodeRequest(Ajp13 ch, Ajp13Packet msg, BaseRequest req)
        throws IOException
    {
        
        if (debug > 0) {
            log("decodeRequest()");
        }

	// XXX Awful return values

        boolean isSSL = false;

        // Translate the HTTP method code to a String.
        byte methodCode = msg.getByte();
        if (methodCode != SC_M_JK_STORED)
          req.method().setString(methodTransArray[(int)methodCode - 1]);

        msg.getMessageBytes(req.protocol()); 
        msg.getMessageBytes(req.requestURI());

        msg.getMessageBytes(req.remoteAddr());
        msg.getMessageBytes(req.remoteHost());
        msg.getMessageBytes(req.serverName());
        req.setServerPort(msg.getInt());

	isSSL = msg.getBool();

	// Decode headers
	MimeHeaders headers = req.headers();
	int hCount = msg.getInt();
        for(int i = 0 ; i < hCount ; i++) {
            String hName = null;

	    // Header names are encoded as either an integer code starting
	    // with 0xA0, or as a normal string (in which case the first
	    // two bytes are the length).
            int isc = msg.peekInt();
            int hId = isc & 0xFF;

	    MessageBytes vMB=null;
            isc &= 0xFF00;
            if(0xA000 == isc) {
                //
                // header name is encoded as an int
                //
                msg.getInt(); // To advance the read position
                hName = headerTransArray[hId - 1];
		vMB= headers.addValue(hName);
                msg.getMessageBytes(vMB);

                if (hId == SC_REQ_CONTENT_LENGTH) {
                    // just read content-length header
                    int contentLength = (vMB == null) ? -1 : vMB.getInt();
                    req.setContentLength(contentLength);
                } else if (hId == SC_REQ_CONTENT_TYPE) {
                    // just read content-type header
                    ByteChunk bchunk = vMB.getByteChunk();
                    req.contentType().setBytes(bchunk.getBytes(),
                                               bchunk.getOffset(),
                                               bchunk.getLength());
                } else if (hId == SC_REQ_AUTHORIZATION) {
                    ByteChunk bchunk = vMB.getByteChunk();
                    req.authorization().setBytes(bchunk.getBytes(),
                                               bchunk.getOffset(),
                                               bchunk.getLength());
                }
            } else {
                //
                // header name is a string
                //
		// XXX Not very elegant
		vMB = msg.addHeader(headers);
		if (vMB == null) {
                    return 500; // wrong packet
                }
                msg.getMessageBytes(vMB);
            }
        }

	byte attributeCode;
        for(attributeCode = msg.getByte() ;
            attributeCode != SC_A_ARE_DONE ;
            attributeCode = msg.getByte()) {
            switch(attributeCode) {
	    case SC_A_CONTEXT      :
                break;
		
	    case SC_A_SERVLET_PATH :
                break;
		
	    case SC_A_REMOTE_USER  :
                msg.getMessageBytes(req.remoteUser());
                break;
		
	    case SC_A_AUTH_TYPE    :
                msg.getMessageBytes(req.authType());
                break;
		
	    case SC_A_QUERY_STRING :
		msg.getMessageBytes(req.queryString());
                break;
		
	    case SC_A_JVM_ROUTE    :
                msg.getMessageBytes(req.jvmRoute());
                break;
		
	    case SC_A_SSL_CERT     :
		isSSL = true;
                // Transform the string into certificate.
                String certString = msg.getString();
                byte[] certData = certString.getBytes();
                ByteArrayInputStream bais = new ByteArrayInputStream(certData);
 
                // Fill the first element.
                X509Certificate jsseCerts[] = null;
                try {
                    CertificateFactory cf =
                        CertificateFactory.getInstance("X.509");
                    X509Certificate cert = (X509Certificate)
                        cf.generateCertificate(bais);
                    jsseCerts =  new X509Certificate[1];
                    jsseCerts[0] = cert;
                } catch(java.security.cert.CertificateException e) {
                    log("Certificate convertion failed" + e );
                }
 
                req.setAttribute("javax.servlet.request.X509Certificate",
                                 jsseCerts);
                break;
		
	    case SC_A_SSL_CIPHER   :
		isSSL = true;
		req.setAttribute("javax.servlet.request.cipher_suite",
				 msg.getString());
                break;
		
	    case SC_A_SECRET   :
                // If a request has a secret attribute, set it on
                // channel - it'll be visible to the caller ( Interceptor,
                // Connector ) and it can check it against its settings before
                // trusting us.
                String secret=msg.getString();
                if(secret!=null) {
                    ch.setSecret( secret );
                }
                break;
		
	    case SC_A_SSL_SESSION  :
		isSSL = true;
		req.setAttribute("javax.servlet.request.ssl_session",
				  msg.getString());
                break;
		
	    case SC_A_REQ_ATTRIBUTE :
		req.setAttribute(msg.getString(), 
				 msg.getString());
                break;

	    case SC_A_SSL_KEY_SIZE: // Ajp13 !
                isSSL = true;
		req.setAttribute("javax.servlet.request.key_size",
				 Integer.toString(msg.getInt()));
		break;
    
        case SC_A_STORED_METHOD:
                req.method().setString(msg.getString());
                break;
    
	    default:
                // Ignore. Assume a single-string value - we shouldn't
                // allow anything else.
                msg.getString();
                break;
	    }
        }

        if(isSSL) {
            req.setScheme(req.SCHEME_HTTPS);
            req.setSecure(true);
        }

        // set cookies on request now that we have all headers
        req.cookies().setHeaders(req.headers());

	// Check to see if there should be a body packet coming along
	// immediately after
    	if(req.getContentLength() > 0) {

	    /* Read present data */
	    int err = ch.receive(ch.inBuf);
            if(err < 0) {
            	return 500;
	    }
	    
	    ch.blen = ch.inBuf.peekInt();
	    ch.pos = 0;
	    ch.inBuf.getBytes(ch.bodyBuff);
    	}
    
        if (debug > 5) {
            log(req.toString());
        }

        return 200; // Success
    }
    

    // -------------------- Messages from container to server ------------------
    
    /**
     * Send the HTTP headers back to the web server and on to the browser.
     *
     * @param status The HTTP status code to send.
     * @param statusMessage the HTTP status message to send.
     * @param headers The set of all headers.
     */
    public void sendHeaders(Ajp13 ch, Ajp13Packet outBuf,
			    int status, String statusMessage,
                            MimeHeaders headers)
        throws IOException
    {
	// XXX if more headers that MAX_SIZE, send 2 packets!
	if( statusMessage==null ) statusMessage=HttpMessages.getMessage(status);
	outBuf.reset();
        outBuf.appendByte(JK_AJP13_SEND_HEADERS);
        outBuf.appendInt(status);
	
	outBuf.appendString(statusMessage);
        
	int numHeaders = headers.size();
        outBuf.appendInt(numHeaders);
        
	for( int i=0 ; i < numHeaders ; i++ ) {
	    String headerName = headers.getName(i).toString();
	    int sc = headerNameToSc(headerName);
            if(-1 != sc) {
                outBuf.appendInt(sc);
            } else {
                outBuf.appendString(headerName);
            }
            outBuf.appendString(headers.getValue(i).toString() );
        }

        outBuf.end();
        ch.send(outBuf);
    } 


    /**
     * Signal the web server that the servlet has finished handling this
     * request, and that the connection can be reused.
     */
    public void finish(Ajp13 ch, Ajp13Packet outBuf) throws IOException {
        if (debug > 0)  log("finish()");

	outBuf.reset();
        outBuf.appendByte(JK_AJP13_END_RESPONSE);
        outBuf.appendBool(true); // Reuse this connection
        outBuf.end();
        ch.send(outBuf);
    }

    /**
     * Send a chunk of response body data to the web server and on to the
     * browser.
     *
     * @param b A huffer of bytes to send.
     * @param off The offset into the buffer from which to start sending.
     * @param len The number of bytes to send.
     */    
    public void doWrite(Ajp13 ch, Ajp13Packet outBuf,
			byte b[], int off, int len)
	throws IOException
    {
        if (debug > 0) log("doWrite(byte[], " + off + ", " + len + ")");

	int sent = 0;
	while(sent < len) {
	    int to_send = len - sent;
	    to_send = to_send > Ajp13.MAX_SEND_SIZE ? Ajp13.MAX_SEND_SIZE : to_send;

	    outBuf.reset();
	    outBuf.appendByte(JK_AJP13_SEND_BODY_CHUNK);	        	
	    outBuf.appendBytes(b, off + sent, to_send);	        
	    ch.send(outBuf);
	    sent += to_send;
	}
    }

    // -------------------- Utils -------------------- 

    /**
     * Translate an HTTP response header name to an integer code if
     * possible.  Case is ignored.
     * 
     * @param name The name of the response header to translate.
     *
     * @return The code for that header name, or -1 if no code exists.
     */
    protected int headerNameToSc(String name)
    {       
        switch(name.charAt(0)) {
	case 'c':
	case 'C':
	    if(name.equalsIgnoreCase("Content-Type")) {
		return SC_RESP_CONTENT_TYPE;
	    } else if(name.equalsIgnoreCase("Content-Language")) {
		return SC_RESP_CONTENT_LANGUAGE;
	    } else if(name.equalsIgnoreCase("Content-Length")) {
		return SC_RESP_CONTENT_LENGTH;
	    }
            break;
            
	case 'd':
	case 'D':
	    if(name.equalsIgnoreCase("Date")) {
                return SC_RESP_DATE;
	    }
            break;
            
	case 'l':
	case 'L':
	    if(name.equalsIgnoreCase("Last-Modified")) {
		return SC_RESP_LAST_MODIFIED;
	    } else if(name.equalsIgnoreCase("Location")) {
		return SC_RESP_LOCATION;
	    }
            break;

	case 's':
	case 'S':
	    if(name.equalsIgnoreCase("Set-Cookie")) {
		return SC_RESP_SET_COOKIE;
	    } else if(name.equalsIgnoreCase("Set-Cookie2")) {
		return SC_RESP_SET_COOKIE2;
	    }
            break;
            
	case 'w':
	case 'W':
	    if(name.equalsIgnoreCase("WWW-Authenticate")) {
		return SC_RESP_WWW_AUTHENTICATE;
	    }
            break;          
        }
        
        return -1;
    }
   
    private int debug=0;
    private Logger logger = new Logger();
    
    public void setDebug(int debug) {
        this.debug = debug;
    }

    public void setLogger(Logger l) {
        this.logger = l;
    }
    
    void log(String s) {
        logger.log("[RequestHandler] " + s );
    }

    // ==================== Servlet Input Support =================
    // XXX DEPRECATED
    
    public int available(Ajp13 ch) throws IOException {
        if (debug > 0) {
            log("available()");
        }

        if (ch.pos >= ch.blen) {
            if( ! refillReadBuffer(ch)) {
		return 0;
	    }
        }
        return ch.blen - ch.pos;
    }

    /**
     * Return the next byte of request body data (to a servlet).
     */
    public int doRead(Ajp13 ch) throws IOException 
    {
        if (debug > 0) {
            log("doRead()");
        }

        if(ch.pos >= ch.blen) {
            if( ! refillReadBuffer(ch)) {
		return -1;
	    }
        }
        return ch.bodyBuff[ch.pos++] & 0xFF;
    }
    
    /**
     * Store a chunk of request data into the passed-in byte buffer.
     *
     * @param b A buffer to fill with data from the request.
     * @param off The offset in the buffer at which to start filling.
     * @param len The number of bytes to copy into the buffer.
     *
     * @return The number of bytes actually copied into the buffer, or -1
     * if the end of the stream has been reached.
     */
    public int doRead(Ajp13 ch, byte[] b, int off, int len) throws IOException 
    {
        if (debug > 0) {
            log("doRead(byte[], int, int)");
        }

	if(ch.pos >= ch.blen) {
	    if( ! refillReadBuffer(ch)) {
		return -1;
	    }
	}

	if(ch.pos + len <= ch.blen) { // Fear the off by one error
	    // Sanity check b.length > off + len?
	    System.arraycopy(ch.bodyBuff, ch.pos, b, off, len);
	    ch.pos += len;
	    return len;
	}

	// Not enough data (blen < pos + len)
	int toCopy = len;
	while(toCopy > 0) {
	    int bytesRemaining = ch.blen - ch.pos;
	    if(bytesRemaining < 0) 
		bytesRemaining = 0;
	    int c = bytesRemaining < toCopy ? bytesRemaining : toCopy;
            
	    System.arraycopy(ch.bodyBuff, ch.pos, b, off, c);

	    toCopy    -= c;

	    off       += c;
	    ch.pos       += c; // In case we exactly consume the buffer

	    if(toCopy > 0) 
		if( ! refillReadBuffer(ch)) { // Resets blen and pos
		    break;
		}
	}

	return len - toCopy;
    }
    
    /**
     * Get more request body data from the web server and store it in the 
     * internal buffer.
     *
     * @return true if there is more data, false if not.    
     */
    public boolean refillReadBuffer(Ajp13 ch) throws IOException 
    {
        if (debug > 0) {
            log("refillReadBuffer()");
        }

	// If the server returns an empty packet, assume that that end of
	// the stream has been reached (yuck -- fix protocol??).

	// Why not use outBuf??
	ch.inBuf.reset();
	ch.inBuf.appendByte(JK_AJP13_GET_BODY_CHUNK);
	ch.inBuf.appendInt(Ajp13.MAX_READ_SIZE);
	ch.send(ch.inBuf);
	
	int err = ch.receive(ch.inBuf);
        if(err < 0) {
	    throw new IOException();
	}
	
        // check for empty packet, which means end of stream
        if (ch.inBuf.getLen() == 0) {
            if (debug > 0) {
                log("refillReadBuffer():  "
                    + "received empty packet -> end of stream");
            }
            ch.blen = 0;
            ch.pos = 0;
            return false;
        }

    	ch.blen = ch.inBuf.peekInt();
    	ch.pos = 0;
    	ch.inBuf.getBytes(ch.bodyBuff);

	return (ch.blen > 0);
    }    

    // ==================== Servlet Output Support =================
    
    /**
     */
    public void beginSendHeaders(Ajp13 ch, Ajp13Packet outBuf,
				 int status,
                                 String statusMessage,
                                 int numHeaders) throws IOException {

        if (debug > 0) {
            log("sendHeaders()");
        }

	// XXX if more headers that MAX_SIZE, send 2 packets!

	outBuf.reset();
        outBuf.appendByte(JK_AJP13_SEND_HEADERS);

        if (debug > 0) {
            log("status is:  " + status +
                       "(" + statusMessage + ")");
        }

        // set status code and message
        outBuf.appendInt(status);
        outBuf.appendString(statusMessage);

        // write the number of headers...
        outBuf.appendInt(numHeaders);
    }

    public void sendHeader(Ajp13Packet outBuf,
			   String name, String value)
	throws IOException
    {
        int sc = headerNameToSc(name);
        if(-1 != sc) {
            outBuf.appendInt(sc);
        } else {
            outBuf.appendString(name);
        }
        outBuf.appendString(value);
    }

    public void endSendHeaders(Ajp13 ch, Ajp13Packet outBuf)
	throws IOException
    {
        outBuf.end();
        ch.send(outBuf);
    }

    /**
     * Send the HTTP headers back to the web server and on to the browser.
     *
     * @param status The HTTP status code to send.
     * @param headers The set of all headers.
     */
    public void sendHeaders(Ajp13 ch, Ajp13Packet outBuf,
			    int status, MimeHeaders headers)
        throws IOException
    {
        sendHeaders(ch, outBuf, status, HttpMessages.getMessage(status),
                    headers);
    }
    

 }
