Class, constructor and inherance.
Rikki Cattermole via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Thu Oct 15 21:04:11 PDT 2015
On 16/10/15 4:14 PM, holo wrote:
> 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;
> }
> }
I was thinking along the lines of a new object per result.
But that sorta also works, since the handler can be and will be reused.
More information about the Digitalmars-d-learn
mailing list