Httpie: Request to add `-d, --data` option for raw body like curl

Created on 31 Oct 2016  ·  18Comments  ·  Source: httpie/httpie

The request is simple, just to add an option to pass raw data like curl does:

http :/api/user -d 'MyRawData...'

I know that in mostly cases if you are sending JSON or form data, it can be achieved with the _"request items"_, like:

http :/api/hey say=Hello to=me …

And it will converted to the proper format depending of the content type, that is awesome! And if you have something that is not a JSON or form data to send, you can do something like:

echo 'MyRawData...' | http :/api/hey

But this is impractical, the main idea of HTTPie is _cURL-like tool for humans_ , and this case is far of that principle, in fact, curl is more practical than HTTPie for the previous example. Adding more than one command and pipe them with ugly characters like | < just because a simple option is missing doesn't sound _human-friendly_.

What's wrong with add the -d option to http?

Most helpful comment

you can just do http POST example.org <<< "foo bar" or http POST example.org < file.name

All 18 comments

What's wrong with add the -d option to http?

There'd be nothing _particularly_ wrong with that. I just find piping cleaner and strongly prefer when there is only one way of doing the same thing. Piping exists for this very purpose (i.e. to pass _data_ to programs), and It's easy to understand, universal, and unambiguous. Every decent CLI tool supports piping (with the notable exception of curl) so you only need to learn the concept once.

Compare:

httpie

A universal method for passing request data is through redirected stdin (standard input). Such data is buffered and then with no further processing used as the request body.

curl

-d, --data <data>
              (HTTP)  Sends  the  specified data in a POST request to the HTTP server, in the same way that a browser
              does when a user has filled in an HTML form and presses the submit button. This will cause curl to pass
              the  data  to  the  server  using  the  content-type application/x-www-form-urlencoded.  Compare to -F,
              --form.

              -d, --data is the same as --data-ascii. --data-raw is almost the same  but  does  not  have  a  special
              interpretation of the @ character. To post data purely binary, you should instead use the --data-binary
              option.  To URL-encode the value of a form field you may use --data-urlencode.

              If any of these options is used more than once on the same command line, the data pieces specified will
              be merged together with a separating &-symbol. Thus, using '-d name=daniel -d skill=lousy' would gener-
              ate a post chunk that looks like 'name=daniel&skill=lousy'.

              If you start the data with the letter @, the rest should be a file name to read the data from, or -  if
              you  want  curl  to read the data from stdin. Multiple files can also be specified. Posting data from a
              file named 'foobar' would thus be done with --data @foobar. When --data is told to  read  from  a  file
              like  that,  carriage  returns  and newlines will be stripped out. If you don't want the @ character to
              have a special interpretation use --data-raw instead.

Yes, I agree with you that support piping in a command line tool is a good feature, and also I made a command line tool that supports piping ( Mongotail ), and to be honest I didn't know that curl doesn't support it. But I think that support both features does not add complexity, because almost all known CLI tools in the Unix ecosystem support both ways. Eg. cat, grep, find, tail ...

The commands you mention do generally accept either a filename argument list or raw input data through stdin. The don't, however, accept the actual data as arguments. Accepting raw data via an argument is quite uncommon.

(Clarifying what I wrote in an earlier comment: curl does support stdin but it needs be to explicitly instructed to read it with, for example, --data-binary @-.)

Came here to file a bug related to this issue, so maybe it's not a bug but working as designed.

I have a bash script I was changing to use "httpie" instead of "curl". The requests are empty-body POSTs to an http server. I run this script by piping it into a docker exec -i ${container} bash -x.

I had a hard time figuring out that the http POST command, while it worked fine when run from an interactive shell, was causing the script to immediately exit.

I guess it's something about http reading stdin in the docker exec. It seems weird that I have to pipe "echo -n" to avoid this.

#!/bin/bash
echo "STARTING..."
echo -n | http POST ...     # this replaces: curl -XPOST --data-binary '' ...
echo "Without the 'echo -n' above this statement would not be reached."
echo "DONE"

(@jamshid you POST an empty body simply with http POST httpbin.org/post. Please read about the specifics of using HTTPie in script — you want to include the --ignore-stdin option. This is unrelated issue, though, so please open a new issue instead of replying here, if needed.)

Am I right in thinking that 15.1 Request data from a filename covers this issue's original request? I guess this issue can be closed.

As an aside, I wish I'd known about HTTPie before yesterday as I would've avoided 3 hours or so working out why line breaks in my XML file weren't being preserved. (I thought it was my app but it was curl, which requires its --data-binary option to be used to leave the data alone.) Thanks for HTTPie!

It does not, @DavidOliver . @mrsarm requested to be able to pass a string from parameter, not contents of a file.

+1

Would you accept MR with this feature @jakubroztocil ?

you can just do http POST example.org <<< "foo bar" or http POST example.org < file.name

http :/api/hey say=Hello to=me …

you can just do http POST example.org <<< "foo bar" or http POST example.org < file.name

seemed not work for powershell, 'raw body data' | http post :8080/api/events worked for me on powershell,
but still wanna -d, --data or something like this to transfer a raw body data

according to the docs you can use a "Bash here string":

http example.com/ <<<'{"name": "John"}'

UI-wise, the option makes sense.

i can't seem to find a way to send an empty json object ({}) which is a strange but valid use case.

@minusf: i can't seem to find a way to send an empty json object ({}) which is a strange but valid use case.

$ echo '{}' | http httpbin.org/post

any way to discard the newline while redirecting?

$ echo 20 | http POST httpbin.org/post

the data filed would be "data": "20\n"

@hahattan you can instruct echo to not print the trailing newline character with -n:

$ echo -n foo | http httpbin.org/post
Was this page helpful?
0 / 5 - 0 ratings

Related issues

tonsV2 picture tonsV2  ·  4Comments

loretoparisi picture loretoparisi  ·  6Comments

hrj picture hrj  ·  5Comments

Govinda-Fichtner picture Govinda-Fichtner  ·  6Comments

mattotodd picture mattotodd  ·  3Comments