Form Data
The Form represents a collection of FormFields that can be a multipart or URL-encoded form:
final case class Form(formData: Chunk[FormField])
A Form is commonly used in request bodies for handling data from HTML forms and file uploads, although it can also be utilized in response bodies.
Form Fields
A FormField is a field within a Form and consists of a name, content type, type-specific content, and an optional filename.
sealed trait FormField {
def name: String
def contentType: MediaType
def filename: Option[String]
}
There are four types of FormField: Simple FormField, Text FormField, Binary FormField, and StreamingBinary FormField.
Simple FormField
Simple form fields are represented by the Simple case class. They consist of a simple key-value pair containing a name and a value (String). Unlike Binary and Text, they do not contain additional metadata such as content type or filename:
final case class Simple(name: String, value: String) extends FormField {
override val contentType: MediaType = MediaType.text.plain
override val filename: Option[String] = None
}
To create a simple form field, we can use FormField.simpleField constructor:
import zio.http._
val simpleFormField = FormField.simpleField("name", "value")
Instances of FormField.Simple are commonly used for transmitting simple textual data where additional metadata is not required, such as form fields in HTML forms.
Text FormField
Text form fields are represented by the Text case class. They contain textual data (String) along with metadata such as the content type and optionally the filename:
final case class Text(
name: String,
value: String,
contentType: MediaType,
filename: Option[String] = None,
) extends FormField
To create a text form field, we can use FormField.textField constructor:
import zio.http._
val textFormField1 = FormField.textField("name", "value")
val textFormField2 = FormField.textField("name", "value", MediaType.text.plain)
Instances of FormField.Text are used for transmitting simple textual data and textual files, such as text files, HTML files, and so on.
Binary FormField
Binary form fields are represented by the FormField.Binary case class. They contain binary data (Chunk[Byte]), along with metadata such as the content type (MediaType) and optionally the Content-Transfer-Encoding header field and filename:
final case class Binary(
name: String,
data: Chunk[Byte],
contentType: MediaType,
transferEncoding: Option[ContentTransferEncoding] = None,
filename: Option[String] = None,
) extends FormField
To create a binary form field, we can use FormField.binaryField constructor:
import zio._
import zio.http._
import zio.http.Header._
val image = Chunk.fromArray(???)
val binaryFormField = FormField.binaryField(
name = "profile pic",
data = image,
mediaType = MediaType.image.jpeg,
transferEncoding = Some(ContentTransferEncoding.Binary),
filename = Some("profile.jpg")
)
The data is not encoded in any way relative to the provided transferEncoding. It is the responsibility of the user to encode the data accordingly.
This form field is suitable for transmitting files or other binary data through HTTP requests.
The data is typically encoded in a way that can be transmitted as text (e.g., Base64 encoding) and decoded on the receiving end. The transfer encoding can be one of the following: SevenBit, EightBit, Binary, QuotedPrintable, Base64, and XToken.
Creating a Form
The Form's companion object offers several convenient methods for constructing form data, whether from individual form fields, key-value pairs, multipart bytes, query parameters, or URL-encoded data. We'll cover each of these methods and provide examples to illustrate their usage.