Skip to content
Permalink
Browse files

Fix #241 and fix #242 (plus misc fixes)

  • Loading branch information
ndw committed Dec 16, 2016
1 parent b46fe75 commit f5fdcb60924da43f9a23cca546a611c9713746ea
Showing with 49 additions and 77 deletions.
  1. +49 −77 src/main/java/com/xmlcalabash/library/HttpRequest.java
@@ -46,6 +46,7 @@
import org.apache.http.Consts;
import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
@@ -126,12 +127,9 @@

private static final int bufSize = 912 * 8; // A multiple of 3, 4, and 75 for base64 line breaking

private boolean statusOnly = false;
private boolean detailed = false;
private String method = null;
private URI requestURI = null;
private Vector<Header> headers = new Vector<Header> ();
private String contentType = null;
private String overrideContentType = null;
private String headerContentType = null;
private boolean encodeBinary = false;
@@ -191,8 +189,8 @@ public void run() throws SaxonApiException {
String send = step.getExtensionAttribute(cx_send_binary);
encodeBinary = !"true".equals(send);

method = start.getAttributeValue(_method);
statusOnly = "true".equals(start.getAttributeValue(_status_only));
boolean statusOnly = "true".equals(start.getAttributeValue(_status_only));
String method = start.getAttributeValue(_method);
detailed = "true".equals(start.getAttributeValue(_detailed));
overrideContentType = start.getAttributeValue(_override_content_type);

@@ -267,13 +265,15 @@ public void run() throws SaxonApiException {
throw XProcException.stepError(3, "Unsupported auth-method: " + meth);
}

rqbuilder.setProxyPreferredAuthSchemes(authpref);

String host = requestURI.getHost();
int port = requestURI.getPort();
AuthScope scope = new AuthScope(host,port);
// Or this? new AuthScope(null, AuthScope.ANY_PORT)

BasicCredentialsProvider bCredsProvider = new BasicCredentialsProvider();
bCredsProvider.setCredentials(new AuthScope(null, AuthScope.ANY_PORT),
new UsernamePasswordCredentials(user, pass));
bCredsProvider.setCredentials(scope, new UsernamePasswordCredentials(user, pass));
builder.setDefaultCredentialsProvider(bCredsProvider);
}

@@ -484,7 +484,7 @@ private void doPutOrPostSinglepart(HttpEntityEnclosingRequest method, XdmNode bo
// ATTENTION: This doesn't handle multipart, that's done entirely separately

// Check for consistency of content-type
contentType = body.getAttributeValue(_content_type);
String contentType = body.getAttributeValue(_content_type);
if (contentType == null) {
throw new XProcException(step.getNode(), "Content-type on c:body is required.");
}
@@ -553,37 +553,49 @@ private void doPutOrPostSinglepart(HttpEntityEnclosingRequest method, XdmNode bo
method.addHeader(header);
}

// FIXME: This sucks rocks. I want to write the data to be posted, not provide some way to read it
String postContent = null;
String encoding = body.getAttributeValue(_encoding);

if (encoding != null && !"base64".equals(encoding)) {
throw XProcException.stepError(52);
}

HttpEntity requestEntity = null;

try {
if ("base64".equals(encoding)) {
String charset = body.getAttributeValue(_charset);
// FIXME: is utf-8 the right default?
if (charset == null) { charset = "utf-8"; }

// Make sure it's all characters
XdmSequenceIterator iter = body.axisIterator(Axis.CHILD);
while (iter.hasNext()) {
XdmNode node = (XdmNode) iter.next();
if (node.getNodeKind() != XdmNodeKind.TEXT) {
throw XProcException.stepError(28);

// See also: https://github.com/ndw/xmlcalabash1/pull/241 and
// https://github.com/ndw/xmlcalabash1/issues/242
//
// The PR proposes ignoring the charset and treating the data as binary.
// That's clearly necessary for the case where the data *is* binary.
// However, if the base64 encoded element *has* a charset parameter,
// I think that's an indication that it *should* be encoded. If it isn't
// encoded, then the charset would have to be included in the POST and
// I'm not sure that's straightforward.
//
// My solution is to leave the encoding in place when the charset is
// explicitly set, but post binary decoded data otherwise. In other
// words, the answer to the comment "is utf-8 the right default?" that
// used to be here is: No.

String content = extractText(body);
byte[] decoded = Base64.decode(content);

if (charset == null) {
// Treat as binary
requestEntity = new ByteArrayEntity(decoded, ContentType.create(contentType));
} else {
// Treat as encoded characters
try {
requestEntity = new StringEntity(new String(decoded, charset), ContentType.create(contentType, "UTF-8"));
} catch (UnsupportedEncodingException uee) {
throw XProcException.stepError(10, uee);
}
}

String escapedContent = decodeBase64(body, charset);
StringWriter writer = new StringWriter();
writer.write(escapedContent);
writer.close();
postContent = writer.toString();
} else {
if (jsonContentType(contentType)) {
postContent = XMLtoJSON.convert(body);
requestEntity = new StringEntity(XMLtoJSON.convert(body), ContentType.create(contentType, "UTF-8"));
} else if (xmlContentType(contentType)) {
Serializer serializer = makeSerializer();

@@ -605,23 +617,12 @@ private void doPutOrPostSinglepart(HttpEntityEnclosingRequest method, XdmNode bo
serializer.setOutputWriter(writer);
S9apiUtils.serialize(runtime, content, serializer);
writer.close();
postContent = writer.toString();
requestEntity = new StringEntity(writer.toString(), ContentType.create(contentType, "UTF-8"));
} else {
StringWriter writer = new StringWriter();
XdmSequenceIterator iter = body.axisIterator(Axis.CHILD);
while (iter.hasNext()) {
XdmNode node = (XdmNode) iter.next();
if (node.getNodeKind() != XdmNodeKind.TEXT) {
throw XProcException.stepError(28);
}
writer.write(node.getStringValue());
}
writer.close();
postContent = writer.toString();
requestEntity = new StringEntity(extractText(body), ContentType.create(contentType, "UTF-8"));
}
}

StringEntity requestEntity = new StringEntity(postContent, ContentType.create(contentType, "UTF-8"));
method.setEntity(requestEntity);

} catch (IOException ioe) {
@@ -636,7 +637,7 @@ private void doPutOrPostMultipart(HttpEntityEnclosingRequest method, XdmNode mul
// and build the body ourselves, using the boundaries etc.

// Check for consistency of content-type
contentType = multipart.getAttributeValue(_content_type);
String contentType = multipart.getAttributeValue(_content_type);
if (contentType == null) {
contentType = "multipart/mixed";
}
@@ -705,35 +706,25 @@ private void doPutOrPostMultipart(HttpEntityEnclosingRequest method, XdmNode mul

if (bodyCharset != null) {
bodyContentType += "; charset=" + bodyCharset;
} else {
// Is utf-8 the right default? What about the image/ case?
bodyContentType += "; charset=utf-8";
}

//postContent += "--" + boundary + "\r\n";
//postContent += "Content-Type: " + bodyContentType + "\r\n";
byteContent.append("--" + boundary + "\r\n");
byteContent.append("Content-Type: " + bodyContentType + "\r\n");

if (bodyDescription != null) {
//postContent += "Content-Description: " + bodyDescription + "\r\n";
byteContent.append("Content-Description: " + bodyDescription + "\r\n");
}
if (bodyId != null) {
//postContent += "Content-ID: " + bodyId + "\r\n";
byteContent.append("Content-ID: " + bodyId + "\r\n");
}
if (bodyDisposition != null) {
//postContent += "Content-Disposition: " + bodyDisposition + "\r\n";
byteContent.append("Content-Disposition: " + bodyDisposition + "\r\n");
}
if (bodyEncoding != null) {
//postContent += "Content-Transfer-Encoding: " + bodyEncoding + "\r\n";
if (encodeBinary) {
byteContent.append("Content-Transfer-Encoding: " + bodyEncoding + "\r\n");
}
}
//postContent += "\r\n";
byteContent.append("\r\n");

try {
@@ -752,26 +743,14 @@ private void doPutOrPostMultipart(HttpEntityEnclosingRequest method, XdmNode mul
serializer.setOutputWriter(writer);
S9apiUtils.serialize(runtime, content, serializer);
writer.close();
//postContent += writer.toString();
byteContent.append(writer.toString());
} else if (jsonContentType(contentType)) {
byteContent.append(XMLtoJSON.convert(body));
} else if (!encodeBinary && "base64".equals(bodyEncoding)) {
byte[] decoded = Base64.decode(body.getStringValue());
byteContent.append(decoded, decoded.length);
} else {
StringWriter writer = new StringWriter();
XdmSequenceIterator iter = body.axisIterator(Axis.CHILD);
while (iter.hasNext()) {
XdmNode node = (XdmNode) iter.next();
if (node.getNodeKind() != XdmNodeKind.TEXT) {
throw XProcException.stepError(28);
}
writer.write(node.getStringValue());
}
writer.close();
//postContent += writer.toString();
byteContent.append(writer.toString());
byteContent.append(extractText(body));
}

//postContent += "\r\n";
@@ -944,7 +923,7 @@ private void readMultipartContent(TreeWriter tree, InputStream bodyStream, Strin
Header pctype = reader.getHeader("Content-Type");
Header pclen = reader.getHeader("Content-Length");

contentType = getHeaderValue(pctype);
String contentType = getHeaderValue(pctype);

String charset = getContentCharset(pctype);
String partType = getHeaderValue(pctype);
@@ -1083,24 +1062,17 @@ public void readBodyContentPart(TreeWriter tree, InputStream bodyStream, String

private String extractText(XdmNode doc) {
String content = "";

XdmSequenceIterator iter = doc.axisIterator(Axis.CHILD);
while (iter.hasNext()) {
XdmNode child = (XdmNode) iter.next();
if (child.getNodeKind() == XdmNodeKind.ELEMENT || child.getNodeKind() == XdmNodeKind.TEXT) {
content += child.getStringValue();
if (child.getNodeKind() != XdmNodeKind.TEXT) {
throw XProcException.stepError(28);
}
content += child.getStringValue();
}
return content;
}

private String decodeBase64(XdmNode doc, String charset) {
String content = extractText(doc);
byte[] decoded = Base64.decode(content);
try {
return new String(decoded, charset);
} catch (UnsupportedEncodingException uee) {
throw XProcException.stepError(10, uee);
}
return content;
}

private void doFile(String href, String base) {

0 comments on commit f5fdcb6

Please sign in to comment.
You can’t perform that action at this time.