Binary data

Communication presents the values shared by Pages, Actions and WebSocket. This page explains how GOX transfers binary content without converting it to text or JSON.

The binary data represent bytes without file name. The basic and structured values are explained separately in Values. When the name, type MIME or content identity are relevant, use gox.File.


Equivalence

AddressOriginDestination
JavaScript to GoArrayBuffer, view, Blob[]byte
Go to Action[]byte, io.ReaderReadableStream
Go to WebSocket[]byteUint8Array
Go to Page[]byte, io.ReaderHTTP response body

A view includes types like Uint8Array, Uint16Array and DataView.


Send data from JavaScript

Actions and WebSocket can receive a ArrayBuffer, a view or a Blob how []byte.

js
const data = new Uint8Array([0, 127, 128, 255])
const [result, err] = await Actions.StoreBinary(data)
gox
func StoreBinary(data []byte) gox.Action {
    ...
}

A full buffer may also be sent:

js
socket.emit("binary", data.buffer)
gox
socket.On("binary", func(data []byte) {
    ...
})

GOX retains the bytes. A view sends the visible content of that view, not a textual representation of its values.


Receive data via WebSocket

One []byte sent from Go comes as Uint8Array.

gox
socket.Emit("binary", []byte{0, 127, 128, 255})
js
socket.on("binary", data => {
    console.log(data instanceof Uint8Array) // true
})

WebSocket delivers the full value within the event. It does not expose it as stream.


Responses from Actions

An Action that Returns []byte delivery a ReadableStream to the client.

gox
func Export() gox.Action {
    return []byte{0, 127, 128, 255}
}
js
const [stream, err] = await Actions.Export()
const reader = stream.getReader()

You can also return a value compatible with io.Reader:

gox
func StreamLog() gox.Action {
    file, err := os.Open("server.log")
    if err != nil {
        return err
    }
    return file
}

The client receives the body of the response as ReadableStream and can consume it progressively.


Page responses

A Page can use []byte as a binary body:

gox
func GET() gox.Page {
    return []byte{0, 127, 128, 255}
}

You can also return a io.Reader to write the response progressively:

gox
func GET() gox.Page {
    reader, err := os.Open("data.bin")
    if err != nil {
        return err
    }
    return reader
}

The browser access the content by using the usual HTTP APIs, such as fetch() and response.body.

Configure Content-Type by ctx.Response.Headers when the type of content is known. Response Headers to know how to modify the headers before starting the response.


Binary and File

UseWhen you need to
[]byteTransfer bytes without file identity
io.ReaderProduce content progressively
gox.FileKeep name, type MIME and size

One Blob sent from JavaScript can become []bytebut does not provide by itself the complete identity that GOX requires to build a gox.File.

See Files when the content represents a downloadable file or uploaded by the user.


Streams

Streams are part of the HTTP responses of Pages and Actions. WebSocket transmits complete messages and does not convert io.Reader in a ReadableStream remoto.

One ReadableStream must be consumed or cancelled from JavaScript. The result cannot be reused after your body has been consumed.


Errors

The transfer fails when:

  • The argument is not a compatible binary source.
  • Go expects a different type of []byte.
  • The stream makes a mistake during reading.
  • The response has already started before setting up its headers.

In Actions, the problem is delivered by the error result. In WebSocket, it is communicated by the event error described as WebSocket eventsIn Pages, it is given as an HTTP response error.


Best practices

  • Use Uint8Array when you work directly with bytes in JavaScript.
  • Use []byte for small binary content or fully available.
  • Use io.Reader for large or progressive content.
  • Configure the MIME type before writing an HTTP response.
  • Use gox.File where the name of the content is significant.
  • Do not convert binary data to Base64 unless another protocol requires it.
  • Limit the size accepted according to the application needs.

See also

Next step

Continue with Files to keep the name, type MIME and the size of the transferred content.

Files