Uploading a file with cURL
About
My tcpdump skills are still fresh. Let's go inspect some traffic when we
upload a file with cURL.
Experiment
Let's host a TCP server with netcat:
nc -l 1234And then let's create a foobar file that contains some new lines to see how cURL will handle it .
echo hello > foobar
echo world >> foobar
echo . >> foobar
The --data family of flags use application/x-www-form-urlencoded as
Content-Type.
The --form family of flags use multipart/form-data as the Content-Type.
–data
Let's send the data over to our server using the --data flag.
curl --data @foobar http://localhost:1234
The client will be waiting from an http response from the server, so just type
HTTP/1.1 200 OK in netcat, and submit it entering a newline followed with the
EOF character (Control-D on Linux/MacOS).
This is the HTTP request that will be sent to the server:
POST / HTTP/1.1
Host: localhost:1234
User-Agent: curl/8.7.1
Accept: */*
Content-Length: 11
Content-Type: application/x-www-form-urlencoded
helloworld.The carriage returns and newlines are stripped out because the @ character performs special interpretation.
–data-urlencode
If we wanted to include the new lines, then we will need to use
--data-urlencode instead to escape the newlines:
POST / HTTP/1.1
Host: localhost:1234
User-Agent: curl/8.7.1
Accept: */*
Content-Length: 20
Content-Type: application/x-www-form-urlencoded
hello%0Aworld%0A.%0A
There are four more syntaxes for specifying the content. We've already
experimented with the @filename syntax.
Let's see name@filname now: curl --data-urlencode foobar@foobar
http://localhost:1234.
POST / HTTP/1.1
Host: localhost:1234
User-Agent: curl/8.7.1
Accept: */*
Content-Length: 27
Content-Type: application/x-www-form-urlencoded
foobar=hello%0Aworld%0A.%0A
Let's see content now: curl --data-urlencode helloworld
http://localhost:1234.
POST / HTTP/1.1
Host: localhost:1234
User-Agent: curl/8.7.1
Accept: */*
Content-Length: 10
Content-Type: application/x-www-form-urlencoded
helloworld
Let's see =content now: curl --data-urlencode =helloworld
http://localhost:1234.
POST / HTTP/1.1
Host: localhost:1234
User-Agent: curl/8.7.1
Accept: */*
Content-Length: 10
Content-Type: application/x-www-form-urlencoded
helloworld
Let's see name=content now: curl --data-urlencode foobar=helloworld
http://localhost:1234.
POST / HTTP/1.1
Host: localhost:1234
User-Agent: curl/8.7.1
Accept: */*
Content-Length: 17
Content-Type: application/x-www-form-urlencoded
foobar=helloworld–form-string
Now let's experiment requests that use multipart/form-data as Content-Type.
The --form-string allows us to send strings as values.
curl --form-string foobar=helloworld http://localhost:1234POST / HTTP/1.1
Host: localhost:1234
User-Agent: curl/8.7.1
Accept: */*
Content-Length: 163
Content-Type: multipart/form-data; boundary=------------------------rq1DxrKk0eSy5XPZUjENER
--------------------------rq1DxrKk0eSy5XPZUjENER
Content-Disposition: form-data; name="foobar"
helloworld
--------------------------rq1DxrKk0eSy5XPZUjENER--–form
The --form flag adds meaning to the @ and < when it prefixes the file.
The @ sign tells cURL to consider the file as a binary and includes the
filename in the Content-Type field line.
curl --form foo=@foobar http://localhost:1234POST / HTTP/1.1
Host: localhost:1234
User-Agent: curl/8.7.1
Accept: */*
Content-Length: 223
Content-Type: multipart/form-data; boundary=------------------------T6bqePJBQp4FoNvv1De6Lw
--------------------------T6bqePJBQp4FoNvv1De6Lw
Content-Disposition: form-data; name="foo"; filename="foobar"
Content-Type: application/octet-stream
hello
world
.
--------------------------T6bqePJBQp4FoNvv1De6Lw--
The < sign tells curl to consider the file as a text and retrieves its
content. You will see that there's no filename in the Content-Type field
line.
Hint: Be sure to to quote the <name=content> to escape the < sign from
the shell.
curl --form "foo=<foobar" http://localhost:1234POST / HTTP/1.1
Host: localhost:1234
User-Agent: curl/8.7.1
Accept: */*
Content-Length: 164
Content-Type: multipart/form-data; boundary=------------------------RxN8nUhV7pI3nC0pLRgjSi
--------------------------RxN8nUhV7pI3nC0pLRgjSi
Content-Disposition: form-data; name="foo"
hello
world
.
--------------------------RxN8nUhV7pI3nC0pLRgjSi--