7

Without GenerateHTTPResponse the import works as expected.

ba = ExportByteArray[Plot[x, {x, 0, 1}], "PNG"];
ImportByteArray[ba]

Mathematica graphics

However, when I use GenerateHTTPResponse

hr = GenerateHTTPResponse[ExportByteArray[Plot[x, {x, 0, 1}], "PNG"]];

then none of the following resolve to the image.

ImportByteArray@hr["BodyByteArray"]
ImportByteArray@*ByteArray@hr["BodyBytes"]
ImportByteArray[hr["Body"]]

What am I missing?

Note that this is for a web api and something other than Wolfram Language will be importing the ByteArray from the response. So I need to transport the bytes in the response such that any language can get the bytes and reconstruct the PNG image. I thought as a starting point that WL would be able to consume its own bytes within WL but I am obviously missing something.

Edmund
  • 42,267
  • 3
  • 51
  • 143

1 Answers1

9

One needs to be careful and construct the HTTPResponse properly before we ask GenerateHTTPRespone to produce the final thing so that it can be consumed by any HTTP client outside of WL world.

The following explicit MIME specification will solve the above problem.

res = HTTPResponse[
   ExportString[Plot[x, {x, 0, 1}], "PNG"],
   <|"ContentType" -> "image/png"|>
   ];
hr = GenerateHTTPResponse[res];
ImportByteArray@hr["BodyByteArray"]

enter image description here

Also as expected the following two ways will also produce the above image.

ImportString[hr["Body"], "PNG"]
ImportByteArray@ByteArray@hr["BodyBytes"]

Reason

The problem OP faced is just due to mime type getting messed up.

Note how the MIME type gets spoiled when we do:

GenerateHTTPResponse[
  ExportByteArray[Plot[x, {x, 0, 1}], "PNG"]]["ContentType"]

"text/plain;charset=utf-8"

WL will not deduce the correct content type "image/png" from the above code.

However the above behavior is probably natural as a byte array is just a collection of byte and possess no extra metadata about it's content type. Until one supply such metadata to a processor of the given byte array (e.g the process of creating a HTTP response from the given byte array), it is forced to predict the content type before it can process. In our case GenerateHTTPResponse predicts the content type to default "text/plain;charset=utf-8" and things gets messed up.

Using ExportForm

If one wants to skip explicitly forming the HTTPResponse there is a shorter way possible as pointed by @Kuba here. It uses the ExportForm function that can successfully infer the content type and form the HTTP response.

expr = Plot[x, {x, 0, 1}]]
GenerateHTTPResponse @ ExportForm[expr, "PNG"]
PlatoManiac
  • 14,723
  • 2
  • 42
  • 74