Class, constructor and inherance.

holo via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Mon Oct 12 09:56:54 PDT 2015


@Rikki:

> If you didn't need to make it easily changeable I would say not 
> even bother with OOP at all.

Basically that what i had was enough for me and on top of that i 
could build my app. It need to just periodically check for new 
instances and if they are started or stopped and count "up and 
running time" for billing purpose. But like i said i want to 
learn programming in D and basically OOP too so i want to make it 
"proper way".

BTW: i think right now i understand what tuple is, but still 
don't know for what to duplicate struct functionalities :). Those 
Templates still don't understand but i hope that will came 
naturally with time and practice. eg.. they are very similar to 
normal functions but you can call it with types not only 
attributes.. strange ;)

I red yours advises and try to create according to it my own 
first class.

I moved time functions and variables to method "go" they need to 
be current as possible when im sending request, if wont 
authorization could not pass.. so i think they shouldn't be in 
constructor.

I moved some other variables too, and created interface.

 From all that things came out such monster which is working and 
doing its job :)

module sigawsv4;

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;

interface credential
{
	int go();
}

class sigv4 : credential
{
	//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&Version=2013-10-15")
	{

		this.method = methodStr;
		this.service = serviceStr;
		this.host = hostStr;
		this.region = regionStr;
		this.endpoint = endpointStr;
		this.payload = payloadStr;
		this.request_parameters = parmStr;

		this.accessKey = environment.get("AWS_ACCESS_KEY");
		this.secretKey = environment.get("AWS_SECRET_KEY");
	}

	public:
		string method;
		string service;
		string host;
		string region;
		string endpoint;
		string payload;
		string request_parameters;

	
		int go()
		{
			//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 = request_parameters;
			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();

			return content;
		}

	private:
		const algorithm = "AWS4-HMAC-SHA256";
		
		string accessKey;
		string secretKey;

		string currentClock;
		string currentDate;
		string curDateStr;
		string currentTime;
		string curTimeStr;
		string xamztime;

		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;
		}
}

void main()
{
	sigv4 sig = new sigv4();	
	writeln(sig.go());
}

I want to ask you for  advises what i could do with that class to 
make it looks more "pro"/elegant/build in "proper way". Probably 
there are lot of mistakes which all beginners are doing.

eg.: Did i use interface correctly?


More information about the Digitalmars-d-learn mailing list