Updated at Feb 2, 2017
The prototype is open sourced on GitHub.
What is Aliyun?
Aliyun is a cloud service provider rooted in mainland China.
Currently, it provides numerous kinds of cloud service, such as:
- ECS: Elastic Compute Service
- RDS: Relational Database Service
- OSS: Object Storage Service
- SLB: Server Load Balancer
- CDN: Content Delivery Network
All APIs of Aliyun are based on the HTTP/HTTPS protocol. But handcrafting the query string can be boring and difficult. So you need some libraries to help you get a native, convenient API. Beside that, some visualization, user information management etc., are also part of the SDK’s functionalities.
By developing a SDK in Haskell, I can combine the cloud service into my Haskell-driven application. For the sake of itself, I hope for:
- Safety and soundness, easy to refactor
- Generality, easy to extend
- Less code, easy to read
Up to now, I finished some interfacing code with ECS, OSS and RDS services. It took me two days to build everything from scratch to commit
There are mainly two ways of calling:
- URL parameters
- HTTP Header
And it requires a lot of
- Encoding, such as UTF-8, base64, URL encode etc.
- Canonicalization: uniquely map a structure into string
- Hashing & Encrypting, mostly using MD5 and HMAC-SHA1
However, beyond that, due to the fact that industry Haskell is basically built on top of a lot of user-contributed packages, so a lot of gluing work are necessary. And again due to the strong typing, so a lot of explicit castings are driving me crazy. Look at this and feel it yourself:
base64 :: [Word8] -> String base64 = BC.unpack . BB.encode . B.pack
And a lot of packages, for example, the
Data.HMAC, is actually type-unsafe. It leaves the typing duty to user, so I have to create
Secret wrappers myself. Actually, just due to this fact, I wasted two hours debugging my code and finally spotted that I encrypted the secret with message!
And another bad thing is that, the
Network.HTTP is not providing any HTTPS functionality. So you have to use the
Network.HTTP.Conduit package. However, a lot of stuff, such as the header format, are not mutually compatible.
Currently, its architecture is simple:
Aliyun.Auth gives you safe type
AkId, also re-exports some specific encryption/encoding functions.
Aliyun.API is the general logic on composing a URL. Any query-specific parameters are passed in, so other common parameters can be added here.
Aliyun.Action exposes a typeclass
Action, representing a functionality. For example, in
Aliyun.RDS, we have
RDSAction type, so it can implement the
Action typeclass, and other supporting code can be written in a more general style.
Aliyun.Config is about all related user configuration in order to construct API query string.
Aliyun.HTTP is a very hack-ish thing. I mainly re-export the different HTTP/HTTPS simple request APIs.
Aliyun.RDS are some service implementations. It is not a complete implementation, but considerably easier to extend.
- Full support for all available APIs. My idea is to parse the official documentation and generate Haskell bindings automatically
- Better configuration setup. The actual user information can be rather complex, for example, user has several services, different services have different plans, different plans can be in different regions, having different URLs etc.
- Unify the HTTP interface