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
| Address | Origin | Destination |
|---|---|---|
| JavaScript to Go | ArrayBuffer, view, Blob | []byte |
| Go to Action | []byte, io.Reader | ReadableStream |
| Go to WebSocket | []byte | Uint8Array |
| Go to Page | []byte, io.Reader | HTTP 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.
const data = new Uint8Array([0, 127, 128, 255])
const [result, err] = await Actions.StoreBinary(data) func StoreBinary(data []byte) gox.Action {
...
} A full buffer may also be sent:
socket.emit("binary", data.buffer) 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.
socket.Emit("binary", []byte{0, 127, 128, 255}) 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.
func Export() gox.Action {
return []byte{0, 127, 128, 255}
} const [stream, err] = await Actions.Export()
const reader = stream.getReader() You can also return a value compatible with io.Reader:
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:
func GET() gox.Page {
return []byte{0, 127, 128, 255}
} You can also return a io.Reader to write the response progressively:
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
| Use | When you need to |
|---|---|
[]byte | Transfer bytes without file identity |
io.Reader | Produce content progressively |
gox.File | Keep 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
Uint8Arraywhen you work directly with bytes in JavaScript. - Use
[]bytefor small binary content or fully available. - Use
io.Readerfor large or progressive content. - Configure the MIME type before writing an HTTP response.
- Use
gox.Filewhere 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.