1 module doveralls.request;
2 
3 import std.json, std.net.curl, std.stdio, etc.c.curl;
4 
5 /// Send the json arguments to Coveralls.io.
6 int sendData(JSONValue data)
7 {
8     static if (__VERSION__ >= 2072)
9         auto json = toJSON(data, false);
10     else
11         auto json = toJSON(&data, false);
12 
13     curl_httppost* formpost, lastptr;
14     curl_formadd(&formpost, &lastptr,
15                  CurlForm.copyname, "json_file".ptr,
16                  CurlForm.buffer, "doveralls.json".ptr,
17                  CurlForm.bufferptr, json.ptr,
18                  CurlForm.bufferlength, json.length,
19                  CurlForm.contenttype, "application/json".ptr,
20                  CurlForm.end);
21 
22     // don't wait for 100-continue response
23     curl_slist *headerlist;
24     headerlist = curl_slist_append(headerlist, cast(char*)"Expect:".ptr);
25 
26     Curl curl;
27     curl.initialize();
28     import std.process : env=environment;
29     auto host = env.get("COVERALLS_ENDPOINT", "https://coveralls.io");
30     curl.set(CurlOption.url, host ~ "/api/v1/jobs");
31     curl.set(CurlOption.httpheader, headerlist);
32     curl.set(CurlOption.httppost, formpost);
33     curl.set(CurlOption.useragent, "doveralls ("~HTTP.defaultUserAgent~")");
34     static extern(C) size_t append(void *buffer, size_t size, size_t nmemb, void *userp)
35     {
36         *cast(string*)userp ~= (cast(char*)buffer)[0 .. size * nmemb];
37         return size * nmemb;
38     }
39     string response;
40     curl.set(CurlOption.writefunction, &append);
41     alias CURLOPTION_WRITEDATA = CurlOption.file; // alias is missing in std.net.curl
42     curl.set(CURLOPTION_WRITEDATA, &response);
43     static if (__VERSION__ >= 2067)
44         enum dontThrowOnError = ThrowOnError.no;
45     else
46         enum dontThrowOnError = false;
47     if (auto res = curl.perform(dontThrowOnError))
48     {
49         import core.stdc.string : strlen;
50         auto msg = curl_easy_strerror(res);
51         stderr.writeln("Failed to upload data: ", msg[0 .. strlen(msg)]);
52         return 1;
53     }
54 
55     auto jsonResponse = parseJSON(response);
56     if (jsonResponse.type != JSONType.object || "url" !in jsonResponse.object)
57     {
58         stderr.writeln("Unexpected upload response: ", jsonResponse.toPrettyString);
59         return 1;
60     }
61     writeln("Uploaded data to: ", jsonResponse["url"].str);
62     return 0;
63 }