resty icon indicating copy to clipboard operation
resty copied to clipboard

Is there anyway to make multipart formdata has order?

Open Sczlog opened this issue 1 year ago • 6 comments

I am working with graphql-upload and it's processor must accept one field before any other fields, otherwise it will throw an error. I know that map has no order and should has no order, but if there is anyway to make a raw body of multipart and keep its order?

image

Sczlog avatar Jun 21 '23 04:06 Sczlog

Find myself a workaround, use mime/multipart to create body, set raw body and content-type will keep the order.

var bBody bytes.Buffer
writer := multipart.NewWriter(&bBody)

writer.WriteField("firstkey","firstvalue")
writer.WriteField("secondkey","secondvalue")
part, err := writer.CreateFormFile("fieldname", "filename")
if err != nil {
	return nil, err
}
part.Write([]byte("filecontent"))
writer.Close()
request := c.Client.R()
request.SetHeader("Content-Type", writer.FormDataContentType())
request.SetBody(bBody.Bytes())
resp, err := request.Post("endpoint")

Sczlog avatar Jun 21 '23 07:06 Sczlog

@Sczlog Thanks for bringing it up and finding a workaround to move forward. I may think of a way to preserve order.

jeevatkm avatar Sep 17 '23 08:09 jeevatkm

Can we add a new method that can accept a slice instead of map and write it to the body in the same order ?

praem90 avatar Sep 25 '23 04:09 praem90

My rant: Go insists that maps don't/can't have order. But that's an implementation issue based on the fact that these are Hash based maps instead of Tree based maps (which are ordered).

What might be a slightly better solution than a slice (just a consideration) - take a sort function. Then it can be by insertion order or actual sort order.

I don't know what the spec for mime/multipart says, but definitely don't deviate from it.

chb0github avatar Oct 09 '23 16:10 chb0github

@chb0github I hear you! I will have to check the RFC spec for this part.

A possible workaround/approach (as @praem90 mentioned above) is to add a method to accept the slice and process it.

jeevatkm avatar Oct 12 '23 03:10 jeevatkm

I am working with graphql-upload and it's processor must accept one field before any other fields, otherwise it will throw an error. I know that map has no order and should has no order, but if there is anyway to make a raw body of multipart and keep its order?

image

this can help you:

package main

import (
	"log"
	"strings"

	"github.com/gospider007/requests"
)

func main() {
	orderMap := requests.NewOrderMap()
	orderMap.Set("name", "test")
	orderMap.Set("age", 11)
	orderMap.Set("sex", "boy")

	resp, err := requests.Post(nil, "https://httpbin.org/anything", requests.RequestOption{
		Form: orderMap,
	})
	if err != nil {
		log.Panic(err)
	}
	jsonData, err := resp.Json()
	if err != nil {
		log.Panic(err)
	}
	if !strings.HasPrefix(jsonData.Get("headers.Content-Type").String(), "multipart/form-data") {
		log.Panic("json data error")
	}
	if jsonData.Get("form.name").String() != "test" {
		log.Panic("json data error")
	}
}

gospider007 avatar Nov 20 '23 13:11 gospider007