I am trying to implement a batch handler that accepts multipart mixed.
My currently somewhat naive implementation looks like the below. Later I will try to aggregate the responses and send a multipart response.
My current issue is that I am not able to parse the body of the individual parts into a new request.
func handleBatchPost(w http.ResponseWriter, r *http.Request) {
// read the multipart body
reader, err := r.MultipartReader()
if err != nil {
http.Error(w, fmt.Sprintf("could not read multipart %v\n", err), http.StatusBadRequest)
}
// read each part
for {
part, err := reader.NextPart()
if err == io.EOF {
break
} else if err != nil {
http.Error(w, fmt.Sprintf("could not read next part %v\n", err), http.StatusBadRequest)
return
}
// check if content type is http
if part.Header.Get("Content-Type") != "application/http" {
http.Error(w, fmt.Sprintf("part has wrong content type: %s\n", part.Header.Get("Content-Type")), http.StatusBadRequest)
return
}
// parse the body of the part into a request
req, err := http.ReadRequest(bufio.NewReader(part))
if err != nil {
http.Error(w, fmt.Sprintf("could not create request: %s\n", err), http.StatusBadRequest)
return
}
// handle the request
router.ServeHTTP(w, req)
}
}
func handleItemPost(w http.ResponseWriter, r *http.Request) {
var item map[string]interface{}
if err := json.NewDecoder(r.Body).Decode(&item); err != nil {
http.Error(w, fmt.Sprintf("could not decode item json: %v\n", err), http.StatusBadRequest)
return
}
w.Write([]byte(`{"success": true}`))
}
I am getting an error response from the server. It seems like ReadRequest
is not reading the body but only the headers (method, url, etc).
could not decode item json: EOF
This is the payload I am sending.
POST /batch HTTP/1.1
Host: localhost:8080
Content-Type: multipart/mixed; boundary=boundary
--boundary
Content-Type: application/http
Content-ID: <item1>
POST /items HTTP/1.1
Content-Type: application/json
{ "name": "batch1", "description": "batch1 description" }
--boundary
Content-Type: application/http
Content-ID: <item2>
POST /items HTTP/1.1
Content-Type: application/json
{ "name": "batch2", "description": "batch2 description" }
--boundary--
I found this pattern on the gmail api docs https://developers.google.com/gmail/api/guides/batch.