Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore stdin when STDIN is closed #660

Closed
mqudsi opened this issue Mar 1, 2018 · 3 comments
Closed

Ignore stdin when STDIN is closed #660

mqudsi opened this issue Mar 1, 2018 · 3 comments

Comments

@mqudsi
Copy link

mqudsi commented Mar 1, 2018

I ran into the bug reported in #150 and subsequently worked around in f7b703b but under different circumstances.

In my case, http was being invoked as part of a BsdMakefile script. bmake helpfully buffers IO when performing a parallel make (make -jX) so that lines from various rule outputs are not intermixed. httpie was detecting this as stdin and reporting an error about conflicting input streams (command line and STDIN).

Before looking up #150 or even Googling the issue, I correctly surmised that was the case, and attempted to work around it by explicitly closing STDIN:

http POST "https://neosmart.net/xxxx" authcode="xxxx" version="5.5.2" 0<&-
usage: http [--json] [--form] [--pretty {all,colors,format,none}]
            [--style STYLE] [--print WHAT] [--headers] [--body] [--verbose]
            [--all] [--history-print WHAT] [--stream] [--output FILE]
            [--download] [--continue]
            [--session SESSION_NAME_OR_PATH | --session-read-only SESSION_NAME_OR_PATH]
            [--auth USER[:PASS]] [--auth-type {basic,digest}]
            [--proxy PROTOCOL:PROXY_URL] [--follow]
            [--max-redirects MAX_REDIRECTS] [--timeout SECONDS]
            [--check-status] [--verify VERIFY]
            [--ssl {ssl2.3,ssl3,tls1,tls1.1,tls1.2}] [--cert CERT]
            [--cert-key CERT_KEY] [--ignore-stdin] [--help] [--version]
            [--traceback] [--default-scheme DEFAULT_SCHEME] [--debug]
            [METHOD] URL [REQUEST_ITEM [REQUEST_ITEM ...]]
http: error: Request body (from stdin or a file) and request data (key=value) cannot be mixed.

Is it possible for httpie to distinguish between a closed and redirected stream?

@stormbeta
Copy link

stormbeta commented Aug 2, 2018

I agree - the default should be to use explicit args over implicit stdin; the current behavior of throwing an arbitrary error is quite confusing and surprising.

The objection raised in #150 is that the tool shouldn't try to guess, but most shell utilities already give priority to local or explicit context over global or implied context, and that's the behavior expected by the vast majority of developers.

For example, if I run git commit --author=..., git isn't going to throw an error just because I happen to have the author configured in the global git config. It correctly understands that I intend to override the global config with an invocation-local explicit flag, and this is the behavior most people would expect.

With httpie, the data args are just as explicit as the author flag above, whereas the stdin could come from anywhere, including outside the script entirely and in non-obvious ways:

http get https://google.com x=y

There is no local redirect of stdin, stdin is never explicitly used in any way. If I run the script directly, it works as expected. But if I run in a watch loop...

fswatch script.sh | xargs -n1 -I{} bash script.sh

Now the script breaks for what appears to the user to be no reason - and in my case the fswatch command was part of a larger suite of CLI helpers, making the breakage seem even more arbitrary and confusing.

@jkbrzt
Copy link
Member

jkbrzt commented Nov 24, 2018

The stdin handling is indeed confusing. I can see two good improvements mentioned here:

  1. ignoring stdin if it's closed
  2. ignoring stdin if data is specified via foo=bar data arguments as well (i.e., distinguishing between @file and < file and throwing the error only for the former)

This leaves us with the "hanging" issue when no data args are specified and httpie is called with redirected stdin, for example, from cron:

$ crontab -l
0 * * * * http httpbin.org/get                  # this will hang
0 * * * * http --ingore-stdin httpbin.org/get   # this won't

I think the design choice to automatically read stdin when redirected (like bash does, for example) is really useful during interactive usage, but at the expense of non-interactive usage not being intuitive (even though it's documented). I wish there was a way to distinguish between the two modes.

To completely get rid of this issue, it would require changing the handling of stdin from the current implicit one to an explicit one (i.e., adding something like --read-stdin). However, this wouldn't be backwards-compatible and would probably break many existing scripts.

One thing that can be done to improve the UX while maintaining backwards compatibility could be to write a warning message to stderr if stdin is being read but no data arrives within, say, 1s.

@jkbrzt
Copy link
Member

jkbrzt commented May 23, 2020

This no longer throws an error:

$ echo stdin_data | http httpbin.org/post cli=data 0<&-

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants