Search code examples
bashcurlmultipartform-data

Adapt multipart/form-data request to curl with image and json in the same request


I need to rewrite this curl request extracted from the browser to execute it from bash, it is a multipart/form-data that combines the upload of an image together with a json in the same request, I have carried out several tests substituting the raw data for two -F but the server responds with error. What would be the correct way? I also fail to understand the key that is next to WebKitFormBoundary is a value that seems random, is it just a separator? can i use anything?

I have removed the headers that I considered irrelevant

curl 'https://localhost' \
  -H 'Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryXXXXXXXXXXXXXXXX' 
  -H 'Accept: */*' \
  --data-raw $'------WebKitFormBoundaryXXXXXXXXXXXXXXXX\r\nContent-Disposition: form-data; name="image"; filename="image.jpg"\r\nContent-Type: image/jpeg\r\n\r\n\r\n------WebKitFormBoundaryXXXXXXXXXXXXXXXX\r\nContent-Disposition: form-data; name="item"; filename="blob"\r\nContent-Type: application/json\r\n\r\n{"item1":"xxxx","item2":"yyyy"}\r\n------WebKitFormBoundaryXXXXXXXXXXXXXXXX--\r\n' \

Thanks


Solution

  • I also fail to understand the key that is next to WebKitFormBoundary is a value that seems random, is it just a separator? can i use anything?

    yes and yes and practically speaking yes. it's supposed to be a random-guaranteed-unique string used as separator to signal start and end of forms.. if you know beforehand that none of your uploads contains the string stackoverflow, you could use Content-Type: multipart/form-data; boundary=stackoverflow for example (but this may break if you upload a file actually containing the string stackoverflow !), but you should let curl generate that string automatically, rather than specifying it yourself, curl will auto-generate a string that is practically guaranteed to be unique.

    I have removed the headers that I considered irrelevant

    ... if you guessed wrong, the server may give you an error for missing a required header. assuimg that you didn't make any mistakes in removing irrelevant headers though, i think it's

    curl 'https://localhost'\
      --form "[email protected];type=image/jpeg"\
      --form "item=@blob;type=application/json"
    

    the request generated by that command is roghly:

    POST / HTTP/1.1
    Host: localhost
    User-Agent: curl/7.81.0
    Accept: */*
    Content-Length: 359
    Content-Type: multipart/form-data; boundary=------------------------7d0262831ce8f248
    
    --------------------------7d0262831ce8f248
    Content-Disposition: form-data; name="image"; filename="image.jpg"
    Content-Type: image/jpeg
    
    image.jpg content
    
    --------------------------7d0262831ce8f248
    Content-Disposition: form-data; name="item"; filename="blob"
    Content-Type: application/json
    
    ["json lol"]
    
    --------------------------7d0262831ce8f248--
    

    as you can see above, Accept: */* is curl's default accept-header anyway, so there's no need to specify it, and curl auto-generated the boundary ------------------------7d0262831ce8f248 so there's no need to manually specify a boundary either.