2

I have the following cURL command:

// original curl
curl https://example.com \
  -F "id=id" \
  -F "secret=secret"

which I thought can be represented with this fetch expression:

// fetch
const body = new FormData();
body.append('id', 'id');
body.append('secret', 'secret');

return fetch('https://example.com', {
  method: 'POST',
  mode: 'no-cors',
  headers: {
    'Content-Type': 'multipart/form-data',
  },
  body,
})

And then, copying the fetch request as cURL generates the following command:

// generated curl
curl 'https://example.com' \
  -H 'content-type: multipart/form-data' \
  --data-raw $'------WebKitFormBoundaryH2Ve4S1AUbboJ21W\r\nContent-Disposition: form-data; name="id"\r\n\r\nid\r\n------WebKitFormBoundaryH2Ve4S1AUbboJ21W\r\nContent-Disposition: form-data; name="secret"\r\n\r\nsecret\r\n------WebKitFormBoundaryH2Ve4S1AUbboJ21W--\r\n' \
  --compressed

To my surprise, when using real data instead of placeholder data for the endpoint and form values, the original curl request works, but the generated curl request does not (nor does the fetch version).

Is there something obvious that I'm missing? What is the difference between the original cURL command and the fetch expression / generated cURL command?

Tanaike
  • 181,128
  • 11
  • 97
  • 165
Raphael Rafatpanah
  • 19,082
  • 25
  • 92
  • 158

1 Answers1

2

I believe your goal as follows.

  • You want to convert the following curl command to fetch of Javascript.

      curl https://example.com \
        -F "id=id" \
        -F "secret=secret"
    

In this case, how about the following script? When FormData is used, Content-Type is automatically added to the request header by including the boundary.

Sample script:

const body = new FormData();
body.append('id', 'id');
body.append('secret', 'secret');
return fetch('https://example.com', {
  method: 'POST',
  // mode: 'no-cors' // I thought that this might not be required to be used. But please check this for your actual situation.
  body
});

Reference:

Added:

About your following comment,

are you aware of a way to convert the original cURL command into something that doesn't use the -F option?

In this case, how about manually creating the request body as follows?

curl -H 'Content-Type: multipart/form-data; boundary=boundaryboundary' \
  -d $'--boundaryboundary\r\nContent-Disposition: form-data; name="id"\r\n\r\nid\r\n--boundaryboundary\r\nContent-Disposition: form-data; name="secret"\r\n\r\nsecret\r\n--boundaryboundary--\r\n' \
  'https://example.com'
Tanaike
  • 181,128
  • 11
  • 97
  • 165
  • You're right about the goal, and omitting the `Content-Type` header is a good idea, but unfortunately the fetch query is still different than the `curl` command. Note, I do need to use the `mode: 'no-cors'` in my case – Raphael Rafatpanah Jun 04 '21 at 00:31
  • In my case, in the fetch example, `response.ok` is always false. But when using the original `curl` command, I get a valid JSON response – Raphael Rafatpanah Jun 04 '21 at 00:35
  • @Raphael Rafatpanah Thank you for replying. I apologize for the inconvenience. About `mode: 'no-cors'`, I understood it. About `but unfortunately the fetch query is still different than the curl command.`, unfortunately, I cannot understand about it. I apologize for this. So can I ask you about the detail of `still different`? When I tested above modified script, I could confirm that it is the same with the curl. So I would like to confirm your current situation. As a test, for example, for above modified script, when you didn't use `mode: 'no-cors'`, what result will you obtain? – Tanaike Jun 04 '21 at 00:41
  • Without `mode: 'no-cors'` the browser stop the request early and the server is never hit (since there is a CORS error). What's different: with the original cURL command, the server returns a 200. Using fetch, the server returns 500 and I'm not sure why, although I guess there may be something specific to the server I'm requesting that is causing this behavior – Raphael Rafatpanah Jun 04 '21 at 00:47
  • It is helpful to know that there _shouldn't_ be any obvious differences, however, so +1 – Raphael Rafatpanah Jun 04 '21 at 00:48
  • Lastly, are you aware of a way to convert the original cURL command into something that doesn't use the `-F` option? – Raphael Rafatpanah Jun 04 '21 at 00:52
  • 1
    @Raphael Rafatpanah Thank you for replying. From your replying, I could understand about your situation. When I checked your curl command and the modified Javascript again, I confirmed that both requests are the same. So, I would like to confirm whether there is other case. About `convert the original cURL command into something that doesn't use the -F option`, in this case, I think that the request body can be manually created. For this, I added the sample curl command in my answer. – Tanaike Jun 04 '21 at 00:59
  • 1
    I think the difference was that `mode: 'no-cors'` causes `response.status` to always be `0`. [source](https://stackoverflow.com/a/40182952/1911755) – Raphael Rafatpanah Jun 04 '21 at 01:20