Author: midon
Date: Fri Jul 18 18:40:06 2008
New Revision: 678089
URL: http://svn.apache.org/viewvc?rev=678089&view=rev
Log:
ODE-310: better status code handling for 4xx & 5xx
Modified:
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpHelper.java
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java
ode/branches/APACHE_ODE_1.X/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpHelperTest.java
Modified:
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java
URL:
http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java?rev=678089&r1=678088&r2=678089&view=diff
==============================================================================
---
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java
(original)
+++
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpExternalService.java
Fri Jul 18 18:40:06 2008
@@ -39,6 +39,7 @@
import org.apache.ode.bpel.iapi.ProcessConf;
import org.apache.ode.bpel.iapi.Scheduler;
import org.apache.ode.utils.DOMUtils;
+import static org.apache.ode.utils.http.StatusCode.*;
import org.apache.ode.utils.wsdl.Messages;
import org.apache.ode.utils.wsdl.WsdlUtils;
import org.w3c.dom.Element;
@@ -276,10 +277,8 @@
_2xx_success();
} else if (statusCode >= 300 && statusCode < 400) {
_3xx_redirection();
- } else if (statusCode >= 400 && statusCode < 500) {
- _4xx_badRequest();
- } else if (statusCode >= 500 && statusCode < 600) {
- _5xx_serverError();
+ } else if (statusCode >= 400 && statusCode < 600) {
+ _4xx_5xx_error();
} else {
unmanagedStatus();
}
@@ -310,20 +309,26 @@
errmsg = "[Service: " + serviceName + ", Port: " + portName +
", Operation: " + operation.getName() + "] Status-Line: " +
method.getStatusLine() + " for " + method.getURI();
log.warn(errmsg);
}
- PartnerRoleMessageExchange odeMex = (PartnerRoleMessageExchange)
server.getEngine().getMessageExchange(mexId);
- Object[] fault = httpMethodConverter.parseFault(odeMex, method);
- Message response = (Message) fault[1];
- QName faultName = (QName) fault[0];
-
- // finally send the fault. We did it!
- if (log.isWarnEnabled())
- log.warn("[Service: " + serviceName + ", Port: " + portName +
", Operation: " + operation.getName() + "] Fault response: faultName=" +
faultName + " faultType=" + response.getType() + "\n" +
DOMUtils.domToString(response.getMessage()));
-
- odeMex.replyWithFault(faultName, response);
+ int status = method.getStatusCode();
+ if (status == _503_SERVICE_UNAVAILABLE
+ || status == _504_GATEWAY_TIMEOUT) {
+ // reply with a failure, meaning the request might be repeated
+ replyWithFailure("HTTP Status-Line: " + method.getStatusLine()
+ " for " + method.getURI());
+ } else {
+ // reply with a fault, meaning the request should not be
repeated later
+ replyWithFault();
+ }
}
- private void _4xx_badRequest() throws Exception {
- replyWithFailure("HTTP Status-Line: " + method.getStatusLine() + "
for " + method.getURI());
+ private void _4xx_5xx_error() throws Exception {
+ int status = method.getStatusCode();
+ if(HttpHelper.isFaultOrFailure(status)>0){
+ // reply with a fault, meaning the request should not be
repeated
+ replyWithFault();
+ } else {
+ // reply with a failure, meaning the request might be repeated
later
+ replyWithFailure("HTTP Status-Line: " + method.getStatusLine()
+ " for " + method.getURI());
+ }
}
private void _3xx_redirection() throws Exception {
@@ -355,6 +360,20 @@
}
}
+ void replyWithFault() {
+ PartnerRoleMessageExchange odeMex = (PartnerRoleMessageExchange)
server.getEngine().getMessageExchange(mexId);
+ Object[] fault = httpMethodConverter.parseFault(odeMex, method);
+ Message response = (Message) fault[1];
+ QName faultName = (QName) fault[0];
+
+ // finally send the fault. We did it!
+ if (log.isWarnEnabled())
+ log.warn("[Service: " + serviceName + ", Port: " + portName +
", Operation: " + operation.getName() + "] Fault response: faultName=" +
faultName + " faultType=" + response.getType() + "\n" +
DOMUtils.domToString(response.getMessage()));
+
+ odeMex.replyWithFault(faultName, response);
+ }
+
+
void replyWithFailure(String errmsg) {
replyWithFailure(errmsg, null);
}
@@ -365,4 +384,4 @@
odeMex.replyWithFailure(MessageExchange.FailureType.OTHER, errmsg,
HttpHelper.prepareDetailsElement(method));
}
}
-}
+}
\ No newline at end of file
Modified:
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpHelper.java
URL:
http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpHelper.java?rev=678089&r1=678088&r2=678089&view=diff
==============================================================================
---
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpHelper.java
(original)
+++
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpHelper.java
Fri Jul 18 18:40:06 2008
@@ -30,21 +30,18 @@
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
-import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.params.HttpParams;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.lang.StringUtils;
import org.apache.ode.axis2.Properties;
import org.apache.ode.utils.DOMUtils;
+import org.apache.ode.utils.http.HttpUtils;
+import static org.apache.ode.utils.http.StatusCode.*;
import org.w3c.dom.Element;
import org.w3c.dom.Document;
import java.io.IOException;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.io.StringWriter;
-import java.io.PipedOutputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -128,7 +125,7 @@
public static Element prepareDetailsElement(HttpMethod method) {
Header h = method.getResponseHeader("Content-Type");
String receivedType = h != null ? h.getValue() : null;
- boolean bodyIsXml = receivedType != null &&
HttpHelper.isXml(receivedType);
+ boolean bodyIsXml = receivedType != null &&
HttpUtils.isXml(receivedType);
Document doc = DOMUtils.newDocument();
@@ -203,20 +200,6 @@
return sb.toString();
}
- public static final String XML_MIME_TYPE_REGEX =
"(text/xml)|(application/xml)|((.*)\\+xml)";
- private static final String TEXT_MIME_TYPE_REGEX = "text/(?!xml$).*";
- private static final Pattern XML_MIME_TYPE_PATTERN =
Pattern.compile(XML_MIME_TYPE_REGEX);
- private static final Pattern TEXT_MIME_TYPE_PATTERN =
Pattern.compile(TEXT_MIME_TYPE_REGEX);
-
- public static boolean isXml(String contentType) {
- return XML_MIME_TYPE_PATTERN.matcher(contentType).matches();
- }
-
- public static boolean isText(String contentType) {
- return TEXT_MIME_TYPE_PATTERN.matcher(contentType).matches();
- }
-
-
public static String requestToString(HttpMethod m) {
StringBuilder sb = new StringBuilder(256);
try {
@@ -278,4 +261,44 @@
}
return sb.toString();
}
+
+ /**
+ *
+ * @param s, the status code to test, must be in [400, 600[
+ * @return 1 if fault, -1 if failure, 0 if undetermined
+ */
+ public static int isFaultOrFailure(int s) {
+ if (s < 400 || s >= 600) {
+ throw new IllegalArgumentException("Status-Code must be in
interval [400;600[");
+ }
+ if (s == _500_INTERNAL_SERVER_ERROR
+ || s == _501_NOT_IMPLEMENTED
+ || s == _502_BAD_GATEWAY
+ || s == _505_HTTP_VERSION_NOT_SUPPORTED
+ || s == _400_BAD_REQUEST
+ || s == _402_PAYMENT_REQUIRED
+ || s == _403_FORBIDDEN
+ || s == _404_NOT_FOUND
+ || s == _405_METHOD_NOT_ALLOWED
+ || s == _406_NOT_ACCEPTABLE
+ || s == _407_PROXY_AUTHENTICATION_REQUIRED
+ || s == _409_CONFLICT
+ || s == _410_GONE
+ || s == _412_PRECONDITION_FAILED
+ || s == _413_REQUEST_TOO_LONG
+ || s == _414_REQUEST_URI_TOO_LONG
+ || s == _415_UNSUPPORTED_MEDIA_TYPE
+ || s == _411_LENGTH_REQUIRED
+ || s == _416_REQUESTED_RANGE_NOT_SATISFIABLE
+ || s == _417_EXPECTATION_FAILED) {
+ return 1;
+ } else if (s == _503_SERVICE_UNAVAILABLE
+ || s == _504_GATEWAY_TIMEOUT
+ || s == _401_UNAUTHORIZED
+ || s == _408_REQUEST_TIMEOUT) {
+ return -1;
+ } else {
+ return 0;
+ }
+ }
}
Modified:
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java
URL:
http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java?rev=678089&r1=678088&r2=678089&view=diff
==============================================================================
---
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java
(original)
+++
ode/branches/APACHE_ODE_1.X/axis2/src/main/java/org/apache/ode/axis2/httpbinding/HttpMethodConverter.java
Fri Jul 18 18:40:06 2008
@@ -39,6 +39,9 @@
import org.apache.ode.bpel.iapi.PartnerRoleMessageExchange;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.Namespaces;
+import org.apache.ode.utils.http.HttpUtils;
+import static org.apache.ode.utils.http.HttpUtils.bodyAllowed;
+import static org.apache.ode.utils.http.StatusCode.*;
import org.apache.ode.utils.wsdl.Messages;
import org.apache.ode.utils.wsdl.WsdlUtils;
import org.w3c.dom.Document;
@@ -194,7 +197,7 @@
String errMsg = "XML Types are not supported. Parts must
use elements.";
if (log.isErrorEnabled()) log.error(errMsg);
throw new RuntimeException(errMsg);
- } else if (HttpHelper.isXml(contentType)) {
+ } else if (HttpUtils.isXml(contentType)) {
if (log.isDebugEnabled()) log.debug("Content-Type [" +
contentType + "] equivalent to 'text/xml'");
// stringify the first element
String xmlString =
DOMUtils.domToString(DOMUtils.getFirstChildElement(partValue));
@@ -431,12 +434,12 @@
// assumption is made that a response may have at most one body.
HttpBindingValidator checks this.
MIMEContent outputContent =
WsdlUtils.getMimeContent(opBinding.getBindingOutput().getExtensibilityElements());
- int statusCode = method.getStatusCode();
+ int status = method.getStatusCode();
- boolean xmlExpected = outputContent != null &&
HttpHelper.isXml(outputContent.getType());
+ boolean xmlExpected = outputContent != null &&
HttpUtils.isXml(outputContent.getType());
// '202/Accepted' and '204/No Content' status codes explicitly state
that there is no body, so we should not fail even if a part is bound to the
body response
boolean isBodyExpected = outputContent != null;
- boolean isBodyMandatory = isBodyExpected && statusCode != 204 &&
statusCode != 202;
+ boolean isBodyMandatory = isBodyExpected && bodyAllowed(status) &&
status != _202_ACCEPTED;
final String body;
try {
body = method.getResponseBodyAsString();
@@ -459,7 +462,7 @@
Header h = method.getResponseHeader("Content-Type");
String receivedType = h != null ? h.getValue() : null;
boolean contentTypeSet = receivedType != null;
- boolean xmlReceived = contentTypeSet &&
HttpHelper.isXml(receivedType);
+ boolean xmlReceived = contentTypeSet &&
HttpUtils.isXml(receivedType);
// a few checks
if (!contentTypeSet) {
@@ -506,7 +509,7 @@
throw new RuntimeException("No fault binding. This " +
method.getStatusCode() + " error will be considered as a failure.");
} else if (StringUtils.isEmpty(body)) {
throw new RuntimeException("No body in the response. This " +
method.getStatusCode() + " error will be considered as a failure.");
- } else if (receivedType != null && !HttpHelper.isXml(receivedType)) {
+ } else if (receivedType != null && !HttpUtils.isXml(receivedType)) {
throw new RuntimeException("Response Content-Type [" +
receivedType + "] does not describe XML entities. Faults must be XML. This " +
method.getStatusCode() + " error will be considered as a failure.");
} else {
Modified:
ode/branches/APACHE_ODE_1.X/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpHelperTest.java
URL:
http://svn.apache.org/viewvc/ode/branches/APACHE_ODE_1.X/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpHelperTest.java?rev=678089&r1=678088&r2=678089&view=diff
==============================================================================
---
ode/branches/APACHE_ODE_1.X/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpHelperTest.java
(original)
+++
ode/branches/APACHE_ODE_1.X/axis2/src/test/java/org/apache/ode/axis2/httpbinding/HttpHelperTest.java
Fri Jul 18 18:40:06 2008
@@ -20,8 +20,7 @@
package org.apache.ode.axis2.httpbinding;
import junit.framework.TestCase;
-import org.apache.ode.utils.DOMUtils;
-import org.w3c.dom.Document;
+import org.apache.ode.utils.http.HttpUtils;
/**
*
@@ -51,26 +50,26 @@
public void testIsXml() {
for (String s : IS_XML) {
- assertTrue(s+" is an xml type", HttpHelper.isXml(s));
+ assertTrue(s+" is an xml type", HttpUtils.isXml(s));
}
for (String s : IS_TEXT) {
- assertFalse(s+" is not an xml type", HttpHelper.isXml(s));
+ assertFalse(s+" is not an xml type", HttpUtils.isXml(s));
}
for (String s : IS_IMAGE) {
- assertFalse(s+" is not an xml type", HttpHelper.isXml(s));
+ assertFalse(s+" is not an xml type", HttpUtils.isXml(s));
}
}
public void testIsText() {
for (String s : IS_TEXT) {
- assertTrue(s+" is a text type", HttpHelper.isText(s));
+ assertTrue(s+" is a text type", HttpUtils.isText(s));
}
for (String s : IS_XML) {
- assertFalse(s+" is not a text type", HttpHelper.isText(s));
+ assertFalse(s+" is not a text type", HttpUtils.isText(s));
}
for (String s : IS_IMAGE) {
- assertFalse(s+" is not a text type", HttpHelper.isXml(s));
+ assertFalse(s+" is not a text type", HttpUtils.isXml(s));
}
}
}