0

I know how to use curl to insert new events into a CalDAV calendar, if the event is saved as a local ics file by a previous command:

$command > $localfile curl -T "$localfile" $url 

That works perfectly, but I'd like to do this without the need for a local file, I want to pipe the result from $command into curl, something like this:

$command | curl -T - $url 

According to curl’s manual, the option "T -" should be what is required: it is supposed to read from stdin instead from a file. But if I use that option, I get this response:

<?xml version="1.0" encoding="utf-8"?> <d:error xmlns:d="DAV:" xmlns:s="http://sabredav.org/ns"> <s:exception>Sabre\DAV\Exception\Conflict</s:exception> <s:message>PUT is not allowed on non-files.</s:message> </d:error> 

I've tried different other parameter like "--data" and "--data-raw", but I haven't found the right combination yet. Could someone help me with this, please?


Actually, the complete command cycle I am trying to realize looks like this:

cat<<EOC | curl -T - $url BEGIN:VCALENDAR VERSION:2.0 BEGIN:VEVENT CREATED:${CREATED} UID:${RNDUID} CLASS:PUBLIC CATEGORIES:TV SUMMARY:${SUMMARY} LOCATION:${LOCATION} DTSTART:${DTSTART} DTEND:${DTEND} DESCRIPTION:${DESCRIPTION} END:VEVENT END:VCALENDAR EOC 

I tried "echo" instead of "cat", but that doesn't change the result.

4
  • Don't you need to echo that command ? Therefore echo $command | curl -T - $url Commented Jan 30, 2020 at 16:35
  • It might also be that your HTTP content type defaults to something that is not a file. So maybe you have to specify -H "Content-Type: text/plain" with a correct content type Commented Jan 30, 2020 at 16:42
  • There seems to be a very big difference between the handling of these two commands: "create_tempfile; curl -T $tempfile $url" and "create_tempfile; cat $tempfile | curl -T - $url". While the first one works perfectly, the second exits with "put is not allowed on none-files". So I guess the main question is: how to make NextCloud believe that the input is a file and nothing else? Commented Feb 1, 2020 at 9:52
  • Please mark the answer as accepted instead of putting Solved in the title. Commented Feb 2, 2020 at 20:20

2 Answers 2

0

Eureka! :)

The solution is to make use of a HERE document:

$CURL $url -T /dev/stdin <<-EOF BEGIN:VCALENDAR VERSION:2.0 BEGIN:VEVENT CREATED:$CREATED UID:$RNDUID SUMMARY:$SUMMARY LOCATION:$LOCATION DTSTART:$DTSTART DTSTAMP:$DTSTART DTEND:$DTEND DESCRIPTION:$DESCRIPTION END:VEVENT END:VCALENDAR EOF 

Regard the input parameter "/dev/stdin"! The curl parameter "-T" does not work there, when "-" (dash) is used for the input. You have to use "/dev/stdin" instead, which, sadly, is not available on all Unix like systems. On Linux it can be used as a replacement for "-", when programs don't support the option "-" or if the dash has a different meaning to them, like marking the end of all input parameters.

The "-" after "<<" is part of the HERE document command: it suppresses tabulators, but no blanks, so the document can be arranged in a more eye-friendly way.

I haven't figured out yet what's the difference between

cat<<EOF | curl ... ... EOF 

and the solution I found now, other than this first attempt clearly is a useless use of cat. But it looks very much like the "cat" brings in something that the old dog named "curl" doesn't like much. ;)

If some one has an explanation to this, I'd be very thankful to here it.

Sign up to request clarification or add additional context in comments.

2 Comments

Glad you found the answer ! I would recommend you to edit your question title as to make it more related to the issue ("How to pipe text to CURL PUT command" or something) now that you have a better idea of what caused the issue. Also instead of including SOLVED in the title, just mark your own answer as correct (a green mark will be displayed alongside your question on SO)
I marked the answer as accepted. But I am not so sure about the title, because I don't know if this solution is also valid for piping other data than a calendar into curl's put command. I doubt that using a HERE document will work with binary data, like a picture.
0

If your shell allows, you could simply use process substitution with <(:

curl -T <($command) $url 

The <($command) will be replaced by a temporary file descriptor (/dev/fdXX) delivering the output from $command. Then curl will be able to read as if it was a regular file.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.