On 7/6/22 02:26, Bagomot wrote:

> 1) How to make asynchronous HTTP requests with curl in order to receive
> progress and status? And how do you know that the request is completed?

I don't know how dlangui or others automate this but I had fun writing the following program that uses std.concurrency and std.net.curl:

> 3) My application must perform some work in a separate thread (I do this
> through inheritance of the worker from core.thread.Thread, is that
> correct?).

core.thread.Thread is low level. I would consider std.parallelism and std.concurrency first. (I use the latter for message passing in the program below.)

import std.concurrency;
import std.net.curl;
import std.conv;
import std.stdio;
import std.algorithm;
import std.range;
import std.format;

// Signifies that the main thread requests the getter to stop
// serving. (Not used here.)
struct Done {}

// Represents download progress.
struct Progress {
  size_t downloaded;
  size_t total;
}

// Represents a URL
struct Url {
  string value;
}

// The thread entry point for the getter
void getterFunc() {
  receive(
    (Done _) {
      // Not used here but this is for clean termination.
      return;
    },

    (Url url) {
      // Received a URL to get.
      auto http = HTTP(url.value);

      // std.net.curl.HTTP will call this delegate with progress
      // information...
      http.onProgress((size_t dl, size_t dln, size_t ul, size_t uln) {
        if (dl != 0) {
          // ... and we will send it along to the main thread.
          ownerTid.send(Progress(dln, dl));
        }
        return 0;
      });

      // std.net.curl.HTTP will call this delegate with
      // downloaded parts...
      http.onReceive((ubyte[] data) {
        // ... and we will send it along to the main thread.
        ownerTid.send((cast(char[])data).to!string);
        return data.length;
      });

      // Everything is set up. Let's do it.
      http.perform();
    },
  );
}

void main() {
  auto getter = spawnLinked(&getterFunc);

  getter.send(Url("dlang.org"));

  string result;
  bool done = false;
  while (!done) {
    receive(
      (LinkTerminated msg) {
        // (This may or may not be expected.)
        stderr.writefln!"The getter thread terminated.";
        done = true;
      },

      (Progress progress) {
        writeln(progress);
        if (!result.empty &&
            (progress.downloaded == progress.total)) {
          done = true;
        }
      },

      (string part) {
        result ~= part;
      },
    );
  }

  writefln!"Downloaded %s bytes:\n%s"(result.length, result);
}

Ali

Reply via email to