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 /** Current release number - FIXME Derive this from Git Tag. How in D? */
17 enum acmeClientVersion = "0.0.1";
18 
19 /** Compose an error msg from custom and CURL error
20  *
21  * Params:
22  *  msg - custom message
23  */
24 string getCurlError(string s, CURLcode c)
25 {
26 	import std.format;
27 	auto errorstring = curl_easy_strerror(c).to!string;
28 	auto resultstring = format( "%s\nErrorcode: %d (%s)", s, c, errorstring);
29     return resultstring;
30 }
31 
32 /* ---------------------------------------------------------------------------- */
33 
34 /** Get just the http receive headers with a given name from an URL
35 
36 	Params:
37 	  url - Url to query
38 	  headerKey - headerline to query
39 	Returns:
40 	  the value of a given header or null
41  */
42 string getResponseHeader(string url, string headerKey)
43 {
44 	string headerVal;
45 
46 	auto http = HTTP(url);
47 	http.setUserAgent = "acme-lw-d/" ~ acmeClientVersion ~ " " ~ HTTP.defaultUserAgent();
48 	http.method = HTTP.Method.head;
49 	http.onReceiveHeader =
50 		(in char[] key, in char[] value)
51 			{
52 				writeln( "Response Header : ", key, " = ", value);
53 				if (key.toLower == headerKey.toLower)
54 					headerVal = value.idup;
55 			};
56 	http.perform();
57 	return headerVal;
58 }
59 
60 /* ---------------------------------------------------------------------------- */
61 
62 /** Do some posting, filter for some headerkey
63  *
64  * Params:
65  *  url - url to pst to
66  *  postBody - data to post
67  *  rheaders - responseheader to return
68  *  nonce - pointer to nonce string, so that we can update it.
69  *
70  * Returns:
71  *   the received payload of the POST operation
72  */
73 string doPost(string url, char[] postBody, HTTP.StatusLine* status,
74 	string[string]* rheaders,
75 	string* nonce)
76 {
77 	string response;
78 	string headerVal;
79 
80 	auto http = HTTP(url);
81 	http.setUserAgent = "acme-lw-d/" ~ acmeClientVersion ~ " " ~ HTTP.defaultUserAgent();
82 	http.verbose = true;
83 	http.method = HTTP.Method.post;
84 	http.addRequestHeader("Content-Type", "application/jose+json");
85 
86 	http.onReceiveHeader =
87 		(in char[] key, in char[] value)
88 			{
89 				if (key.toLower == "replay-nonce") {
90 					*nonce = value.idup;
91 					writeln("Setting new NOnce: ", *nonce);
92 				}
93 			};
94 	http.onReceive =
95 		(ubyte[] data)
96 			{
97 				//writefln( "data: %s", to!string(data));
98 				response ~= data;
99 				return data.length;
100 			};
101 	http.postData = postBody;
102 
103 	http.perform();
104 
105 	if (status !is null) *status = http.statusLine;
106 
107 	if (rheaders !is null)
108 		*rheaders = http.responseHeaders;
109 
110 	return response;
111 }
112 
113 /* ---------------------------------------------------------------------------- */
114