src/server/apache/ApacheTransport.cpp (246 lines of code) (raw):

/* * Copyright 2003-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. * * * @author Susantha Kumara (susantha@opensource.lk, skumara@virtusa.com) * @author Samisa Abeysinghe (sabeysinghe@virtusa.com) * */ /* * Revision 1.1 2004/05/24 samisa * Filled in the empty body of setTransportProperty */ #include "ApacheTransport.h" #define AXIS_URI_EXTENSION "/axis" /* Following is the character that should be used to separate the method name in * the SOAPAction header value. Ex: "Calculator#Add" */ #define SOAPACTION_METHODNAME_SEPARATOR "#" ApacheTransport::ApacheTransport(void* pContext) { m_eProtocolType = APTHTTP1_1; m_bHeadersSent = false; m_pContext = pContext; #ifndef CHUNCKED_DATA_SUPPORTED m_pBuffers = new BufferInfo[NO_OF_SERIALIZE_BUFFERS]; memset((void*)m_pBuffers, 0, sizeof(BufferInfo)*NO_OF_SERIALIZE_BUFFERS); #endif } ApacheTransport::~ApacheTransport() { if(m_pBuffers) { delete [] m_pBuffers; m_pBuffers = NULL; } } AXIS_TRANSPORT_STATUS ApacheTransport::sendBytes(const char* pcSendBuffer, const void* pBufferId) { if (!m_bHeadersSent) { ap_send_http_header ((request_rec*)m_pContext); m_bHeadersSent = true; } #ifndef CHUNCKED_DATA_SUPPORTED int index; #endif if (!pBufferId) /* temporary buffers should always sent immediately */ { ap_rputs(pcSendBuffer, (request_rec*)m_pContext); return TRANSPORT_FINISHED; } #ifdef CHUNCKED_DATA_SUPPORTED // Do we need to send any headers and length of this chunk ? ap_rputs(pcSendBuffer, (request_rec*)m_pContext); /* Do we need to send any indication to mark the end of this * chunk ? */ return TRANSPORT_FINISHED; #else for (index = 0; index < NO_OF_SERIALIZE_BUFFERS; index++) { if (!m_pBuffers[index].pcBuffer) { m_pBuffers[index].pcBuffer = pcSendBuffer; m_pBuffers[index].pBufferId = pBufferId; break; } } return TRANSPORT_IN_PROGRESS; #endif } int ApacheTransport::setTransportProperty(AXIS_TRANSPORT_INFORMATION_TYPE type, const char* value) { const char* key = NULL; switch (type) { case SOAPACTION_HEADER: /* needed only in the client side ? */ break; case SERVICE_URI: /* need to set ? */ break; case OPERATION_NAME: /* need to set ? */ break; case SOAP_MESSAGE_LENGTH: /* This is apache module and transport is http so the key */ key = "Content-Length"; break; default:; } if (key) { ap_table_set (((request_rec*)m_pContext)->headers_out, key, value); #ifdef CHUNCKED_DATA_SUPPORTED ap_send_http_header ((request_rec*)m_pContext); /* Should we remove the sent headers ? */ #endif } return 0; } AXIS_TRANSPORT_STATUS ApacheTransport::flushOutput() { #ifndef CHUNCKED_DATA_SUPPORTED int contentLength = 0; int index; char strtonum[8]; #endif #ifdef CHUNCKED_DATA_SUPPORTED /* headers have already been sent. see set_transport_information * http body too have been sent * Do we need to send any indication to mark end of chuncked * data ? */ #else /* Calculate Content-Length and set header */ for (index = 0; index < NO_OF_SERIALIZE_BUFFERS; index++) { if (!m_pBuffers[index].pcBuffer) break; contentLength += strlen(m_pBuffers[index].pcBuffer); } if (contentLength != 0) /* do only if the http body is not empty. */ { sprintf (strtonum, "%d", contentLength); setTransportProperty(SOAP_MESSAGE_LENGTH, strtonum); ap_send_http_header((request_rec*)m_pContext); /* Send all buffers */ for (index = 0; index < NO_OF_SERIALIZE_BUFFERS; index++) { if (!m_pBuffers[index].pcBuffer) break; ap_rputs(m_pBuffers[index].pcBuffer, (request_rec*)m_pContext); /* Let Axis know that the buffer is no longer in use */ m_pReleaseBufferCallback(m_pBuffers[index].pcBuffer, m_pBuffers[index].pBufferId); } } #endif return TRANSPORT_FINISHED; } AXIS_TRANSPORT_STATUS ApacheTransport::getBytes(char* pBuffer, int* piSize) { int nBufSize = *piSize; int len_read; ap_hard_timeout ("util_read", (request_rec*) m_pContext); len_read = ap_get_client_block ((request_rec*) m_pContext, pBuffer, *piSize); ap_reset_timeout ((request_rec*) m_pContext); *piSize = len_read; if (strstr(pBuffer, "Content-Id")) { pAttachmentHelper = new AttachmentHelper(); //char *pAttachBuffer = (char*)malloc(1000); //char *mimeBoundary = (char*)malloc(1000); pAttachmentHelper->extract_Attachment(pBuffer); pAttachmentHelper->extract_SOAPMimeHeaders(pBuffer); pAttachmentHelper->extract_Soap(pBuffer); } if (len_read < nBufSize) { pBuffer[len_read] = '\0'; return TRANSPORT_FINISHED; } else return TRANSPORT_IN_PROGRESS; } const char* ApacheTransport::getTransportProperty(AXIS_TRANSPORT_INFORMATION_TYPE eType) { const char* pcValue = NULL; /* the member, "path" of "parsed_uri" contains the uri of the request (i.e "/abc/xyz" part of http://somehost/abc/xyz) */ const char* pcUriPath = ((request_rec*)m_pContext)->parsed_uri.path; switch (eType) { case SOAPACTION_HEADER: return getTransportProperty("SOAPAction"); case SERVICE_URI: if (strstr(pcUriPath, AXIS_URI_EXTENSION)) { return strstr(pcUriPath, AXIS_URI_EXTENSION) + strlen (AXIS_URI_EXTENSION) + 1; } else { return pcUriPath; } case OPERATION_NAME: pcValue = getTransportProperty("SOAPAction"); if (pcValue) { if (strstr(pcValue, SOAPACTION_METHODNAME_SEPARATOR)) { return strstr(pcValue, SOAPACTION_METHODNAME_SEPARATOR) + strlen(SOAPACTION_METHODNAME_SEPARATOR); } else { return pcValue; } } case SOAP_MESSAGE_LENGTH: return getTransportProperty("Content-Length"); /* this is apache module and transport is http so the key */ default:; } return NULL; } int ApacheTransport::setTransportProperty(const char* pcKey, const char* pcValue) { if (pcKey && pcValue) { ap_table_set (((request_rec*)m_pContext)->headers_out, pcKey, pcValue); #ifdef CHUNCKED_DATA_SUPPORTED ap_send_http_header ((request_rec*)m_pContext); /* Should we remove the sent headers ? */ #endif } return 0; } const char* ApacheTransport::getTransportProperty(const char* pcKey, bool response) { /* ap_table_elts returns an array_header struct. The nelts element of that * struct contains the number of input header elements. Finally assigns that * to the axis soap data structure. */ array_header* arr = NULL; int headercount = ap_table_elts(((request_rec*)m_pContext)->headers_in)->nelts; Ax_header* pHeaders = 0; /* casting req_rec->headers_in to axis header struct and assigning that to * the axis soap structure. Hope this is ok */ /* obtain the array_header from the headers_in table and assign it to the * axis soap structure */ arr = ap_table_elts(((request_rec*)m_pContext)->headers_in); pHeaders = (Ax_header*) arr->elts; for (int ix=0; ix<headercount; ix++) { if (!strcmp(pHeaders->headername, pcKey)) return pHeaders->headervalue; pHeaders++; } return 0; } void ApacheTransport::setSessionId(const char* pcSessionId) { } const char* ApacheTransport::getSessionId() { return "this is temporary session id"; //TODO } const char* ApacheTransport::getServiceName() { return 0; //TODO } AXIS_PROTOCOL_TYPE ApacheTransport::getProtocol() { return m_eProtocolType; } int ApacheTransport::setProtocol(AXIS_PROTOCOL_TYPE eProtocol) { if( eProtocol == APTHTTP1_1 || eProtocol == APTHTTP1_0 ) { m_eProtocolType = eProtocol; return AXIS_SUCCESS; } else return AXIS_FAIL; } int ApacheTransport::getSubProtocol() { //Determine the http method and assign it to the axis soap structure switch (((request_rec*)m_pContext)->method_number) { case M_GET: return AXIS_HTTP_GET; case M_POST: return AXIS_HTTP_POST; default: return AXIS_HTTP_UNSUPPORTED; } } ISoapAttachment* ApacheTransport::getAttachment(const char* pcAttachmentid) { ISoapAttachment* pAttch = pAttachmentHelper->getAttachment(pcAttachmentid); return pAttch; }; char* ApacheTransport::getIncomingSOAPMimeHeaders() { return pAttachmentHelper->getIncomingSOAPMimeHeaders(); } ISoapAttachment** ApacheTransport::getAllAttachments(int *pAttchArraySize) { ISoapAttachment** pAttachments = pAttachmentHelper->getAllAttachments(pAttchArraySize); return pAttachments; }