Perform cURL POST Request [Practical Examples]


Tips and Tricks

Basic Understanding of HTTP Methods

Before we jump into curl POST Method explanation, let us understand some basics.

HTTP (Hypertext Transfer Protocol) is the foundation of data communication on the internet. One of the core features of HTTP is its use of methods (sometimes called "verbs") to indicate the desired action to be taken on a given resource.

  1. GET: This method retrieves information from the server. When you enter a URL into your web browser's address bar and hit Enter, you're typically sending a GET request. It requests data from a specified resource and should have no other effect on the data.
  2. POST: This method submits data to a server to be processed. It is used when submitting form data or uploading a file. Unlike GET requests, POST requests do not append data to the URL; instead, they include data in the body of the request.
  3. PUT: This method is used to update an existing resource or create it if it doesn't exist. It provides a block of data (like POST) to a data resource referred to by a URL.
  4. DELETE: As the name suggests, this method deletes a specified resource. It removes the resource identified by a URI.
  5. HEAD: This method is almost identical to GET, but it only requests the headers of the response and not the response body. It can be used to retrieve the metadata about a resource without fetching the actual data.
  6. OPTIONS: This method describes the communication options for the target resource. It is used to describe the ways to communicate for a given URL or the server in general.
  7. PATCH: This method applies partial modifications to a resource. It provides a partial update to a resource, as opposed to the full update approach of PUT.

There are other methods like CONNECT and TRACE, but the ones mentioned above are the most commonly used.

 

Understanding HTTP POST Request Method

The POST method is designed to request that a web server accept and store the data enclosed in the body of the request. It's commonly used when submitting form data or uploading a file.

Here are some of the typical use cases of POST method:

  • Form Submission: Most online forms (like contact forms, registration forms, and login forms) use the POST method to submit form data to the server for processing.
  • File Upload: When you upload a file, whether it's an image, video, or document, the data is typically sent to the server using a POST request.
  • API Interactions: Many API endpoints require data to be sent in the body of the request, typically using POST. For instance, creating a new user record, adding a comment, or sending a message in many web applications often involves a POST request.
  • Secure Data Transfer: Data sent via POST is placed in the body of the request, ensuring that sensitive data isn't visible in the URL or saved in browser history.

Data sent from the browser to the server using the HTTP POST method is stored in the request body, as shown below.

POST /test/demo_form.php HTTP/1.1
Content-Type: application/json
Content-Length: 1024
Host: www.golinuxcloud.com

 

Sending a POST Request with Curl [Syntax]

cURL is a command-line tool used for transferring data with URLs. When making POST requests with cURL, the general structure can be described as:

curl [flags/options] [URL]

Here are the flags and options relevant to POST requests:

-X, --request: Specifies the HTTP method to be used. For a POST request, this would be -X POST.

-d, --data: Sends the specified data in a POST request to the server. The data should be URL-encoded if it's of type application/x-www-form-urlencoded.

curl -X POST -d "key1=value1&key2=value2" http://example.com

--data-raw: Sends unprocessed data directly in the POST request.

curl -X POST --data-raw "raw data here" http://example.com

--data-urlencode: This option is used when the data being sent should be URL encoded.

curl -X POST --data-urlencode "data=value with spaces" http://example.com

-H, --header: Used to send headers in your HTTP request. A common header used with POST requests is Content-Type.

Example (sending JSON data):

curl -X POST -H "Content-Type: application/json" -d '{"key": "value"}' http://example.com

-F, --form: This sends data as multipart/form-data, which is often used for file uploads.

curl -X POST -F "file=@path/to/your/file.txt" http://example.com/upload

-u, --user: This is used for server authentication. If you need to include a username and password with your POST request, use this option.

curl -X POST -u username:password -d "data=value" http://example.com

-b, --cookie: Use this to send cookies with your POST request.

curl -X POST -b "name=value" http://example.com

 

Headers and Data in POST Requests

HTTP headers play an essential role in defining the nature of the request, specifying metadata, controlling caching, and facilitating authentication and redirections, among other tasks. Particularly in POST requests, headers become crucial because they can define the nature of the data being sent.

In a POST request, data is usually sent in the request body. The format of the data and how it should be interpreted is typically indicated using the Content-Type header.

  • Form Data: This is the default way browsers submit forms. The data is URL-encoded and looks something like: key1=value1&key2=value2.
  • JSON Data: With the rise of RESTful APIs, JSON (JavaScript Object Notation) has become a popular choice. The data is structured in key-value pairs, arrays, or nested objects: {"key1": "value1", "key2": "value2"}.

The Content-Type header is pivotal in telling the server what type of data you're sending, so it knows how to interpret it.

  • application/x-www-form-urlencoded: This is the default for web forms. When sending data from a web form, it's encoded as name/value pairs.
  • application/json: Used when sending JSON data.
  • multipart/form-data: Used when submitting forms with binary data or file uploads. The data is split into multiple parts, each with its own content type.

 

Examples performing cURL POST Requests

Setup simple webserver

I am setting up a simple webserver using Python Flask for demonstrating examples in this tutorial. Here is my code:

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/formdata', methods=['POST'])
def form_data():
    data = request.form
    return jsonify(data), 200

@app.route('/jsondata', methods=['POST'])
def json_data():
    data = request.json
    return jsonify(data), 200

@app.route('/upload', methods=['POST'])
def upload_file():
    uploaded_file = request.files['file']
    if uploaded_file.filename != '':
        uploaded_file.save(uploaded_file.filename)
        return f"File {uploaded_file.filename} uploaded successfully!", 200
    else:
        return "No file selected for uploading", 400

if __name__ == '__main__':
    app.run(debug=True)

In this webserver:

  • /formdata endpoint accepts form data.
  • /jsondata endpoint accepts JSON data.
  • /upload endpoint allows file uploads.

 

Let's see how this works in practice using cURL.

 

1. Sending Form Data:

Assuming the server is running locally:

curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "username=JohnDoe&password=secret" http://127.0.0.1:5000/formdata

Response:

{
  "password": "secret",
  "username": "JohnDoe"
}

Instead of providing data directly in the command line using -d, you can have cURL read from a file using the --data-binary flag along with the @ symbol:

curl -X POST --data-binary @datafile.txt http://example.com

 

2. Sending JSON Data:

curl -X POST -H "Content-Type: application/json" -d '{"username": "JohnDoe", "password": "secret"}' http://127.0.0.1:5000/jsondata

Response:

{
  "password": "secret",
  "username": "JohnDoe"
}

 

3. File Upload:

Suppose you have a file named test.txt in the current directory and you want to upload it:

curl -X POST -H "Content-Type: multipart/form-data" -F "file=@test.txt" http://127.0.0.1:5000/upload

Response:

File test.txt uploaded successfully!

If your webserver supports multipart file uploads, to send files using a POST request, similar to how a web form might allow for file uploads, you can use the -F or --form flag:

curl -F "file=@path/to/file.jpg" http://example.com/upload

If you need to specify the content type of the file:

curl -F "file=@path/to/file.jpg;type=image/jpeg" http://example.com/upload

 

4. Authentication and Authorization:

Many modern web services require users to authenticate. This can involve sending a username and password to obtain a token, which can then be used in subsequent requests.

Let me enhance my webserver to handle endpoint /authenticate

@app.route('/authenticate', methods=['POST'])
def authenticate():
    data = request.json
    username = data.get('username')
    password = data.get('password')

    # Mock authentication check
    if username == "JohnDoe" and password == "secret":
        # In real-world scenarios, you'd generate a secure token here.
        return jsonify({"token": "some_secure_token"}), 200
    return jsonify({"error": "Invalid credentials"}), 401

The client sends a POST request with their username and password, and in return, they receive a JSON Web Token (JWT) or another form of token.

curl -X POST -H "Content-Type: application/json" -d '{"username": "JohnDoe", "password": "secret"}' http://127.0.0.1:5000/authenticate

Response:

{
  "token": "some_secure_token"
}

 

5. Complex JSON Payloads:

In modern applications, especially single-page applications (SPAs) and mobile apps, it's common to send complex JSON objects in POST requests.

Let me enhance my webserver to handle endpoint /create-profile

@app.route('/create-profile', methods=['POST'])
def create_profile():
    data = request.json
    name = data.get('name')
    address = data.get('address', {})
    city = address.get('city')
    country = address.get('country')
    
    # Save to database or other operations here...

    return jsonify({"status": "Profile created successfully"}), 200

The client might send a JSON object with various nested fields to create a user profile:

curl -X POST -H "Content-Type: application/json" -d '{"name": "John", "address": {"city": "New York", "country": "USA"}}' http://127.0.0.1:5000/create-profile

Response:

{
  "status": "Profile created successfully"
}

 

6. Batch Requests:

Instead of sending individual requests for each item, clients can send multiple items in a single POST request to reduce the number of requests and improve efficiency.

Let me enhance my webserver to handle endpoint /batch-upload

@app.route('/batch-upload', methods=['POST'])
def batch_upload():
    items = request.json.get('items', [])
    
    for item in items:
        # Process each item...
        pass

    return jsonify({"status": f"{len(items)} items processed"}), 200

The client might send a list of items to be processed:

curl -X POST -H "Content-Type: application/json" -d '{"items": ["item1", "item2", "item3"]}' http://127.0.0.1:5000/batch-upload

Response:

{
  "status": "3 items processed"
}

 

7. Webhooks:

Services often provide webhooks to notify about events. For instance, a payment gateway might send a POST request to your provided URL every time a transaction occurs.

Let me enhance my webserver to handle endpoint /payment-webhook

@app.route('/payment-webhook', methods=['POST'])
def payment_webhook():
    data = request.json
    transaction_id = data.get('transaction_id')
    status = data.get('status')
    
    # Log the transaction, update database, etc.

    return jsonify({"status": "Received"}), 200

Your server would process incoming notifications about payments:

curl -X POST -H "Content-Type: application/json" -d '{"transaction_id": "12345", "status": "success"}' http://127.0.0.1:5000/payment-webhook

Response:

{
  "status": "Received"
}

 

8. Content Negotiation:

Clients can use POST requests to ask servers to return data in a specific format by using the Accept header.

Let me enhance my webserver to handle data in XML instead of JSON:

@app.route('/data', methods=['POST'])
def get_data():
    if request.headers.get('Accept') == 'application/xml':
        # Return data as XML...
        pass
    # Default to JSON...
    return jsonify({"data": "sample_data"}), 200

In this case, the client specifies it wants XML data.

curl -X POST -H "Accept: application/xml" http://127.0.0.1:5000/data

Response:

{
  "data": "sample_data"
}

 

9. Data Transformation:

A client can send data in one format, and the server might transform it into another format.

Let me enhance my webserver to handle endpoint /convert-to-uppercase

@app.route('/convert-to-uppercase', methods=['POST'])
def convert_to_uppercase():
    data = request.json
    text = data.get('text', '').upper()
    return jsonify({"converted_text": text}), 200

Transforming received text to uppercase:

curl -X POST -H "Content-Type: application/json" -d '{"text": "hello"}' http://127.0.0.1:5000/convert-to-uppercase

Response:

{
  "converted_text": "HELLO"
}

 

10. Expect Header:

By default, cURL adds an "Expect: 100-continue" header for POST requests larger than a certain size. This tells the server to confirm it's willing to receive the data before cURL sends it. However, in some cases, you might want to avoid this behavior. You can disable this header with:

curl -X POST -d "data=value" -H "Expect:" http://example.com

Let me add another endpoint /data-endpoint for this example:

@app.route('/data-endpoint', methods=['POST'])
def data_endpoint():
    content = request.data.decode('utf-8')
    return jsonify({"received_data": content})

Example:

curl -X POST -d "data=value" -H "Expect:" http://127.0.0.1:5000/data-endpoint

Response:

{
  "received_data": ""
}

 

11. Chunked Transfer:

You can send POST data using chunked transfer encoding by setting the Transfer-Encoding header:

curl -X POST -d "data=value" -H "Transfer-Encoding: chunked" http://127.0.0.1:5000/data-endpoint

 

12. URL-Encoded POST Data:

If you don't specify the Content-Type header as "application/x-www-form-urlencoded" (which is default for -d), but still need your data to be URL-encoded, you can use the --data-urlencode option:

Update webserver to support endpoint /url-encoded-data

@app.route('/url-encoded-data', methods=['POST'])
def url_encoded_data():
    content = request.form['data']
    return jsonify({"received_data": content})

cURL command:

curl -X POST --data-urlencode "data=value with spaces" http://127.0.0.1:5000/url-encoded-data

Response:

{
  "received_data": "value with spaces"
}

 

Conclusion

cURL, a robust command-line tool for working with URLs, is invaluable for developers, testers, and even system administrators. Its versatility in making various types of requests, especially POST requests, makes it a crucial tool in the world of web development and testing.

Recapping the significance of understanding cURL POST requests:

  • Deep Insight into HTTP Communication: Through cURL's POST requests, one gains an in-depth view of how data is transmitted across the web. This insight is essential for debugging, API interaction, and understanding the intricacies of server-client communication.
  • Versatility: With the knowledge of POST requests using cURL, users can simulate forms submissions, file uploads, and more. They can send data in various formats, from URL-encoded form data to JSON payloads, and even binary data.
  • Advanced Interactions: Beyond simple data submissions, cURL offers advanced features like multipart file uploads, chunked transfers, and more. Mastery over cURL's POST functionalities can simplify interactions with complex web services.
  • Security Implications: By understanding POST requests, users can also grasp the security implications related to data transmission. This knowledge aids in developing more secure applications and identifying potential vulnerabilities.
  • Efficient Testing and Debugging: For developers and testers, the ability to craft specific POST requests helps in replicating bugs, testing endpoints, and ensuring robustness in applications.
  • A Step Towards Automation: Knowledge of making POST requests via cURL sets the foundation for automation. Whether it's for automated testing, data submission, or server interactions, cURL is a powerful ally.

For more information about Curl, you can check out the official documentation page. Do you have any queries or comments about this topic? If yes, please feel free to hit the comments below.

 

Deepak Prasad

Deepak Prasad

He is the founder of GoLinuxCloud and brings over a decade of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels in various domains, from development to DevOps, Networking, and Security, ensuring robust and efficient solutions for diverse projects. You can connect with him on his LinkedIn profile.

Can't find what you're searching for? Let us assist you.

Enter your query below, and we'll provide instant results tailored to your needs.

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can send mail to admin@golinuxcloud.com

Thank You for your support!!

Leave a Comment