///|
/// Represents the body of an HTTP request, which can be read as a stream or buffered in memory.
struct RequestBody {
group : @async.TaskGroup[Unit]
mut state : RequestBodyState
}
///|
priv enum RequestBodyState {
ReadyStream(&@io.Reader)
Unbuffered
Buffered(@async.Task[&@io.Data])
}
///|
fn RequestBody::from_ready_stream(
reader : &@io.Reader,
group~ : @async.TaskGroup[Unit],
) -> RequestBody {
{ group, state: ReadyStream(reader) }
}
///|
async fn RequestBody::data(self : RequestBody) -> &@io.Data {
match self.state {
ReadyStream(reader) => {
let task = self.group.spawn(() => reader.read_all())
self.state = Buffered(task)
task.wait()
}
Unbuffered =>
fail(
"Request body has already been read as a stream, cannot be read again",
)
Buffered(task) => task.wait()
}
}
///|
/// Returns the request body as a stream reader.
/// This can only be called once, and `no_buffer=false` is not supported yet.
pub fn RequestBody::reader(
self : RequestBody,
no_buffer? : Bool = true,
) -> &@io.Reader raise {
if !no_buffer {
fail(
"no_buffer=false is not supported for RequestBody::reader, as buffering is not implemented yet",
)
}
match self.state {
ReadyStream(reader) => {
self.state = Unbuffered
reader
}
Unbuffered =>
fail(
"Request body has already been read as a stream, cannot be read again",
)
Buffered(_task) =>
fail("Request body has already been buffered, cannot be read as a stream")
}
}
///|
/// Reads the full request body as raw bytes.
///
/// This buffers the entire body in memory, so it should only be used for small
/// request bodies or when the content length is known to be reasonable.
pub async fn RequestBody::binary(self : RequestBody) -> Bytes {
self.data().binary()
}
///|
/// Reads the full request body as text.
///
/// This buffers the entire body in memory, so it should only be used for small
/// request bodies or when the content length is known to be reasonable.
pub async fn RequestBody::text(self : RequestBody) -> String {
self.data().text()
}
///|
/// Reads the full request body and parses it as JSON.
///
/// This buffers the entire body in memory, so it should only be used for small
/// request bodies or when the content length is known to be reasonable.
pub async fn RequestBody::json(self : RequestBody) -> Json {
self.data().json()
}