diff --git a/wizard-server/src/main/java/org/cobbzilla/wizard/stream/DataUrlSendableResource.java b/wizard-server/src/main/java/org/cobbzilla/wizard/stream/DataUrlSendableResource.java index d5c4a4a..241cb65 100644 --- a/wizard-server/src/main/java/org/cobbzilla/wizard/stream/DataUrlSendableResource.java +++ b/wizard-server/src/main/java/org/cobbzilla/wizard/stream/DataUrlSendableResource.java @@ -2,11 +2,14 @@ package org.cobbzilla.wizard.stream; public class DataUrlSendableResource extends SendableResource { - public DataUrlSendableResource(String name, String dataUrl) { - super(new DataUrlStreamingOutput(dataUrl)); + public DataUrlSendableResource(String name, String dataUrl) { this(name, dataUrl, false); } + + public DataUrlSendableResource(String name, String dataUrl, boolean base64) { + super(new DataUrlStreamingOutput(dataUrl, base64)); final DataUrlStreamingOutput out = (DataUrlStreamingOutput) getOut(); setName(name); setContentType(out.getContentType()); + setContentLength(out.getContentLength()); } } diff --git a/wizard-server/src/main/java/org/cobbzilla/wizard/stream/DataUrlStreamingOutput.java b/wizard-server/src/main/java/org/cobbzilla/wizard/stream/DataUrlStreamingOutput.java index 0526baa..2aecda4 100644 --- a/wizard-server/src/main/java/org/cobbzilla/wizard/stream/DataUrlStreamingOutput.java +++ b/wizard-server/src/main/java/org/cobbzilla/wizard/stream/DataUrlStreamingOutput.java @@ -3,6 +3,7 @@ package org.cobbzilla.wizard.stream; import lombok.Getter; import org.apache.commons.codec.binary.Base64InputStream; import org.apache.commons.io.IOUtils; +import org.cobbzilla.util.string.Base64; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.StreamingOutput; @@ -12,6 +13,7 @@ import java.io.InputStream; import java.io.OutputStream; import static org.cobbzilla.util.daemon.ZillaRuntime.die; +import static org.cobbzilla.util.http.HttpContentTypes.TEXT_PLAIN; import static org.cobbzilla.util.string.StringUtil.ellipsis; public class DataUrlStreamingOutput implements StreamingOutput { @@ -19,10 +21,20 @@ public class DataUrlStreamingOutput implements StreamingOutput { public static final String DATA_URL_PREFIX = "data:"; @Getter private final String contentType; - private final boolean base64; + @Getter private final Long contentLength; private final InputStream data; - public DataUrlStreamingOutput(String dataUrl) { + public static String dataUrl (String contentType, boolean base64, String data) { + return DATA_URL_PREFIX + contentType + (base64 ? ";base64" : "") + "," + data; + } + + public static byte[] dataUrlBytes (String contentType, boolean base64, String data) { + return dataUrl(contentType, base64, data).getBytes(); + } + + public DataUrlStreamingOutput(String dataUrl) { this(dataUrl, false); } + + public DataUrlStreamingOutput(String dataUrl, boolean base64) { if (!dataUrl.startsWith(DATA_URL_PREFIX)) die("DataUrlStreamingOutput: url does not start with 'data:' : "+ ellipsis(dataUrl, 50)); final int commaPos = dataUrl.indexOf(","); @@ -31,15 +43,33 @@ public class DataUrlStreamingOutput implements StreamingOutput { final String mediaSpecifier = dataUrl.substring(DATA_URL_PREFIX.length(), commaPos); final int b64pos = mediaSpecifier.indexOf(";base64"); + final byte[] urlBytes = dataUrl.getBytes(); final byte[] dataBytes = dataUrl.substring(commaPos).getBytes(); if (b64pos == -1) { - contentType = mediaSpecifier; - base64 = false; - data = new ByteArrayInputStream(dataBytes); + if (base64) { + // data url was not base64, but base64 was requested -- encode and send + final byte[] bytes = dataUrlBytes(mediaSpecifier, true, Base64.encodeBytes(dataBytes)); + data = new ByteArrayInputStream(bytes); + contentType = TEXT_PLAIN; + contentLength = (long) bytes.length; + } else { + // data url was not base64, and base64 was not requested -- send as-is + data = new ByteArrayInputStream(dataBytes); + contentType = mediaSpecifier; + contentLength = (long) dataBytes.length; + } } else { - contentType = mediaSpecifier.substring(0, b64pos); - base64 = true; - data = new Base64InputStream(new ByteArrayInputStream(dataBytes), false); + if (base64) { + // data url was base64, and base64 was requested -- send as-is + data = new ByteArrayInputStream(urlBytes); + contentType = TEXT_PLAIN; + contentLength = (long) urlBytes.length; + } else { + // data url was base64, and base64 was not requested -- decode and send + data = new Base64InputStream(new ByteArrayInputStream(dataBytes), false); + contentType = mediaSpecifier.substring(0, b64pos); + contentLength = (long) dataBytes.length; + } } } diff --git a/wizard-server/src/main/java/org/cobbzilla/wizard/stream/UrlSendableResource.java b/wizard-server/src/main/java/org/cobbzilla/wizard/stream/UrlSendableResource.java index bded51c..1283e43 100644 --- a/wizard-server/src/main/java/org/cobbzilla/wizard/stream/UrlSendableResource.java +++ b/wizard-server/src/main/java/org/cobbzilla/wizard/stream/UrlSendableResource.java @@ -2,19 +2,22 @@ package org.cobbzilla.wizard.stream; import org.cobbzilla.util.collection.NameAndValue; +import static org.cobbzilla.util.http.HttpContentTypes.TEXT_PLAIN; import static org.cobbzilla.util.http.URIUtil.getPath; import static org.cobbzilla.util.io.FileUtil.basename; public class UrlSendableResource extends SendableResource { - public UrlSendableResource(String url) { - super(new UrlStreamingOutput(url)); + public UrlSendableResource(String url) { this(url, false); } + + public UrlSendableResource(String url, boolean base64) { + super(new UrlStreamingOutput(url, base64)); final UrlStreamingOutput urlOut = (UrlStreamingOutput) getOut(); setStatus(urlOut.getResponse().getStatus()); setHeaders(urlOut.getResponse().getHeaders().toArray(NameAndValue.EMPTY_ARRAY)); setName(basename(getPath(url))); - setContentLength(urlOut.getResponse().getContentLength()); - setContentType(urlOut.getResponse().getContentType()); + setContentLength(urlOut.getContentLength()); + setContentType(base64 ? TEXT_PLAIN : urlOut.getResponse().getContentType()); } } diff --git a/wizard-server/src/main/java/org/cobbzilla/wizard/stream/UrlStreamingOutput.java b/wizard-server/src/main/java/org/cobbzilla/wizard/stream/UrlStreamingOutput.java index ea3ac78..eb336e4 100644 --- a/wizard-server/src/main/java/org/cobbzilla/wizard/stream/UrlStreamingOutput.java +++ b/wizard-server/src/main/java/org/cobbzilla/wizard/stream/UrlStreamingOutput.java @@ -5,6 +5,7 @@ import org.apache.commons.io.IOUtils; import org.cobbzilla.util.http.HttpRequestBean; import org.cobbzilla.util.http.HttpResponseBean; import org.cobbzilla.util.http.HttpUtil; +import org.cobbzilla.util.string.Base64; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.StreamingOutput; @@ -19,11 +20,22 @@ public class UrlStreamingOutput implements StreamingOutput { @Getter private HttpResponseBean response; private ByteArrayInputStream in; + @Getter private long contentLength; - public UrlStreamingOutput(String url) { + public UrlStreamingOutput(String url) { this(url, false); } + + public UrlStreamingOutput(String url, boolean base64) { try { response = HttpUtil.getResponse(new HttpRequestBean(url)); - in = new ByteArrayInputStream(response.getEntity()); + if (base64) { + final String b64data = Base64.encodeBytes(response.getEntity()); + final byte[] b64bytes = b64data.getBytes(); + this.in = new ByteArrayInputStream(b64bytes); + this.contentLength = b64bytes.length; + } else { + this.in = new ByteArrayInputStream(response.getEntity()); + this.contentLength = response.getEntity().length; + } } catch (IOException e) { die("UrlStreamingOutput: "+shortError(e)); }