3723

I use Ubuntu and installed cURL on it. I want to test my Spring REST application with cURL. I wrote my POST code at the Java side. However, I want to test it with cURL. I am trying to post a JSON data. Example data is like this:

{"value":"30","type":"Tip 3","targetModule":"Target 3","configurationGroup":null,"name":"Configuration Deneme 3","description":null,"identity":"Configuration Deneme 3","version":0,"systemId":3,"active":true}

I use this command:

curl -i \
    -H "Accept: application/json" \
    -H "X-HTTP-Method-Override: PUT" \
    -X POST -d "value":"30","type":"Tip 3","targetModule":"Target 3","configurationGroup":null,"name":"Configuration Deneme 3","description":null,"identity":"Configuration Deneme 3","version":0,"systemId":3,"active":true \
    http://localhost:8080/xx/xxx/xxxx

It returns this error:

HTTP/1.1 415 Unsupported Media Type
Server: Apache-Coyote/1.1
Content-Type: text/html;charset=utf-8
Content-Length: 1051
Date: Wed, 24 Aug 2011 08:50:17 GMT

The error description is this:

The server refused this request because the request entity is in a format not supported by the requested resource for the requested method ().

Tomcat log: "POST /ui/webapp/conf/clear HTTP/1.1" 415 1051

What is the right format of the cURL command?

This is my Java side PUT code (I have tested GET and DELETE and they work):

@RequestMapping(method = RequestMethod.PUT)
public Configuration updateConfiguration(HttpServletResponse response, @RequestBody Configuration configuration) { //consider @Valid tag
    configuration.setName("PUT worked");
    //todo If error occurs response.sendError(HttpServletResponse.SC_NOT_FOUND);
    return configuration;
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
kamaci
  • 72,915
  • 69
  • 228
  • 366
  • 7
    checkout the [link](http://stackoverflow.com/questions/16909742/spring-3-2-0-web-mvc-rest-api-and-json-2-post-requests-how-to-get-it-right-on/16909986#16909986) for spring 3.2.0 post requests. – AmirHd Jun 05 '13 at 09:41
  • 14
    There is a nice post [Using Curl For Ad Hoc Testing Of RESTful Microservices](http://goinbigdata.com/using-curl-for-ad-hoc-testing-of-restful-microservices/) which covers this with multiple examples. – upitau Aug 28 '16 at 11:03
  • By the way, it's better to minify json data before sending to server. Use [smart json](https://fe-tool.com/en-us/formatter/json) to is a better choice in 2023. – cwtuan Jan 10 '23 at 13:12

31 Answers31

5523

You need to set your content-type to application/json. But -d (or --data) sends the Content-Type application/x-www-form-urlencoded by default, which is not accepted on Spring's side.

Looking at the curl man page, I think you can use -H (or --header):

-H "Content-Type: application/json"

Full example:

curl --header "Content-Type: application/json" \
  --request POST \
  --data '{"username":"xyz","password":"xyz"}' \
  http://localhost:3000/api/login

(-H is short for --header, -d for --data)

Note that -request POST is optional if you use -d, as the -d flag implies a POST request.


On Windows, things are slightly different. See the comment thread.

Benjamin Loison
  • 3,782
  • 4
  • 16
  • 33
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • 1
    @kamaci I don't think you need to remove -d, just use -H in addition. – Sean Patrick Floyd Aug 24 '11 at 09:43
  • 1
    I try that: curl -i -H "Accept: application/json" -H "X-HTTP-Method-Override: PUT" -X POST -d "value":"30","type":"Tip 3","targetModule":"Target 3","configurationGroup":null,"name":"Configuration Deneme 3","description":null,"identity":"Configuration Deneme 3","version":0,"systemId":3,"active":true http://localhost:8080/ui/webapp/conf – kamaci Aug 24 '11 at 09:48
  • 1
    @kamaci OK then I'm afraid I can't help you without having access to your server logs. I currently don't have access to any Spring MVC projects. I'd try to look for the http query path in your log file and continue from there. Perhaps you could append a relevant bit of the log to this question. – Sean Patrick Floyd Aug 24 '11 at 09:59
  • 368
    For windows, single quotes around json did not work and I ended up escaping double quotes. `curl -X POST -H "Content-Type: application/json" -d "{ \"key1\": \"value1\" }" http://localhost:3000/api/method` – hIpPy Sep 11 '13 at 17:34
  • 54
    For me under Windows I needed to escape quotes using quotes in this format ```"{ """key1""": """value1""" }"```. Also this answer: http://stackoverflow.com/questions/18314796/couchdb-curl-windows-command-line-invalid-json – chodorowicz Jan 27 '14 at 11:10
  • 1
    @SeanPatrickFloyd Yeah! It's ludicrous. At such moments I'm considering much more seriously moving to *nix system. – chodorowicz Jan 27 '14 at 20:21
  • 4
    I've had issues with POST requests but solved it by capitalized "Application/json" so if you get a 415 error, check the capitalization. – Ebsan Apr 24 '14 at 18:13
  • 1
    if you use a model on @RequestBody, remember that it doesn't want a costructor – Silvio Troia May 14 '14 at 10:03
  • 1
    It is also possible to pipe the JSON data from `STDIN` by using `-d @-` as the `curl` option – Guss May 26 '14 at 13:58
  • 1
    `contentType` or `Content-Type`? – Frozen Flame Jan 02 '15 at 08:20
  • 1
    @FrozenFlame header names are title case with dashes, see [RFC](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.17). Some frameworks like jquery accept headers in camelCase and translate those internally to Title-Dash, but curl doesn't afaik – Sean Patrick Floyd Jan 02 '15 at 10:46
  • 1
    I had to POST the data without 's around the {}'s. Then it worked. You'd think it'd be one standard wayto do it. – FilBot3 Mar 20 '15 at 00:55
  • 1
    To use mixed single quotation and double quotation you can use git bash or some other third party provided terminal – codersaif Jul 20 '15 at 06:51
  • 1
    Why does the windows version of curl require double-quotes around json data?? It's totally ridiculous – Someone Somewhere Oct 07 '15 at 12:25
  • 3
    @Adam Tuttle Why does your comment have so many upvotes? With curl on ubuntu 14.04, you need `"Content-Type: application/json"`, not just `"application/json"`. This wasted a lot of my time... – ostrokach Oct 18 '15 at 23:30
  • 9
    @ostrokach sorry it wasted your time. syntax worked fine for me on OSX when I posted it (haven't retried). Guess it is/was just a platform difference. I imagine the upvotes are from people that it helped. – Adam Tuttle Nov 01 '15 at 01:23
  • 1
    Can you put a little note that this might not work on windows? Ctrl-F "Windows" below. – Keegan Jay Jan 18 '17 at 07:37
  • 1
    @JayKeegan I added a little note but I'm not going to pollute my post with that strange syntax – Sean Patrick Floyd Jan 18 '17 at 13:11
  • I face even more strange behaviour when calling this curl command by java `Runtime.getRuntime().exec` method, in linux I must remove the double quotes. anybody knows why? – Lei Yang May 17 '18 at 15:07
  • Just like `-d` or `--data` defaults to using `POST`, so does the `--data-urlencode` option. – flow2k Jul 11 '18 at 20:35
  • I was using -H 'Content-Type: application/json;charset=UTF-8' on linux which shell is UTF-8 .., but strangely removing the charset parameter solved my problem as well. – Reginaldo Santos Feb 20 '19 at 20:02
  • 1
    On windows, I managed to single quote the whole parameter, leaving the original json with double quotes, like the "Full example" above: `-d '{"username":"xyz","password":"xyz"}'` – riemannzz Jun 13 '19 at 10:14
  • ```| python -m json.tool``` add this pipe to get json output in readable format – Aslam Shaik Jul 31 '19 at 06:03
  • When I am trying to use the same format in Linux, I am getting "no data provided" error. – Suresh Jun 01 '20 at 14:10
  • Windows cmd prompt: the triple quotes in the JSON was step one for me, but step two was to realize that the API example I was working from used single quotes around the Content-Type. Once I changed everything to double quotes, I was golden. – John Chase Nov 15 '21 at 21:37
  • haven't seen this anywhere, but the only thing that worked for me (powershell) was to say `-d '{\"message\": false}'` – Matthias Dec 02 '22 at 10:38
719

Try to put your data in a file, say body.json and then use

curl -H "Content-Type: application/json" --data @body.json http://localhost:8080/ui/webapp/conf
Typisch
  • 7,207
  • 1
  • 13
  • 2
  • 2
    checkout [the answer](http://stackoverflow.com/a/16909986/2210206) on how use CURL and what does different errors mean. – AmirHd Jun 05 '13 at 11:56
  • 31
    You probably should use the `--data-binary` option instead of `--data`. One would expect that the client sends the data as-is, but `--data` strips CR und LF from the input. – h2stein Mar 24 '14 at 08:22
  • 27
    Using cUrl with inline json Strings seems to be a nightmare. There's the need to scape the double quote character. Going with a file like this is nicer. – Aritz Jun 26 '14 at 10:26
  • 66
    It's important to add an `@` character before the name of the file, otherwise it won't work. I just spent 20 minutes banging my head at this crap... – Radu Murzea Aug 18 '15 at 11:41
  • 5
    This way you can also run a JSON lint on the file to see if there's an error in parsing the JSON. – datashaman Dec 07 '16 at 12:37
  • 10
    On Windows, you need double quotes around the filename "@body.json" – Stomf Jun 26 '17 at 09:28
  • 1
    First, THANK YOU, you just saved me days of headache. Also, I'm using Windows 10 and was able to get the @file_name.json without needing quotes. I put the JSON query into a file and used English/Spanish/Chinese in my file query (so no need to set UTF). Here is my final call: `curl -H "Ocp-Apim-Subscription-Key: " -H "Content-Type: application/json" --data-binary @body.json ""` – Azurespot May 12 '20 at 22:09
  • 1
    Having a separate file for every jason command to pass to --data sounds like a nightmare. Couldn't you just use a here string (`<<<`) which is a variable assigned with multi-line indented JSON text in "pretty" format? – WinEunuuchs2Unix Jun 11 '20 at 01:02
  • where to place the `.json` file? In the same folder of curl or some other location? – Moeez Feb 12 '21 at 06:22
  • @Moeez - yes same folder (unless you want to write the path to the file) – Ronen Rabinovici May 24 '22 at 22:56
  • This is the ONLY way I could find that ran in a simple bash script without the need for installing anything else. Kudos. – John.M Mar 27 '23 at 04:52
152

For Windows, having a single quote for the -d value did not work for me, but it did work after changing to double quote. Also I needed to escape double quotes inside curly brackets.

That is, the following did not work:

curl -i -X POST -H "Content-Type: application/json" -d '{"key":"val"}' http://localhost:8080/appname/path

But the following worked:

curl -i -X POST -H "Content-Type: application/json" -d "{\"key\":\"val\"}" http://localhost:8080/appname/path
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
venkatnz
  • 1,621
  • 1
  • 10
  • 2
  • 6
    FYI - looks like you're missing a closing double quote around the json body – acanby Mar 14 '16 at 23:10
  • 4
    For me on Windows, the " around the data does not work, no quotes works instead – rodedo Oct 17 '16 at 09:44
  • 4
    If you're using PowerShell, see [this](https://stackoverflow.com/a/36004654/158074) answer. – rsenna Feb 28 '18 at 19:02
  • 1
    For improved quote-handling, and many other reasons, stop using the ancient/weak cmd.exe and try one of the improved shells like Git-Bash from https://gitforwindows.org/ site. (Highly recommended, even if you don't use Git.) – MarkHu Dec 18 '20 at 18:35
  • yep, quoting behaviour is a [mess](https://github.com/PowerShell/PowerShell/issues/1995) in pwsh. But it should be fixed in pwsh 7.3, in 7.2 you can run `Enable-ExperimentalFeature PSNativeCommandArgumentPassing` to not have to escape this quotes – Mariusz Pawelski Oct 05 '22 at 12:28
119

You might find resty useful:

It's a wrapper round CURL which simplifies command line REST requests. You point it to your API endpoint, and it gives you PUT and POST commands (Examples adapted from the homepage).

resty http://127.0.0.1:8080/data #Sets up resty to point at your endpoing
GET /blogs.json                  #Gets http://127.0.0.1:8080/data/blogs.json
                                 #Put JSON
PUT /blogs/2.json '{"id" : 2, "title" : "updated post", "body" : "This is the new."}'
                                 # POST JSON from a file
POST /blogs/5.json < /tmp/blog.json

Also, it's often still necessary to add the Content Type headers. You can do this once, though, to set a default, of add configuration files per-method per-site: Setting default RESTY options

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
mo-seph
  • 6,073
  • 9
  • 34
  • 35
110

It worked for me using:

curl -H "Accept: application/json" -H "Content-type: application/json" -X POST -d '{"id":100}' http://localhost/api/postJsonReader.do

It was happily mapped to the Spring controller:

@RequestMapping(value = "/postJsonReader", method = RequestMethod.POST)
public @ResponseBody String processPostJsonData(@RequestBody IdOnly idOnly) throws Exception {
        logger.debug("JsonReaderController hit! Reading JSON data!"+idOnly.getId());
        return "JSON Received";
}

IdOnly is a simple POJO with an id property.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Luis
  • 1,390
  • 1
  • 10
  • 4
78

You can use Postman to convert to CURL:

Enter image description here

Enter image description here

Note:

The latest Postman version has some UI upgrades and now the code link is available in the sidebar.

Enter image description here

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
取一个好的名字
  • 1,677
  • 14
  • 16
  • The best answer, saved a lot of time, thanks :) – Amit Meena Nov 16 '21 at 10:49
  • This is a nice way for beginners to understand mapping from a UI tool like this to the curl command, but it's not sustainable in the long term as another dependency to learn and maintain – Filip Seman Sep 16 '22 at 19:25
65

As an example, create a JSON file, params.json, and add this content to it:

[
    {
        "environment": "Devel",
        "description": "Machine for test, please do not delete!"
    }
]

Then you run this command:

curl -v -H "Content-Type: application/json" -X POST --data @params.json -u your_username:your_password http://localhost:8000/env/add_server
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
50

I just run into the same problem. I could solve it by specifying

-H "Content-Type: application/json; charset=UTF-8"
Steffen Roller
  • 3,464
  • 25
  • 43
45

This worked well for me.

curl -X POST --data @json_out.txt http://localhost:8080/

Where,

-X Means the HTTP verb.

--data Means the data you want to send.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Felipe Pereira
  • 1,368
  • 16
  • 26
40

You can use Postman with its intuitive GUI to assemble your cURL command.

  1. Install and Start Postman
  2. Type in your URL, Post Body, Request Headers etc. pp.
  3. Click on Code
  4. Select cURL from the drop-down list
  5. copy & paste your cURL command

Note: There are several options for automated request generation in the drop-down list, which is why I thought my post was neccessary in the first place.

kiltek
  • 3,183
  • 6
  • 47
  • 70
36

HTTPie is a recommended alternative to curl because you can do just

http POST http://example.com/some/endpoint name=value name1=value1

It speaks JSON by default and will handle both setting the necessary header for you as well encoding data as valid JSON. There is also:

Some-Header:value

for headers, and

name==value

for query string parameters. If you have a large chunk of data, you can also read it from a file have it be JSON encoded:

field=@file.txt
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Anthony
  • 1,877
  • 17
  • 21
  • I pray for this to be a standard - at least in terms of being available / preinstalled on each server. – smido Jul 05 '22 at 10:41
  • Also, it would be great if `httpie` supported spilling out the `curl` formatted command, for the situation when `httpie` is not available on a specific host. – smido Jul 05 '22 at 10:43
34

TL;DR:

Use the holy trinity, jo + curl + jq (or fx):

jo value=30 type="Tip 3" targetModule="Target 3" configurationGroup=null name="Configuration Deneme 3" description=null identity="Configuration Deneme 3" | \
curl --json @- \
    -X POST \
    http://localhost:8080/xx/xxx/xxxx | \
jq

This will cover necessary headers that were missing: no need to explicitly define the Content-Type and Accept headers.

The new curl way with --json

Early March 2022, curl released a new command line parameter --json with version 7.82.0. This allows for a shortcut to send through JSON and eliminating the need to define the Content-Type that you had missing and Accept headers as these are automatically assumed, hence reducing risk of mistakes:

curl --json '{"tool": "curl"}' https://example.com/

But wait... there is more. Instead of defining the json parameter as a string to the curl command line, use the nifty jo CLI tool to define JSON as series of key value pairs and pipe the output through curl. Using jo only to define your JSON, it works this way:

 > jo -p value=30 type="Tip 3" targetModule="Target 3" configurationGroup=null name="Configuration Deneme 3" description=null identity="Configuration Deneme 3"
version=0 systemId=3 active=true
{
   "value": 30,
   "type": "Tip 3",
   "targetModule": "Target 3",
   "configurationGroup": null,
   "name": "Configuration Deneme 3",
   "description": null,
   "identity": "Configuration Deneme 3",
   "version": 0,
   "systemId": 3,
   "active": true
}

Let's showcase this now with a similar curl command of yours but without extra headers and using jo + jq for nice output:

jo value=30 type="Tip 3" targetModule="Target 3" configurationGroup=null name="Configuration Deneme 3" description=null identity="Configuration Deneme 3" | \
curl --json @- \
    -X POST \
    http://localhost:8080/xx/xxx/xxxx | \
jq

Example with a free API

Using a free mock API for demonstration:

> jo title="Blog Post" body="lorem ipsum" userId=33 | \
curl --json @- \
    -X POST \
    https://jsonplaceholder.typicode.com/posts | \
jq

The output has a pretty format thanks to jq:

{
  "title": "Blog Post",
  "body": "lorem ipsum",
  "userId": 33,
  "id": 101
}
jlr
  • 1,362
  • 10
  • 17
33

Using CURL Windows, try this:

curl -X POST -H "Content-Type:application/json" -d "{\"firstName\": \"blablabla\",\"lastName\": \"dummy\",\"id\": \"123456\"}" http-host/_ah/api/employeeendpoint/v1/employee
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Márcio Brener
  • 429
  • 4
  • 5
26

Use -d option to add payload

curl -X POST \
http://<host>:<port>/<path> \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-d '{
"foo": "bar",
"lorem": "ipsum"
}'

In addition:

use -X POST to use POST method

use -H 'Accept: application/json' to add accept type header

use -H 'Content-Type: application/json' to add content type header

Benjamin W.
  • 46,058
  • 19
  • 106
  • 116
Sma Ma
  • 3,343
  • 2
  • 31
  • 39
  • 1
    I tried to use it but getting {"errors":["no data provided"]} error. – Suresh Jun 01 '20 at 14:16
  • 1
    @Suresh try `curl`'s `-v` switch to get more details. The service you are hitting may be only handling certain content-type values. – MarkHu Dec 18 '20 at 18:32
25

This worked well for me, additionally using BASIC authentication:

curl -v --proxy '' --basic -u Administrator:password -X POST -H "Content-Type: application/json"
        --data-binary '{"value":"30","type":"Tip 3","targetModule":"Target 3","configurationGroup":null,"name":"Configuration Deneme 3","description":null,"identity":"Configuration Deneme 3","version":0,"systemId":3,"active":true}'
        http://httpbin.org/post

Of course, you should never use BASIC authentication without SSL and a checked certificate.

I ran into this again today, using Cygwin's cURL 7.49.1 for Windows... And when using --data or --data-binary with a JSON argument, cURL got confused and would interpret the {} in the JSON as a URL template. Adding a -g argument to turn off cURL globbing fixed that.

See also Passing a URL with brackets to curl.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
davenpcj
  • 12,508
  • 5
  • 40
  • 37
25

If you're testing a lot of JSON send/responses against a RESTful interface, you may want to check out the Postman plug-in for Chrome (which allows you to manually define web service tests) and its Node.js-based Newman command-line companion (which allows you to automate tests against "collections" of Postman tests.) Both free and open!

törzsmókus
  • 1,799
  • 2
  • 21
  • 28
ftexperts
  • 690
  • 7
  • 8
22

You could also put your JSON content in a file and pass it to curl using the --upload-file option via standard input, like this:

echo 'my.awesome.json.function({"do" : "whatever"})' | curl -X POST "http://url" -T -
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
niken
  • 2,499
  • 3
  • 33
  • 56
19

This worked for me:

curl -H "Content-Type: application/json" -X POST -d @./my_json_body.txt http://192.168.1.1/json
Misa Lazovic
  • 2,805
  • 10
  • 32
  • 38
Amit Vujic
  • 1,632
  • 1
  • 24
  • 32
19

I had the issue of:

curl -X POST http://your-server-end-point -H "Content-Type: application/json" -d @path-of-your-json-file.json

See, I did everything right. Only one thing - I missed "@" before the JSON file path.

I found one relevant go-to document on Internet - Common Options.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Indrajeet Gour
  • 4,020
  • 5
  • 43
  • 70
18

Here is another way to do it, if you have dynamic data to be included.

#!/bin/bash

version=$1
text=$2
branch=$(git rev-parse --abbrev-ref HEAD)
repo_full_name=$(git config --get remote.origin.url | sed 's/.*:\/\/github.com\///;s/.git$//')
token=$(git config --global github.token)

generate_post_data()
{
  cat <<EOF
{
  "tag_name": "$version",
  "target_commitish": "$branch",
  "name": "$version",
  "body": "$text",
  "draft": false,
  "prerelease": false
}
EOF
}

echo "Create release $version for repo: $repo_full_name branch: $branch"
curl --data "$(generate_post_data)" "https://api.github.com/repos/$repo_full_name/releases?access_token=$token"
Anand Rockzz
  • 6,072
  • 5
  • 64
  • 71
13

I am using the below format to test with a web server.

use -F 'json data'

Let's assume this JSON dict format:

{
    'comment': {
        'who':'some_one',
        'desc' : 'get it'
    }
}

Full example

curl -XPOST your_address/api -F comment='{"who":"some_one", "desc":"get it"}'
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
user3180641
  • 131
  • 1
  • 2
  • 1
    I can't see how this could possibly be a general-purpose answer. Your server may be configured to handle this strange format, but YMMV. – MarkHu Dec 18 '20 at 19:16
11

This worked for me for on Windows 10:

curl -d "{"""owner""":"""sasdasdasdasd"""}" -H "Content-Type: application/json" -X  PUT http://localhost:8080/api/changeowner/CAR4
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
9

I made a tool called fetcher for this. It can send requests and format curl snippets:

Here's an example:

enter image description here

Example output:

curl -XGET -H "Accept: application/json" -d "{\"value\":\"30\",\"type\":\"Tip 3\",\"targetModule\":\"Target 3\",\"configurationGroup\":null,\"name\":\"Configuration Deneme 3\",\"description\":null,\"identity\":\"Configuration Deneme 3\",\"version\":0,\"systemId\":3,\"active\":true}" "http://localhost:8080/xx/xxx/xxxx"
Pranay Kumar
  • 2,139
  • 1
  • 15
  • 15
  • 3
    Request/tip: URL links should be clearly spelled out. (Not just mysterious "click here.") Especially for self-promotion of your homemade tool. – MarkHu Dec 18 '20 at 18:29
8

For PowerShell I've used:

curl.exe -H "Content-Type: application/json" --data "@content.json" http://localhost:8080/appname/path

Where content.json was the name of the JSON file on my local containing the request, and curl.exe instead of just curl not to use the alias for Invoke-WebRequest.

Or if you want to specify directly the JSON:

curl.exe -H "Content-Type: application/json" --data '{\"username\":\"xyz\",\"password\":\"xyz\"}' http://localhost:8080/appname/path
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
meJustAndrew
  • 6,011
  • 8
  • 50
  • 76
4

--json <data> Sends the specified JSON data in a POST request to the HTTP server.

curl 7.82.0+

# Send a basic JSON object
curl --json '{"name":"xyz","breed":"xyz","age":100}' http://127.0.0.1:3000/cats

# letter @, read the data from a file
curl --json @cat.txt http://127.0.0.1:3000/cats

# letter -, read the data from stdin
echo '{"name":"xyz","breed":"xyz","age":100}' | curl --json @- http://127.0.0.1:3000/cats

curl 7.82.0-

curl -X POST --header "Content-Type: application/json" --data '{"name":"xyz","breed":"xyz","age":100}' http://127.0.0.1:3000/cats
山茶树和葡萄树
  • 2,050
  • 1
  • 18
  • 18
3
  • -H to send something like content-type or an authentication token in the header
  • -d here adds your data
  • finally add a site link

Note: Don't forget to add an authentication token (if you have) for authentication credentials

curl -X POST -H 'Content-Type: application/json' -H 'Authorization: Token 2de403987713595a7955a9b4655b9e206d4294b3' -d '{"title":"Post test with curl", "body": "test body"}' http://127.0.0.1:8000/api/v1/feeds/
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
omar ahmed
  • 635
  • 5
  • 19
2

Based on Anand Rockzz's answer, here is what I did to this on GitHub Actions. It was a bit tricky due to the EOF tag.

My goal was to send an HTTP call once a Vercel deployment was finished (similar to a webhook).

This real-world example might help other people.

send-webhook-callback-once-deployment-ready:
  name: Invoke webhook callback url defined by the customer (Ubuntu 18.04)
  runs-on: ubuntu-18.04
  needs: await-for-vercel-deployment
  steps:
    - uses: actions/checkout@v1 # Get last commit pushed - See https://github.com/actions/checkout
    - name: Expose GitHub slug/short variables # See https://github.com/rlespinasse/github-slug-action#exposed-github-environment-variables
      uses: rlespinasse/github-slug-action@v3.x # See https://github.com/rlespinasse/github-slug-action
    - name: Expose git environment variables and call webhook (if provided)
      # Workflow overview:
      #  - Resolves webhook url from customer config file
      #  - If a webhook url was defined, send a
      run: |
        MANUAL_TRIGGER_CUSTOMER="${{ github.event.inputs.customer}}"
        CUSTOMER_REF_TO_DEPLOY="${MANUAL_TRIGGER_CUSTOMER:-$(cat vercel.json | jq --raw-output '.build.env.NEXT_PUBLIC_CUSTOMER_REF')}"

        VERCEL_DEPLOYMENT_COMPLETED_WEBHOOK=$(cat vercel.$CUSTOMER_REF_TO_DEPLOY.staging.json | jq --raw-output '.build.env.VERCEL_DEPLOYMENT_COMPLETED_WEBHOOK')

        # Checking if a webhook url is defined
        if [ -n "$VERCEL_DEPLOYMENT_COMPLETED_WEBHOOK" ]; then
          # Run script that populates git-related variables as ENV variables
          echo "Running script populate-git-env.sh"
          . ./scripts/populate-git-env.sh

          echo "Resolved git variables:"
          echo "'GIT_COMMIT_SHA': $GIT_COMMIT_SHA"
          echo "'GIT_COMMIT_REF': $GIT_COMMIT_REF"
          echo "'GIT_COMMIT_TAGS': $GIT_COMMIT_TAGS"

          # Generates JSON using a bash function - See https://stackoverflow.com/a/57369772/2391795
          # "End Of File" must be at the beginning of the line with no space/tab before or after - See https://stackoverflow.com/a/12909284/2391795
          # But, when executed by GitHub Action, it must be inside the "run" section instead
          generate_post_data() {
            cat <<EOF
          {
            "MANUAL_TRIGGER_CUSTOMER": "${MANUAL_TRIGGER_CUSTOMER}",
            "CUSTOMER_REF": "${CUSTOMER_REF_TO_DEPLOY}",
            "STAGE": "staging",
            "GIT_COMMIT_SHA": "${GIT_COMMIT_SHA}",
            "GIT_COMMIT_REF": "${GIT_COMMIT_REF}",
            "GIT_COMMIT_TAGS": "${GIT_COMMIT_TAGS}",
            "GITHUB_REF_SLUG": "${GITHUB_REF_SLUG}",
            "GITHUB_HEAD_REF_SLUG": "${GITHUB_HEAD_REF_SLUG}",
            "GITHUB_BASE_REF_SLUG": "${GITHUB_BASE_REF_SLUG}",
            "GITHUB_EVENT_REF_SLUG": "${GITHUB_EVENT_REF_SLUG}",
            "GITHUB_REPOSITORY_SLUG": "${GITHUB_REPOSITORY_SLUG}",
            "GITHUB_REF_SLUG_URL": "${GITHUB_REF_SLUG_URL}",
            "GITHUB_HEAD_REF_SLUG_URL": "${GITHUB_HEAD_REF_SLUG_URL}",
            "GITHUB_BASE_REF_SLUG_URL": "${GITHUB_BASE_REF_SLUG_URL}",
            "GITHUB_EVENT_REF_SLUG_URL": "${GITHUB_EVENT_REF_SLUG_URL}",
            "GITHUB_REPOSITORY_SLUG_URL": "${GITHUB_REPOSITORY_SLUG_URL}",
            "GITHUB_SHA_SHORT": "${GITHUB_SHA_SHORT}"
          }
        EOF
          }

          echo "Print generate_post_data():"
          echo "$(generate_post_data)"

          echo "Calling webhook at '$VERCEL_DEPLOYMENT_COMPLETED_WEBHOOK'"
          echo "Sending HTTP request (curl):"
          curl POST \
            "$VERCEL_DEPLOYMENT_COMPLETED_WEBHOOK" \
            -vs \
            --header "Accept: application/json" \
            --header "Content-type: application/json" \
            --data "$(generate_post_data)" \
            2>&1 | sed '/^* /d; /bytes data]$/d; s/> //; s/< //'

          # XXX See https://stackoverflow.com/a/54225157/2391795
          # -vs - add headers (-v) but remove progress bar (-s)
          # 2>&1 - combine stdout and stderr into single stdout
          # sed - edit response produced by curl using the commands below
          #   /^* /d - remove lines starting with '* ' (technical info)
          #   /bytes data]$/d - remove lines ending with 'bytes data]' (technical info)
          #   s/> // - remove '> ' prefix
          #   s/< // - remove '< ' prefix

        else
          echo "No webhook url defined in 'vercel.$CUSTOMER_REF_TO_DEPLOY.staging.json:.build.env.VERCEL_DEPLOYMENT_COMPLETED_WEBHOOK' (found '$VERCEL_DEPLOYMENT_COMPLETED_WEBHOOK')"
        fi
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vadorequest
  • 16,593
  • 24
  • 118
  • 215
2

The issue is here:

HTTP/1.1 415 Unsupported Media Type

Server Login can't interpret the Media Type of this request, so it is parsing it as text/html

The media type of any resource is declared in the Content-Type property of the request header

"accept" ... header will fail this request, so the following is required for any JSON request to be sent i.e. content-type

-H 'content-type: application/json'

Suppose data and URL are something like this

{"email": "admin@admin.com","password": "123456"}

http://localhost:5000/api/login

Then in Linux

curl  http://localhost:5000/api/login  -H 'content-type: application/json'  -d '{"email": "user@admin.com", "password": "123456"}'

In Windows (single quotes around parameters will not work)

curl  http://localhost:5000/api/login  -H "content-type: application/json"  -d "{\"email\": \"user@admin.com\", \"password\": \"123456\"}"

-X POST key is not required when -d {.....} is present in command.

For a PUT request:

-X PUT
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
ajay_full_stack
  • 494
  • 7
  • 13
2

You can cat the contents of a JSON file to curl via the --data-raw parameter.

curl 'https://api.com/route' -H 'Content-Type: application/json' --data-raw "$(cat ~/.json/payload-2022-03-03.json | grep -v '^\s*//')"

Note: comments in the JSON file are filtered out via grep -v '^\s*//'

You can also pass the data to curl via standard input using grep or cat.

grep -v '^\s*//' ~/.json/payload-2022-03-03.json | curl 'https://api.com/route' -H 'Content-Type: application/json' -d @-

cat ~/.json/payload-2022-03-03.json | grep -v '^\s*//' | curl 'https://api.com/route' -H 'Content-Type: application/json' -d @-

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Andrew
  • 3,733
  • 1
  • 35
  • 36
2

simple is that

curl -X POST https://localhost:3000/ 
   -H "Content-Type: application/json"
   -d '{"productId": 123456, "quantity": 100}'
jazeb007
  • 578
  • 1
  • 5
  • 11
0

below code works for me.

I was using Sample data api

curl -X POST --data @json_out.txt https://sampledataapi.com/API/login

Here the explanation

-X Means the HTTP verb.
--data Means the data you want to send.
Rahul Koshti
  • 186
  • 1
  • 10