The goal is for a Node.js / hapi API server to respond to a browser's AJAX request with two things:
These are two separate items only because binary data cannot easily be stored in JSON. Otherwise, this would be a single resource. Nevertheless, it is preferable that they be sent in a single response.
We upload these in a single request with multipart/form-data
. In that case, browsers provide a built-in mechanism to serialize the body and most server-side frameworks know how to parse it. But how does one do the same for a response, in the opposite direction? Namely, how should a server serialize the body to transmit it to a client?
From what I can tell, multipart/mixed
could be a useful content type. But there is very little talk of this. Most people seem to resort to providing two separate GET
routes, one for each piece. I dislike that because it opens you up to race conditions, amongst other things. What am I missing?
See also my question in hapijs/discuss#563.
a multipart request is a REST request containing several packed REST requests inside its entity. a multipart response is a REST response containing several packed REST responses inside its entity.
An HTTP multipart request is an HTTP request that HTTP clients construct to send files and data over to an HTTP Server. It is commonly used by browsers and HTTP clients to upload files to the server.
Multipart/form-data is a special type of body that each value is sent as a block of data. Each part is separated by the defined delimiter (a.k.a boundary). The key value is described in the Content-Disposition header of each part. By using multipart/form-data, you can: Send a file or multiple files to your server.
Multipart requests combine one or more sets of data into a single body, separated by boundaries. You typically use these requests for file uploads and for transferring data of several types in a single request (for example, a file along with a JSON object).
You can serve the response as multipart/form-data
and use Response.formData()
to read response at client
fetch("/path/to/server", {method:"POST", body:formData}) .then(response => response.formData()) .then(fd => { for (let [key, prop] of fd) { console.log(key, prop) } })
let fd = new FormData(); fd.append("json", JSON.stringify({ file: "image" })); fetch("data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQACgABACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkEAAoAAgAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkEAAoAAwAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkEAAoABAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQACgAFACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQACgAGACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAAKAAcALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==") .then(response => response.blob()) .then(blob => { fd.append("file", blob); new Response(fd) .formData() .then(formData => { for (let [key, data] of formData) { console.log(key, data) } }) })
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With