1 2 /** Small helpers for libCURL 3 * 4 * This module contains all the CURL related helpers. 5 */ 6 module acme.curl_helpers; 7 8 import etc.c.curl; 9 10 import std.conv; 11 import std.net.curl; 12 import std.stdio; 13 import std.string; 14 import std.typecons; 15 16 private: 17 18 void myLog(alias fun = writeln, T...)(T args) 19 { 20 if (curlBeVerbose) 21 fun(args); 22 } 23 24 /** Current release number - FIXME Derive this from Git Tag. How in D? */ 25 26 public: 27 enum acmeClientVersion = "0.1.8"; /// Client Version FIXME How to set this from cmdline? 28 bool curlBeVerbose = false; /// Use verbose outputs? 29 30 31 /** Compose an error msg from custom and CURL error 32 * 33 * Params: 34 * s = custom message 35 * c = CURLcode 36 */ 37 string getCurlError(string s, CURLcode c) 38 { 39 import std.format : format; 40 auto errorstring = curl_easy_strerror(c).to!string; 41 auto resultstring = format( "%s\nErrorcode: %d (%s)", s, c, errorstring); 42 return resultstring; 43 } 44 45 /* ---------------------------------------------------------------------------- */ 46 47 /** Get just the http receive headers with a given name from an URL 48 49 Params: 50 url = Url to query 51 headerKey = headerline to query 52 Returns: 53 the value of a given header or null 54 */ 55 string getResponseHeader(string url, string headerKey) 56 { 57 string headerVal; 58 59 auto http = HTTP(url); 60 http.setUserAgent = "acme-lw-d/" ~ acmeClientVersion ~ " " ~ HTTP.defaultUserAgent(); 61 http.method = HTTP.Method.head; 62 http.onReceiveHeader = 63 (in char[] key, in char[] value) 64 { 65 myLog( "Response Header : ", key, " = ", value); 66 if (key.toLower == headerKey.toLower) 67 headerVal = value.idup; 68 }; 69 http.perform(); 70 return headerVal; 71 } 72 73 /* ---------------------------------------------------------------------------- */ 74 75 /** Do some posting, filter for some headerkey 76 * 77 * Params: 78 * url = url to pst to 79 * postBody = data to post 80 * status = storage for a HTTP.StatusLine 81 * rheaders = responseheader to return 82 * nonce = pointer to nonce string, so that we can update it. 83 * 84 * Returns: 85 * the received payload of the POST operation 86 */ 87 string doPost(string url, char[] postBody, HTTP.StatusLine* status, 88 string[string]* rheaders, 89 string* nonce) 90 { 91 string response; 92 //string headerVal; 93 94 auto http = HTTP(url); 95 http.setUserAgent = "acme-lw-d/" ~ acmeClientVersion ~ " " ~ HTTP.defaultUserAgent(); 96 http.verbose = curlBeVerbose; 97 http.method = HTTP.Method.post; 98 http.addRequestHeader("Content-Type", "application/jose+json"); 99 100 http.onReceiveHeader = 101 (in char[] key, in char[] value) 102 { 103 if (key.toLower == "replay-nonce") { 104 *nonce = value.idup; 105 myLog("Setting new NOnce: ", *nonce); 106 } 107 }; 108 http.onReceive = 109 (ubyte[] data) 110 { 111 //writefln( "data: %s", to!string(data)); 112 response ~= data; 113 return data.length; 114 }; 115 http.postData = postBody; 116 117 http.perform(); 118 119 if (status !is null) *status = http.statusLine; 120 121 if (rheaders !is null) 122 *rheaders = http.responseHeaders; 123 124 return response; 125 } 126 127 /* ---------------------------------------------------------------------------- */ 128