Class, constructor and inherance.
holo via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Thu Oct 15 20:14:02 PDT 2015
I created interface IfRequestHandler it is used only by one class
RequestHandlerXML right now but thanks to such solution i can
create more classes with same interface which can handle it in
different way.. eg second can be RequestHandlerCSVReport or
RequestHandlerSendViaEmail. Is it this what you ware mentioning?
Bellow working code:
/////////
//main.d:
/////////
#!/usr/bin/rdmd
import std.stdio, sigv4, conf;
void main()
{
ResultHandlerXML hand = new ResultHandlerXML;
SigV4 req = new SigV4(hand);
//req.ResultHandler = hand;
req.go();
hand.processResult();
}
/////////
//conf.d:
/////////
module conf;
import std.stdio, std.process;
import std.net.curl:exit;
interface IfConfig
{
void set(string val, string var);
string get(string var);
}
class Config : IfConfig
{
this()
{
this.accKey = environment.get("AWS_ACCESS_KEY");
if(accKey is null)
{
writeln("accessKey not available");
exit(-1);
}
this.secKey = environment.get("AWS_SECRET_KEY");
if(secKey is null)
{
writeln("secretKey not available");
exit(-1);
}
}
public:
void set(string val, string var)
{
switch(var)
{
case "accKey": accKey = val; break;
case "secKey": secKey = val; break;
default: writeln("Can not be set, not such
value");
}
}
string get(string var)
{
string str = "";
switch(var)
{
case "accKey": return accKey;
case "secKey": return secKey;
default: writeln("Can not be get, not such value");
}
return str;
}
// private:
string accKey;
string secKey;
}
/////////
//sigv4.d
/////////
module sigv4;
import std.stdio, std.process;
import std.digest.sha, std.digest.hmac;
import std.string;
import std.conv;
import std.datetime;
import std.net.curl;
import conf;
interface IfSigV4
{
IfResultHandler go(ResultHandlerXML ResultHandler);
}
interface IfResultHandler
{
void setResult(int content);
void processResult();
}
class ResultHandlerXML : IfResultHandler
{
void setResult(int content)
{
this.xmlresult = content;
}
void processResult()
{
writeln(xmlresult);
}
private:
int xmlresult;
}
class SigV4 : IfSigV4
{
//could be changed to take some structure as parameter instead
of such ammount of attributes
this(string methodStr = "GET", string serviceStr = "ec2", string
hostStr = "ec2.amazonaws.com", string regionStr = "us-east-1",
string endpointStr = "https://ec2.amazonaws.com", string
payloadStr = "", string parmStr = "Action=DescribeInstances")
in
{
writeln(parmStr);
}
body
{
conf.Config config = new conf.Config;
this.method = methodStr;
this.service = serviceStr;
this.host = hostStr;
this.region = regionStr;
this.endpoint = endpointStr;
this.payload = payloadStr;
this.requestParameters = parmStr;
this.accessKey = config.get("accKey");
if(accessKey is null)
{
writeln("accessKey not available");
exit(-1);
}
this.secretKey = config.get("secKey");
if(secretKey is null)
{
writeln("secretKey not available");
exit(-1);
}
}
public:
string method;
string service;
string host;
string region;
string endpoint;
string payload;
string requestParameters;
IfResultHandler ResultHandler;
IfResultHandler go(ResultHandlerXML ResultHandler)
{
//time need to be set when we are sending request not before
auto currentClock = Clock.currTime(UTC());
auto currentDate = cast(Date)currentClock;
auto curDateStr = currentDate.toISOString;
auto currentTime = cast(TimeOfDay)currentClock;
auto curTimeStr = currentTime.toISOString;
auto xamztime = curDateStr ~ "T" ~ curTimeStr ~ "Z";
canonicalURI = "/";
canonicalQueryString = requestParameters ~ this.Version;
canonicalHeadersString = "host:" ~ this.host ~ "\n" ~
"x-amz-date:" ~ xamztime ~ "\n";
signedHeaders = "host;x-amz-date";
auto canonicalRequest = getCanonicalRequest(canonicalURI,
canonicalQueryString, canonicalHeadersString, signedHeaders);
string credentialScope = curDateStr ~ "/" ~ region ~ "/" ~
service ~ "/" ~ "aws4_request";
string stringToSign = algorithm ~ "\n" ~ xamztime ~ "\n" ~
credentialScope ~ "\n" ~
sha256Of(canonicalRequest).toHexString.toLower;
auto signingKey = getSignatureKey(secretKey, curDateStr,
region, service);
string signature = hmac!SHA256(stringToSign.representation,
signingKey).toHexString.toLower;
string authorizationHeader = algorithm ~ " " ~ "Credential=" ~
accessKey ~ "/" ~ credentialScope ~ ", " ~ "SignedHeaders=" ~
signedHeaders ~ ", " ~ "Signature=" ~ signature;
auto client = HTTP(endpoint ~ "?" ~ canonicalQueryString);
client.method = HTTP.Method.get;
client.addRequestHeader("x-amz-date", xamztime);
client.addRequestHeader("Authorization", authorizationHeader);
auto content = client.perform();
writeln(content);
ResultHandler.setResult(content);
return ResultHandler;
}
private:
const string algorithm = "AWS4-HMAC-SHA256";
const string Version = "&Version=2013-10-15";
string accessKey;
string secretKey;
string canonicalURI;
string canonicalQueryString;
string canonicalHeadersString;
string signedHeaders;
alias sign = hmac!SHA256;
auto getSignatureKey(string key, string dateStamp, string
regionName, string serviceName)
{
auto kString = ("AWS4" ~ key).representation;
auto kDate = sign(dateStamp.representation, kString);
auto kRegion = sign(regionName.representation, kDate);
auto kService = sign(serviceName.representation, kRegion);
auto kSigning = sign("aws4_request".representation, kService);
return kSigning;
}
auto getCanonicalRequest(string canonicalURI, string
canonicalQueryString, string canonicalHeadersString, string
signedHeaders)
{
string payloadHash = sha256Of(payload).toHexString.toLower;
string canonicalRequest = method ~ "\n" ~ canonicalURI ~ "\n"
~ canonicalQueryString ~ "\n" ~ canonicalHeadersString ~ "\n" ~
signedHeaders ~ "\n" ~ payloadHash;
return canonicalRequest;
}
}
More information about the Digitalmars-d-learn
mailing list