Author: ruwan Date: Sun May 24 14:42:25 2009 New Revision: 36667 URL: http://wso2.org/svn/browse/wso2?view=rev&revision=36667
Log: Asankha's changes from the synapse trunk Modified: branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/SynapseConstants.java branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/DefaultEndpointFactory.java branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/core/axis2/Axis2FlexibleMEPClient.java branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/endpoints/EndpointDefinition.java branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/Axis2HttpRequest.java branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ClientHandler.java branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ClientWorker.java branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/HttpCoreNIOSender.java branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/NhttpConstants.java branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ServerHandler.java branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ServerWorker.java branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/util/RESTUtil.java Modified: branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/SynapseConstants.java URL: http://wso2.org/svn/browse/wso2/branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/SynapseConstants.java?rev=36667&r1=36666&r2=36667&view=diff ============================================================================== --- branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/SynapseConstants.java (original) +++ branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/SynapseConstants.java Sun May 24 14:42:25 2009 @@ -280,7 +280,8 @@ public static final String FORMAT_POX = "pox"; public static final String FORMAT_GET = "get"; public static final String FORMAT_SOAP11 = "soap11"; - public static final String FORMAT_SOAP12 = "soap12"; + public static final String FORMAT_SOAP12 = "soap12"; + public static final String FORMAT_REST = "rest"; /** Synapse server instance name */ public static final String SERVER_NAME = "serverName"; Modified: branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/DefaultEndpointFactory.java URL: http://wso2.org/svn/browse/wso2/branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/DefaultEndpointFactory.java?rev=36667&r1=36666&r2=36667&view=diff ============================================================================== --- branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/DefaultEndpointFactory.java (original) +++ branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/config/xml/endpoints/DefaultEndpointFactory.java Sun May 24 14:42:25 2009 @@ -112,6 +112,10 @@ definition.setForceSOAP12(true); definition.setFormat(SynapseConstants.FORMAT_SOAP12); + } else if (SynapseConstants.FORMAT_REST.equals(forceValue)) { + definition.setForceREST(true); + definition.setFormat(SynapseConstants.FORMAT_REST); + } else { handleException("force value -\"" + forceValue + "\" not yet implemented"); } Modified: branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/core/axis2/Axis2FlexibleMEPClient.java URL: http://wso2.org/svn/browse/wso2/branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/core/axis2/Axis2FlexibleMEPClient.java?rev=36667&r1=36666&r2=36667&view=diff ============================================================================== --- branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/core/axis2/Axis2FlexibleMEPClient.java (original) +++ branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/core/axis2/Axis2FlexibleMEPClient.java Sun May 24 14:42:25 2009 @@ -41,6 +41,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.synapse.SynapseConstants; +import org.apache.synapse.transport.nhttp.NhttpConstants; import org.apache.synapse.endpoints.EndpointDefinition; import org.apache.synapse.util.MessageHelper; import org.apache.sandesha2.client.SandeshaClientConstants; @@ -165,8 +166,10 @@ } if(axisOutMsgCtx.isSOAP11()) { SOAPUtils.convertSOAP11toSOAP12(axisOutMsgCtx); - } - + } + + } else if (SynapseConstants.FORMAT_REST.equals(endpoint.getFormat())) { + axisOutMsgCtx.setDoingREST(true); } if (endpoint.isUseMTOM()) { @@ -192,7 +195,16 @@ } if (endpoint.getAddress() != null) { - axisOutMsgCtx.setTo(new EndpointReference(endpoint.getAddress())); + if (SynapseConstants.FORMAT_REST.equals(endpoint.getFormat()) && + axisOutMsgCtx.getProperty(NhttpConstants.REST_URL_POSTFIX) != null) { + axisOutMsgCtx.setTo( + new EndpointReference(endpoint.getAddress() + + axisOutMsgCtx.getProperty(NhttpConstants.REST_URL_POSTFIX) + )); + } else { + axisOutMsgCtx.setTo(new EndpointReference(endpoint.getAddress())); + } + axisOutMsgCtx.setProperty(NhttpConstants.ENDPOINT_PREFIX, endpoint.getAddress()); } if (endpoint.isUseSeparateListener()) { Modified: branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/endpoints/EndpointDefinition.java URL: http://wso2.org/svn/browse/wso2/branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/endpoints/EndpointDefinition.java?rev=36667&r1=36666&r2=36667&view=diff ============================================================================== --- branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/endpoints/EndpointDefinition.java (original) +++ branches/synapse/1.3-wso2v1/modules/core/src/main/java/org/apache/synapse/endpoints/EndpointDefinition.java Sun May 24 14:42:25 2009 @@ -92,6 +92,10 @@ */ private boolean forceSOAP12 = false; /** + * force REST on ? + */ + private boolean forceREST = false; + /** * use MTOM * */ private boolean useMTOM = false; @@ -350,6 +354,14 @@ return forceSOAP12; } + public boolean isForceREST() { + return forceREST; + } + + public void setForceREST(boolean forceREST) { + this.forceREST = forceREST; + } + public boolean isUseMTOM() { return useMTOM; } Modified: branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/Axis2HttpRequest.java URL: http://wso2.org/svn/browse/wso2/branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/Axis2HttpRequest.java?rev=36667&r1=36666&r2=36667&view=diff ============================================================================== --- branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/Axis2HttpRequest.java (original) +++ branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/Axis2HttpRequest.java Sun May 24 14:42:25 2009 @@ -72,14 +72,16 @@ OMOutputFormat format = null; private ContentOutputBuffer outputBuffer = null; /** ready to begin streaming? */ - private boolean readyToStream = false; + private volatile boolean readyToStream = false; /** The sending of this request has fully completed */ - private boolean sendingCompleted = false; + private volatile boolean sendingCompleted = false; /** * for request complete checking - request complete means the request has been fully sent * and the response it fully received */ - private boolean completed = false; + private volatile boolean completed = false; + /** The URL prefix of the endpoint (to be used for Location header re-writing in the response)*/ + private String endpointURLPrefix = null; public Axis2HttpRequest(EndpointReference epr, HttpHost httpHost, MessageContext msgContext) { this.epr = epr; @@ -127,33 +129,38 @@ this.timeout = timeout; } + public String getEndpointURLPrefix() { + return endpointURLPrefix; + } + + public void setEndpointURLPrefix(String endpointURLPrefix) { + this.endpointURLPrefix = endpointURLPrefix; + } + /** * Create and return a new HttpPost request to the destination EPR * @return the HttpRequest to be sent out */ public HttpRequest getRequest() throws IOException { - boolean doingGET = Constants.Configuration.HTTP_METHOD_GET.equals( - msgContext.getProperty(Constants.Configuration.HTTP_METHOD)); + String httpMethod = (String) msgContext.getProperty(Constants.Configuration.HTTP_METHOD); + if (httpMethod == null) { + httpMethod = "POST"; + } + endpointURLPrefix = (String) msgContext.getProperty(NhttpConstants.ENDPOINT_PREFIX); HttpRequest httpRequest = null; - if (msgContext.isPropertyTrue(NhttpConstants.FORCE_HTTP_1_0)) { - - if (doingGET) { - - httpRequest = new BasicHttpRequest( - "GET", RESTUtil.getURI( - msgContext, epr.getAddress()), HttpVersion.HTTP_1_0); - - } else { + if ("POST".equals(httpMethod) || "PUT".equals(httpMethod)) { - if (msgContext.isPropertyTrue(NhttpConstants.POST_TO_PATH)) { - httpRequest = new BasicHttpEntityEnclosingRequest( - "POST", new URL(epr.getAddress()).getPath(), HttpVersion.HTTP_1_0); - } else { - httpRequest = new BasicHttpEntityEnclosingRequest( - "POST", epr.getAddress(), HttpVersion.HTTP_1_0); - } - + httpRequest = new BasicHttpEntityEnclosingRequest( + httpMethod, + msgContext.isPropertyTrue(NhttpConstants.POST_TO_PATH) ? + new URL(epr.getAddress()).getPath() : epr.getAddress(), + msgContext.isPropertyTrue(NhttpConstants.FORCE_HTTP_1_0) ? + HttpVersion.HTTP_1_0 : HttpVersion.HTTP_1_1); + + BasicHttpEntity entity = new BasicHttpEntity(); + + if (msgContext.isPropertyTrue(NhttpConstants.FORCE_HTTP_1_0)) { TemporaryData serialized = new TemporaryData(256, 4096, "http-nio_", ".dat"); OutputStream out = serialized.getOutputStream(); try { @@ -161,34 +168,25 @@ } finally { out.close(); } - BasicHttpEntity entity = new BasicHttpEntity(); msgContext.setProperty(NhttpConstants.SERIALIZED_BYTES, serialized); entity.setContentLength(serialized.getLength()); - ((BasicHttpEntityEnclosingRequest) httpRequest).setEntity(entity); - + } else { + entity.setChunked(!msgContext.isPropertyTrue(NhttpConstants.DISABLE_CHUNKING)); } + ((BasicHttpEntityEnclosingRequest) httpRequest).setEntity(entity); + httpRequest.setHeader( + HTTP.CONTENT_TYPE, + messageFormatter.getContentType(msgContext, format, msgContext.getSoapAction())); } else { - if (doingGET) { - - httpRequest = new BasicHttpRequest( - "GET", RESTUtil.getURI(msgContext, epr.getAddress())); - - } else { - if (msgContext.isPropertyTrue(NhttpConstants.POST_TO_PATH)) { - httpRequest = new BasicHttpEntityEnclosingRequest( - "POST", new URL(epr.getAddress()).getPath()); - } else { - httpRequest = new BasicHttpEntityEnclosingRequest("POST", epr.getAddress()); - } - BasicHttpEntity entity = new BasicHttpEntity(); - if (msgContext.isPropertyTrue(NhttpConstants.DISABLE_CHUNKING)) { - entity.setChunked(false); - } - ((BasicHttpEntityEnclosingRequest) httpRequest).setEntity(entity); - } + httpRequest = new BasicHttpRequest( + httpMethod, + msgContext.isPropertyTrue(NhttpConstants.POST_TO_PATH) ? + new URL(epr.getAddress()).getPath() : epr.getAddress(), + msgContext.isPropertyTrue(NhttpConstants.FORCE_HTTP_1_0) ? + HttpVersion.HTTP_1_0 : HttpVersion.HTTP_1_1); } // set any transport headers @@ -229,10 +227,6 @@ soapAction); } - httpRequest.setHeader( - HTTP.CONTENT_TYPE, - messageFormatter.getContentType(msgContext, format, msgContext.getSoapAction())); - if (NHttpConfiguration.getInstance().isKeepAliveDisabled() || msgContext.isPropertyTrue(NhttpConstants.NO_KEEPALIVE)) { httpRequest.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_CLOSE); Modified: branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ClientHandler.java URL: http://wso2.org/svn/browse/wso2/branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ClientHandler.java?rev=36667&r1=36666&r2=36667&view=diff ============================================================================== --- branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ClientHandler.java (original) +++ branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ClientHandler.java Sun May 24 14:42:25 2009 @@ -189,9 +189,11 @@ if (axis2Req.getTimeout() > 0) { conn.setSocketTimeout(axis2Req.getTimeout()); } - - conn.submitRequest(request); + + context.setAttribute(NhttpConstants.ENDPOINT_PREFIX, axis2Req.getEndpointURLPrefix()); + context.setAttribute(NhttpConstants.HTTP_REQ_METHOD, request.getRequestLine().getMethod()); context.setAttribute(ExecutionContext.HTTP_REQUEST, request); + conn.submitRequest(request); } catch (ConnectionClosedException e) { throw e; } catch (IOException e) { @@ -469,10 +471,15 @@ if (context.getAttribute(NhttpConstants.DISCARD_ON_COMPLETE) != null) { try { // this is a connection we should not re-use - conn.shutdown(); + ConnectionPool.forget(conn); + shutdownConnection(conn); + context.removeAttribute(RESPONSE_SINK_BUFFER); + context.removeAttribute(REQUEST_SOURCE_BUFFER); } catch (Exception ignore) {} } else if (!connStrategy.keepAlive(response, context)) { - conn.close(); + shutdownConnection(conn); + context.removeAttribute(RESPONSE_SINK_BUFFER); + context.removeAttribute(REQUEST_SOURCE_BUFFER); } else { ConnectionPool.release(conn); } @@ -537,17 +544,27 @@ HttpContext context = conn.getContext(); HttpResponse response = conn.getHttpResponse(); + if (response.getStatusLine().getStatusCode() == HttpStatus.SC_CONTINUE) { + if (log.isDebugEnabled()) { + log.debug("Received a 100 Continue response"); + } + // according to the HTTP 1.1 specification HTTP status 100 continue implies that + // the response will be followed, and the client should just ignore the 100 Continue + // and wait for the response + return; + } + // Have we sent out our request fully in the first place? if not, forget about it now.. Axis2HttpRequest req = (Axis2HttpRequest) conn.getContext().getAttribute(AXIS2_HTTP_REQUEST); if (req != null) { + req.setCompleted(true); + if (log.isDebugEnabled()) { log.debug("Response Received for Request : " + req); } - if (HttpStatus.SC_CONTINUE != response.getStatusLine().getStatusCode() && - !req.isSendingCompleted()) { - req.setCompleted(true); + if (!req.isSendingCompleted()) { req.getMsgContext().setProperty( NhttpConstants.ERROR_CODE, NhttpConstants.SEND_ABORT); SharedOutputBuffer outputBuffer = (SharedOutputBuffer) @@ -555,7 +572,11 @@ if (outputBuffer != null) { outputBuffer.shutdown(); } - log.warn("Remote server aborted request being sent and replied : " + conn); + if (log.isDebugEnabled()) { + log.debug("Remote server aborted request being sent and replied : " + conn + + " for request : " + conn.getContext().getAttribute( + NhttpConstants.HTTP_REQ_METHOD)); + } context.setAttribute(NhttpConstants.DISCARD_ON_COMPLETE, Boolean.TRUE); if (metrics != null) { metrics.incrementFaultsSending(NhttpConstants.SEND_ABORT, req.getMsgContext()); @@ -631,38 +652,18 @@ return; } - case HttpStatus.SC_BAD_REQUEST : { - log.error(getErrorMessage("Received bad request: " - + response.getStatusLine().getReasonPhrase(), conn)); - return; - } - case HttpStatus.SC_INTERNAL_SERVER_ERROR : { - log.error(getErrorMessage("Received an internal server error : " + - response.getStatusLine().getReasonPhrase(), conn)); - processResponse(conn, context, response); - return; - } - case HttpStatus.SC_CONTINUE : { - - if (log.isDebugEnabled()) { - log.debug("Received a 100 Continue response"); - } - - // according to the HTTP 1.1 specification HTTP status 100 continue implies that - // the response will be followed, and the client should just ignore the 100 Continue - // and wait for the response - return; - } case HttpStatus.SC_OK : { processResponse(conn, context, response); return; } default : { - log.warn(getErrorMessage("Unexpected HTTP status code received : " + + if (log.isDebugEnabled()) { + log.debug(getErrorMessage("HTTP status code received : " + response.getStatusLine().getStatusCode() + " :: " + response.getStatusLine().getReasonPhrase(), conn)); + } - Header contentType = response.getFirstHeader(CONTENT_TYPE); + Header contentType = response.getFirstHeader(HTTP.CONTENT_TYPE); if (contentType != null) { if ((contentType.getValue().indexOf(SOAP11Constants.SOAP_11_CONTENT_TYPE) >= 0) || contentType.getValue().indexOf( @@ -684,10 +685,12 @@ response.getStatusLine().getReasonPhrase(), conn)); } } else { - log.warn(getErrorMessage("Received an unexpected response - " + - "of unknown content type with status code : " + + if (log.isDebugEnabled()) { + log.debug(getErrorMessage("Received a response - " + + "without a content type with status code : " + response.getStatusLine().getStatusCode() + " and reason : " + response.getStatusLine().getReasonPhrase(), conn)); + } } processResponse(conn, context, response); @@ -705,20 +708,55 @@ private void processResponse(final NHttpClientConnection conn, HttpContext context, HttpResponse response) { - ContentInputBuffer inputBuffer - = new SharedInputBuffer(cfg.getBufferSize(), conn, allocator); - context.setAttribute(RESPONSE_SINK_BUFFER, inputBuffer); + ContentInputBuffer inputBuffer = null; + MessageContext outMsgContext = (MessageContext) context.getAttribute(OUTGOING_MESSAGE_CONTEXT); + String endptPrefix = (String) context.getAttribute(NhttpConstants.ENDPOINT_PREFIX); + String requestMethod = (String) context.getAttribute(NhttpConstants.HTTP_REQ_METHOD); + int statusCode = response.getStatusLine().getStatusCode(); + + boolean expectEntityBody = false; + if (!"HEAD".equals(requestMethod) && !"OPTIONS".equals(requestMethod) && + statusCode >= HttpStatus.SC_OK + && statusCode != HttpStatus.SC_NO_CONTENT + && statusCode != HttpStatus.SC_NOT_MODIFIED + && statusCode != HttpStatus.SC_RESET_CONTENT) { + expectEntityBody = true; + } + + if (expectEntityBody) { + inputBuffer + = new SharedInputBuffer(cfg.getBufferSize(), conn, allocator); + context.setAttribute(RESPONSE_SINK_BUFFER, inputBuffer); BasicHttpEntity entity = new BasicHttpEntity(); - if (response.getStatusLine().getProtocolVersion().greaterEquals(HttpVersion.HTTP_1_1)) { - entity.setChunked(true); + if (response.getStatusLine().getProtocolVersion().greaterEquals(HttpVersion.HTTP_1_1)) { + entity.setChunked(true); + } + response.setEntity(entity); + context.setAttribute(ExecutionContext.HTTP_RESPONSE, response); + + } else { + conn.resetInput(); + conn.resetOutput(); + + if (context.getAttribute(NhttpConstants.DISCARD_ON_COMPLETE) != null || + !connStrategy.keepAlive(response, context)) { + try { + // this is a connection we should not re-use + ConnectionPool.forget(conn); + shutdownConnection(conn); + context.removeAttribute(RESPONSE_SINK_BUFFER); + context.removeAttribute(REQUEST_SOURCE_BUFFER); + } catch (Exception ignore) {} + } else { + ConnectionPool.release(conn); + } } - response.setEntity(entity); - context.setAttribute(ExecutionContext.HTTP_RESPONSE, response); workerPool.execute( - new ClientWorker(cfgCtx, new ContentInputStream(inputBuffer), response, - (MessageContext) context.getAttribute(OUTGOING_MESSAGE_CONTEXT))); + new ClientWorker(cfgCtx, + inputBuffer == null ? null : new ContentInputStream(inputBuffer), + response, outMsgContext, endptPrefix)); } Modified: branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ClientWorker.java URL: http://wso2.org/svn/browse/wso2/branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ClientWorker.java?rev=36667&r1=36666&r2=36667&view=diff ============================================================================== --- branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ClientWorker.java (original) +++ branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ClientWorker.java Sun May 24 14:42:25 2009 @@ -59,6 +59,8 @@ private InputStream in = null; /** the HttpResponse received */ private HttpResponse response = null; + /** the endpoint URL prefix */ + private String endpointURLPrefix = null; /** * Create the thread that would process the response message received for the outgoing message @@ -68,11 +70,12 @@ * @param outMsgCtx the original outgoing message context (i.e. corresponding request) */ public ClientWorker(ConfigurationContext cfgCtx, InputStream in, - HttpResponse response, MessageContext outMsgCtx) { + HttpResponse response, MessageContext outMsgCtx, String endpointURLPrefix) { this.cfgCtx = cfgCtx; this.in = in; this.response = response; + this.endpointURLPrefix = endpointURLPrefix; try { responseMsgCtx = outMsgCtx.getOperationContext(). @@ -116,7 +119,16 @@ Map headerMap = new HashMap(); for (int i=0; i<headers.length; i++) { Header header = headers[i]; - headerMap.put(header.getName(), header.getValue()); + if ("Location".equals(header.getName()) + && endpointURLPrefix != null + && outMsgCtx.getProperty(NhttpConstants.SERVICE_PREFIX) != null) { + + headerMap.put(header.getName(), + header.getValue().replaceAll(endpointURLPrefix, + (String) outMsgCtx.getProperty(NhttpConstants.SERVICE_PREFIX))); + } else { + headerMap.put(header.getName(), header.getValue()); + } } responseMsgCtx.setProperty(MessageContext.TRANSPORT_HEADERS, headerMap); } @@ -144,58 +156,63 @@ Header cType = response.getFirstHeader(HTTP.CONTENT_TYPE); - String contentType = ""; if (cType != null) { - contentType = cType.getValue(); - } + String contentType = cType.getValue(); - String charSetEnc = BuilderUtil.getCharSetEncoding(contentType); - if (charSetEnc == null) { - charSetEnc = MessageContext.DEFAULT_CHAR_SET_ENCODING; - } + String charSetEnc = BuilderUtil.getCharSetEncoding(contentType); + if (charSetEnc == null) { + charSetEnc = MessageContext.DEFAULT_CHAR_SET_ENCODING; + } - if (contentType.indexOf(HTTP.CHARSET_PARAM) > 0) { - responseMsgCtx.setProperty(Constants.Configuration.CHARACTER_SET_ENCODING, charSetEnc); - } else { - responseMsgCtx.setProperty(Constants.Configuration.CHARACTER_SET_ENCODING, - MessageContext.DEFAULT_CHAR_SET_ENCODING); - } - // workaround for Axis2 TransportUtils.createSOAPMessage() issue, where a response - // of content type "text/xml" is thought to be REST if !MC.isServerSide(). This - // question is still under debate and due to the timelines, I am commiting this - // workaround as Axis2 1.2 is about to be released and Synapse 1.0 - responseMsgCtx.setServerSide(false); - try { - envelope = TransportUtils.createSOAPMessage( - responseMsgCtx, - HTTPTransportUtils.handleGZip(responseMsgCtx, in), - contentType); - } catch (OMException e) { - // handle non SOAP and POX/REST payloads (probably text/html) - String errorMessage = "Unexpected response received. HTTP response code : " - + this.response.getStatusLine().getStatusCode() + " HTTP status : " - + this.response.getStatusLine().getReasonPhrase() + " exception : " - + e.getMessage(); - - log.warn(errorMessage); - if (log.isDebugEnabled()) { - log.debug(errorMessage, e); - log.debug("Creating the SOAPFault to be injected..."); + responseMsgCtx.setProperty( + Constants.Configuration.CHARACTER_SET_ENCODING, + contentType.indexOf(HTTP.CHARSET_PARAM) > 0 ? + charSetEnc : MessageContext.DEFAULT_CHAR_SET_ENCODING); + + // workaround for Axis2 TransportUtils.createSOAPMessage() issue, where a response + // of content type "text/xml" is thought to be REST if !MC.isServerSide(). This + // question is still under debate and due to the timelines, I am commiting this + // workaround as Axis2 1.2 is about to be released and Synapse 1.0 + responseMsgCtx.setServerSide(false); + try { + envelope = TransportUtils.createSOAPMessage( + responseMsgCtx, + HTTPTransportUtils.handleGZip(responseMsgCtx, in), + contentType); + + } catch (OMException e) { + // handle non SOAP and POX/REST payloads (probably text/html) + String errorMessage = "Unexpected response received. HTTP response code : " + + this.response.getStatusLine().getStatusCode() + " HTTP status : " + + this.response.getStatusLine().getReasonPhrase() + " exception : " + + e.getMessage(); + + log.warn(errorMessage); + if (log.isDebugEnabled()) { + log.debug(errorMessage, e); + log.debug("Creating the SOAPFault to be injected..."); + } + SOAPFactory factory = new SOAP11Factory(); + envelope = factory.getDefaultFaultEnvelope(); + SOAPFaultDetail detail = factory.createSOAPFaultDetail(); + detail.setText(errorMessage); + envelope.getBody().getFault().setDetail(detail); + SOAPFaultReason reason = factory.createSOAPFaultReason(); + reason.setText(errorMessage); + envelope.getBody().getFault().setReason(reason); + SOAPFaultCode code = factory.createSOAPFaultCode(); + code.setText(Integer.toString(this.response.getStatusLine().getStatusCode())); + envelope.getBody().getFault().setCode(code); } - SOAPFactory factory = new SOAP11Factory(); - envelope = factory.getDefaultFaultEnvelope(); - SOAPFaultDetail detail = factory.createSOAPFaultDetail(); - detail.setText(errorMessage); - envelope.getBody().getFault().setDetail(detail); - SOAPFaultReason reason = factory.createSOAPFaultReason(); - reason.setText(errorMessage); - envelope.getBody().getFault().setReason(reason); - SOAPFaultCode code = factory.createSOAPFaultCode(); - code.setText(Integer.toString(this.response.getStatusLine().getStatusCode())); - envelope.getBody().getFault().setCode(code); + responseMsgCtx.setServerSide(true); + responseMsgCtx.setEnvelope(envelope); + + } else { + // there is no response entity-body + responseMsgCtx.setProperty(NhttpConstants.NO_ENTITY_BODY, Boolean.TRUE); + responseMsgCtx.setEnvelope(new SOAP11Factory().getDefaultEnvelope()); } - responseMsgCtx.setServerSide(true); - responseMsgCtx.setEnvelope(envelope); + // copy the HTTP status code as a message context property with the key HTTP_SC to be // used at the sender to set the propper status code when passing the message int statusCode = this.response.getStatusLine().getStatusCode(); @@ -204,6 +221,9 @@ responseMsgCtx.setProperty(NhttpConstants.FAULT_MESSAGE, NhttpConstants.TRUE); } responseMsgCtx.setProperty(NhttpConstants.NON_BLOCKING_TRANSPORT, true); + if (endpointURLPrefix != null) { + responseMsgCtx.setProperty(NhttpConstants.ENDPOINT_PREFIX, endpointURLPrefix); + } // process response received try { Modified: branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/HttpCoreNIOSender.java URL: http://wso2.org/svn/browse/wso2/branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/HttpCoreNIOSender.java?rev=36667&r1=36666&r2=36667&view=diff ============================================================================== --- branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/HttpCoreNIOSender.java (original) +++ branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/HttpCoreNIOSender.java Sun May 24 14:42:25 2009 @@ -427,10 +427,12 @@ OMOutputFormat format = NhttpUtil.getOMOutputFormat(msgContext); MessageFormatter messageFormatter = MessageFormatterDecoratorFactory.createMessageFormatterDecorator(msgContext); - response.setHeader( - HTTP.CONTENT_TYPE, - messageFormatter.getContentType(msgContext, format, msgContext.getSoapAction())); - + Boolean noEntityBody = (Boolean) msgContext.getProperty(NhttpConstants.NO_ENTITY_BODY); + if (noEntityBody == null || Boolean.FALSE == noEntityBody) { + response.setHeader( + HTTP.CONTENT_TYPE, + messageFormatter.getContentType(msgContext, format, msgContext.getSoapAction())); + } response.setStatusCode(determineHttpStatusCode(msgContext, response)); // set any transport headers @@ -456,7 +458,8 @@ * if this is a dummy message to handle http 202 case with non-blocking IO * write an empty byte array as body */ - if (msgContext.isPropertyTrue(NhttpConstants.SC_ACCEPTED)) { + if (msgContext.isPropertyTrue(NhttpConstants.SC_ACCEPTED) + || Boolean.TRUE == noEntityBody) { out.write(new byte[0]); } else { messageFormatter.writeTo(msgContext, format, out, false); Modified: branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/NhttpConstants.java URL: http://wso2.org/svn/browse/wso2/branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/NhttpConstants.java?rev=36667&r1=36666&r2=36667&view=diff ============================================================================== --- branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/NhttpConstants.java (original) +++ branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/NhttpConstants.java Sun May 24 14:42:25 2009 @@ -77,4 +77,10 @@ public static final int CONNECT_TIMEOUT = 101508; public static final int SEND_ABORT = 101509; // ********** DO NOT CHANGE THESE UNLESS CORRESPONDING SYNAPSE CONSTANT ARE CHANGED ************ + + public static final String REST_URL_POSTFIX = "REST_URL_POSTFIX"; + public static final String SERVICE_PREFIX = "SERVICE_PREFIX"; + public static final String HTTP_REQ_METHOD = "HTTP_REQ_METHOD"; + public static final String NO_ENTITY_BODY = "NO_ENTITY_BODY"; + public static final String ENDPOINT_PREFIX = "ENDPOINT_PREFIX"; } Modified: branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ServerHandler.java URL: http://wso2.org/svn/browse/wso2/branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ServerHandler.java?rev=36667&r1=36666&r2=36667&view=diff ============================================================================== --- branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ServerHandler.java (original) +++ branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ServerHandler.java Sun May 24 14:42:25 2009 @@ -115,18 +115,19 @@ HttpRequest request = conn.getHttpRequest(); context.setAttribute(ExecutionContext.HTTP_REQUEST, request); - // Mark request as not yet fully read, to detect timeouts from harmless keepalive deaths - conn.getContext().setAttribute(NhttpConstants.REQUEST_READ, Boolean.FALSE); - try { InputStream is; // Only create an input buffer and ContentInputStream if the request has content if (request instanceof HttpEntityEnclosingRequest) { + // Mark request as not yet fully read, to detect timeouts from harmless keepalive deaths + conn.getContext().setAttribute(NhttpConstants.REQUEST_READ, Boolean.FALSE); + ContentInputBuffer inputBuffer = new SharedInputBuffer(cfg.getBufferSize(), conn, allocator); context.setAttribute(REQUEST_SINK_BUFFER, inputBuffer); is = new ContentInputStream(inputBuffer); } else { is = null; + conn.getContext().removeAttribute(NhttpConstants.REQUEST_READ); } ContentOutputBuffer outputBuffer = new SharedOutputBuffer(cfg.getBufferSize(), conn, allocator); Modified: branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ServerWorker.java URL: http://wso2.org/svn/browse/wso2/branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ServerWorker.java?rev=36667&r1=36666&r2=36667&view=diff ============================================================================== --- branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ServerWorker.java (original) +++ branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/ServerWorker.java Sun May 24 14:42:25 2009 @@ -21,6 +21,7 @@ import org.apache.axiom.om.util.UUIDGenerator; import org.apache.axis2.AxisFault; import org.apache.axis2.Constants; +import org.apache.axis2.builder.BuilderUtil; import org.apache.axis2.addressing.EndpointReference; import org.apache.axis2.context.ConfigurationContext; import org.apache.axis2.context.MessageContext; @@ -189,10 +190,63 @@ public void run() { String method = request.getRequestLine().getMethod().toUpperCase(); + msgContext.setProperty(Constants.Configuration.HTTP_METHOD, + request.getRequestLine().getMethod()); + + String uri = request.getRequestLine().getUri(); + String oriUri = uri; + + if (uri.indexOf(cfgCtx.getServicePath()) != -1) { + // discard upto servicePath + uri = uri.substring(uri.indexOf(cfgCtx.getServicePath()) + + cfgCtx.getServicePath().length()); + // discard [proxy] service name if any + int pos = uri.indexOf("/", 1); + if (pos > 0) { + uri = uri.substring(pos); + } else { + pos = uri.indexOf("?"); + if (pos != -1) { + uri = uri.substring(pos); + } else { + uri = ""; + } + } + } else { + // remove any absolute prefix if any + int pos = uri.indexOf("://"); + if (pos != -1) { + uri = uri.substring(pos + 3); + pos = uri.indexOf("/"); + if (pos != -1) { + uri = uri.substring(pos + 1); + } + } + } + msgContext.setProperty(NhttpConstants.REST_URL_POSTFIX, uri); + String servicePrefix = oriUri.substring(0, oriUri.indexOf(uri)); + if (servicePrefix.indexOf("://") == -1) { + HttpInetConnection inetConn = (HttpInetConnection) conn; + InetAddress localAddr = inetConn.getLocalAddress(); + servicePrefix = (isHttps ? "https://" : "http://") + + localAddr.getHostName() + ":" + inetConn.getLocalPort() + servicePrefix; + } + msgContext.setProperty(NhttpConstants.SERVICE_PREFIX, servicePrefix); + if ("GET".equals(method)) { processGet(); } else if ("POST".equals(method)) { - processPost(); + processEntityEnclosingMethod(); + } else if ("PUT".equals(method)) { + processEntityEnclosingMethod(); + } else if ("HEAD".equals(method)) { + processNonEntityEnclosingMethod(); + } else if ("OPTIONS".equals(method)) { + processNonEntityEnclosingMethod(); + } else if ("DELETE".equals(method)) { + processNonEntityEnclosingMethod(); + } else if ("TRACE".equals(method)) { + processNonEntityEnclosingMethod(); } else { handleException("Unsupported method : " + method, null); } @@ -281,16 +335,21 @@ /** * */ - private void processPost() { + private void processEntityEnclosingMethod() { try { Header contentType = request.getFirstHeader(HTTP.CONTENT_TYPE); + String contentTypeStr = contentType != null ? contentType.getValue() : null; + + String charSetEncoding = BuilderUtil.getCharSetEncoding(contentTypeStr); + msgContext.setProperty(Constants.Configuration.CHARACTER_SET_ENCODING, charSetEncoding); + Header soapAction = request.getFirstHeader(SOAPACTION); HTTPTransportUtils.processHTTPPostRequest( msgContext, is, os, - (contentType != null ? contentType.getValue() : null), + contentTypeStr, (soapAction != null ? soapAction.getValue() : null), request.getRequestLine().getUri()); } catch (AxisFault e) { @@ -299,6 +358,22 @@ } /** + * Process HEAD, DELETE, TRACE, OPTIONS + */ + private void processNonEntityEnclosingMethod() { + + try { + RESTUtil.processURLRequest( + msgContext, os, null, + request.getRequestLine().getUri()); + + } catch (AxisFault e) { + handleException("Error processing " + request.getRequestLine().getMethod() + + " request for : " + request.getRequestLine().getUri(), e); + } + } + + /** * */ private void processGet() { @@ -346,11 +421,6 @@ msgContext.setTo(new EndpointReference(uri)); } - if ("GET".equalsIgnoreCase(request.getRequestLine().getMethod())) { - msgContext.setProperty(Constants.Configuration.HTTP_METHOD, - Constants.Configuration.HTTP_METHOD_GET); - } - if (uri.equals("/favicon.ico")) { response.setStatusCode(HttpStatus.SC_MOVED_PERMANENTLY); response.addHeader(LOCATION, "http://ws.apache.org/favicon.ico"); @@ -503,20 +573,14 @@ } else { try { - if (RESTUtil.processURLRequest( + RESTUtil.processGETRequest( msgContext, os, (request.getFirstHeader(SOAPACTION) != null ? request.getFirstHeader(SOAPACTION).getValue() : null), - request.getRequestLine().getUri(), cfgCtx, parameters)) { - // If RestUtil succesfully decoded the request, do not let the output - // stream close (as by default below) since we are serving this GET request - // through the Synapse engine - return; - } else { - response.setStatusCode(HttpStatus.SC_MOVED_PERMANENTLY); - response.addHeader(LOCATION, servicePath + "/"); - serverHandler.commitResponseHideExceptions(conn, response); - } - + request.getRequestLine().getUri(), cfgCtx, parameters); + // do not let the output stream close (as by default below) since + // we are serving this GET request through the Synapse engine + return; + } catch (AxisFault axisFault) { handleException("Error processing GET request for: " + request.getRequestLine().getUri(), axisFault); Modified: branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/util/RESTUtil.java URL: http://wso2.org/svn/browse/wso2/branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/util/RESTUtil.java?rev=36667&r1=36666&r2=36667&view=diff ============================================================================== --- branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/util/RESTUtil.java (original) +++ branches/synapse/1.3-wso2v1/modules/transports/core/nhttp/src/main/java/org/apache/synapse/transport/nhttp/util/RESTUtil.java Sun May 24 14:42:25 2009 @@ -34,6 +34,7 @@ import org.apache.axis2.engine.AxisEngine; import org.apache.axis2.transport.http.util.URIEncoderDecoder; import org.apache.axis2.util.Utils; +import org.apache.synapse.transport.nhttp.NhttpConstants; import java.io.OutputStream; import java.io.UnsupportedEncodingException; @@ -123,11 +124,11 @@ * @param requestURI The URL that the request came to * @param configurationContext The Axis Configuration Context * @param requestParameters The parameters of the request message - * @return boolean indication whether the operation was succesfull * @throws AxisFault - Thrown in case a fault occurs */ - public static boolean processURLRequest(MessageContext msgContext, OutputStream out, - String soapAction, String requestURI, ConfigurationContext configurationContext, + public static void processGETRequest(MessageContext msgContext, OutputStream out, + String soapAction, String requestURI, + ConfigurationContext configurationContext, Map requestParameters) throws AxisFault { if ((soapAction != null) && soapAction.startsWith("\"") && soapAction.endsWith("\"")) { @@ -138,17 +139,36 @@ msgContext.setTo(new EndpointReference(requestURI)); msgContext.setProperty(MessageContext.TRANSPORT_OUT, out); msgContext.setServerSide(true); - SOAPEnvelope envelope = createEnvelopeFromGetRequest( - requestURI, requestParameters, configurationContext); + msgContext.setDoingREST(true); + msgContext.setEnvelope(createEnvelopeFromGetRequest( + requestURI, requestParameters, configurationContext)); + msgContext.setProperty(NhttpConstants.NO_ENTITY_BODY, Boolean.TRUE); + AxisEngine.receive(msgContext); + } - if (envelope == null) { - return false; - } else { - msgContext.setDoingREST(true); - msgContext.setEnvelope(envelope); - AxisEngine.receive(msgContext); - return true; + /** + * Processes the HTTP GET request and builds the SOAP info-set of the REST message + * + * @param msgContext The MessageContext of the Request Message + * @param out The output stream of the response + * @param soapAction SoapAction of the request + * @param requestURI The URL that the request came to + * @throws AxisFault - Thrown in case a fault occurs + */ + public static void processURLRequest(MessageContext msgContext, OutputStream out, + String soapAction, String requestURI) throws AxisFault { + + if ((soapAction != null) && soapAction.startsWith("\"") && soapAction.endsWith("\"")) { + soapAction = soapAction.substring(1, soapAction.length() - 1); } + msgContext.setSoapAction(soapAction); + msgContext.setTo(new EndpointReference(requestURI)); + msgContext.setProperty(MessageContext.TRANSPORT_OUT, out); + msgContext.setServerSide(true); + msgContext.setDoingREST(true); + msgContext.setEnvelope(new SOAP11Factory().getDefaultEnvelope()); + msgContext.setProperty(NhttpConstants.NO_ENTITY_BODY, Boolean.TRUE); + AxisEngine.receive(msgContext); } /** @@ -161,7 +181,7 @@ * @return created SOAPEnvelope or null if cannot be processed * @throws AxisFault if the service represented by the GET request URL cannot be found */ - public static SOAPEnvelope createEnvelopeFromGetRequest(String requestUrl, Map map, + private static SOAPEnvelope createEnvelopeFromGetRequest(String requestUrl, Map map, ConfigurationContext configCtx) throws AxisFault { String[] values = Utils.parseRequestURLForServiceAndOperation( _______________________________________________ Esb-java-dev mailing list [email protected] https://wso2.org/cgi-bin/mailman/listinfo/esb-java-dev
