Thread overview
POST request with std.net.curl
Jul 23, 2021
bachmeier
Jul 23, 2021
Ali Çehreli
Jul 23, 2021
bachmeier
Jul 24, 2021
frame
Jul 25, 2021
bachmeier
Jul 25, 2021
bachmeier
Jul 25, 2021
frame
Jul 26, 2021
bachmeier
Jul 26, 2021
frame
Jul 27, 2021
bachmeier
July 23, 2021

I'm writing a D program that interacts with the Todoist API using std.net.curl. It's not a problem to do get requests to query tasks, but I cannot find a way to get post to work to create a new task.

This is a working bash script, where APIKEY is defined elsewhere and $1 and $2 are user input when running the script:

curl "https://api.todoist.com/rest/v1/tasks" -X POST --data "{"'"'"content"'"'": "'"'"$1"'"'", "'"'"project_id"'"'": $2}" -H "Content-Type: application/json" -H "Authorization: Bearer $APIKEY"

(For obvious reasons I'm not going to provide a working example.) How can I translate this into a post function call within D?

Todoist API Reference

July 23, 2021
On 7/23/21 11:11 AM, bachmeier wrote:
> I'm writing a D program that interacts with the Todoist API using std.net.curl. It's not a problem to do get requests to query tasks, but I cannot find a way to get post to work to create a new task.
> 
> This is a working bash script, where APIKEY is defined elsewhere and $1 and $2 are user input when running the script:
> 
> ```
> curl "https://api.todoist.com/rest/v1/tasks" -X POST --data "{"'"'"content"'"'": "'"'"$1"'"'", "'"'"project_id"'"'": $2}" -H "Content-Type: application/json" -H "Authorization: Bearer $APIKEY"
> ```
> 
> (For obvious reasons I'm not going to provide a working example.) How can I translate this into a post function call within D?
> 
> [Todoist API Reference](https://developer.todoist.com/rest/v1/?shell#create-a-new-task)

I haven't used it but isn't it the version of post that takes a dictionary here?

  https://dlang.org/phobos/std_net_curl.html#.post

If the Authorization is the problem, I wonder whether addRequestHeader is the solution:

  https://dlang.org/phobos/std_net_curl.html#.HTTP.addRequestHeader

Ali
July 23, 2021
On Friday, 23 July 2021 at 19:59:33 UTC, Ali Çehreli wrote:
> On 7/23/21 11:11 AM, bachmeier wrote:
>> I'm writing a D program that interacts with the Todoist API using std.net.curl. It's not a problem to do get requests to query tasks, but I cannot find a way to get post to work to create a new task.
>> 
>> This is a working bash script, where APIKEY is defined elsewhere and $1 and $2 are user input when running the script:
>> 
>> ```
>> curl "https://api.todoist.com/rest/v1/tasks" -X POST --data "{"'"'"content"'"'": "'"'"$1"'"'", "'"'"project_id"'"'": $2}" -H "Content-Type: application/json" -H "Authorization: Bearer $APIKEY"
>> ```
>> 
>> (For obvious reasons I'm not going to provide a working example.) How can I translate this into a post function call within D?
>> 
>> [Todoist API Reference](https://developer.todoist.com/rest/v1/?shell#create-a-new-task)
>
> I haven't used it but isn't it the version of post that takes a dictionary here?
>
>   https://dlang.org/phobos/std_net_curl.html#.post
>
> If the Authorization is the problem, I wonder whether addRequestHeader is the solution:
>
>   https://dlang.org/phobos/std_net_curl.html#.HTTP.addRequestHeader
>
> Ali

Authorization is working - it's the same whether I'm doing a GET or POST request. The problem is passing the data. The main problem is that the documentation doesn't explain how to translate a `--data` option into a `post` call. I've tried everything I can think of, including what's shown in the documentation, but haven't found anything that works.
July 24, 2021
On Friday, 23 July 2021 at 21:25:01 UTC, bachmeier wrote:

> Authorization is working - it's the same whether I'm doing a GET or POST request. The problem is passing the data. The main problem is that the documentation doesn't explain how to translate a `--data` option into a `post` call. I've tried everything I can think of, including what's shown in the documentation, but haven't found anything that works.

You just need to supply a JSON encoded string for the data - from an object like std.json.JSONValue via its toString() method for example.
July 25, 2021

On Saturday, 24 July 2021 at 06:01:25 UTC, frame wrote:

>

On Friday, 23 July 2021 at 21:25:01 UTC, bachmeier wrote:

>

Authorization is working - it's the same whether I'm doing a GET or POST request. The problem is passing the data. The main problem is that the documentation doesn't explain how to translate a --data option into a post call. I've tried everything I can think of, including what's shown in the documentation, but haven't found anything that works.

You just need to supply a JSON encoded string for the data - from an object like std.json.JSONValue via its toString() method for example.

I understand, and indeed, that's what's done by the working curl command I posted. I don't know how to translate that into a post request using std.net.curl. The natural thing would be to pass as the second argument the same string I'm sending as the --data option to curl, but that doesn't work.

I've decided to give up on std.net.curl and use executeShell to capture the output from shell commands.

July 25, 2021

On Friday, 23 July 2021 at 18:11:51 UTC, bachmeier wrote:

[...]

After all this, it turned out the answer was a simple (but not obvious) typo in the header information. It would be nice to get more information than "HTTP request returned status code 400 ()". I don't know if that's possible, but command line curl provides better messages.

July 25, 2021

On Sunday, 25 July 2021 at 13:07:36 UTC, bachmeier wrote:

>

On Friday, 23 July 2021 at 18:11:51 UTC, bachmeier wrote:

[...]

After all this, it turned out the answer was a simple (but not obvious) typo in the header information. It would be nice to get more information than "HTTP request returned status code 400 ()". I don't know if that's possible, but command line curl provides better messages.

In doubt you can turn on the verbose() method on the HTTP object.

July 26, 2021

On Sunday, 25 July 2021 at 15:44:14 UTC, frame wrote:

>

On Sunday, 25 July 2021 at 13:07:36 UTC, bachmeier wrote:

>

On Friday, 23 July 2021 at 18:11:51 UTC, bachmeier wrote:

[...]

After all this, it turned out the answer was a simple (but not obvious) typo in the header information. It would be nice to get more information than "HTTP request returned status code 400 ()". I don't know if that's possible, but command line curl provides better messages.

In doubt you can turn on the verbose() method on the HTTP object.

That's a modest improvement (for the small number of people that find the option in the docs) but definitely not at the same level of information as the curl CLI. I created an issue requesting better output: https://issues.dlang.org/show_bug.cgi?id=22142

July 26, 2021

On Monday, 26 July 2021 at 14:13:53 UTC, bachmeier wrote:

> >

In doubt you can turn on the verbose() method on the HTTP object.

That's a modest improvement (for the small number of people that find the option in the docs) but definitely not at the same level of information as the curl CLI. I created an issue requesting better output: https://issues.dlang.org/show_bug.cgi?id=22142

I see your intention but this is a bad example. Status 400 means "Bad request" because of a wrong header or wrong payload or any error in the request. "Empty content" wouldn't describe the actual error if you have sent data.

In fact the client cannot know whats wrong. "Content-Type: Application/json" may be wrong from the sight of the server (which is NOT, they are case insensitive btw) but the protocol allows you to use whatever content-type you want and no client needs to know how to handle all. It's just wrong if your CLI tool interprets a status 400 as "Empty content" by arbitrary assumptions.

All better the lib could do is to print the text for the status too and the raw payload sent by the server aka error description, if any.

July 27, 2021

On Monday, 26 July 2021 at 19:53:05 UTC, frame wrote:

>

All better the lib could do is to print the text for the status too and the raw payload sent by the server aka error description, if any.

That's what I'm proposing. Currently std.net.curl's post function doesn't report all the information sent by the server, while curl at the command line does.