I hereby claim:
- I am anandkunal on github.
- I am impvka (https://keybase.io/impvka) on keybase.
- I have a public key ASBjDikMvXd4VPuD27Sj-ADxx-ERd1LLCOe-MMs5OHU2ZQo
To claim this, I am signing this object:
I hereby claim:
To claim this, I am signing this object:
A few years ago, I helped a non-profit organization build and deploy a series of web applications and micro-services on top of AWS. One of the services was responsible for sending out email notifications to people via AWS SES.
Back then, I wrote a really simple program in Go that made direct calls to the AWS API. Instead of using an official library, I read the API specification, learned how to authenticate requests, and implemented a fairly trivial SDK. The code was succinct, readable, and worked perfectly for 3 years without any issues.
That is until this past week…
AWS recently updated the specification, we’re now at Signature Version 4 (SigV4), for how API requests must be formed and signed by clients. In this walkthrough, I’ll share the full Go source code (~130 LOC) that I put together to make valid authenticated calls to AWS for SES. You don’t need to be knowledgeable about Go to grok code in this post. In fact, code in this post will translate pretty cleanly to
package main | |
import ( | |
"log" | |
"net/http" | |
"net/http/httputil" | |
"net/url" | |
) | |
func main() { |
class Thing(object): | |
def __init__(self): | |
self.__missing_method_name = None # Hack! | |
def __getattribute__(self, name): | |
return object.__getattribute__(self, name) | |
def __getattr__(self, name): | |
self.__missing_method_name = name # Could also be a property | |
return getattr(self, '__methodmissing__') |
<?php | |
// Fired for 404 errors | |
ToroHook::add("404", function() {}); | |
// Before/After callbacks in order | |
ToroHook::add("before_request", function() {}); | |
ToroHook::add("before_handler", function() {}); | |
ToroHook::add("after_handler", function() {}); | |
ToroHook::add("after_request", function() {}); |
<?php | |
class ExampleHandler { | |
function get() {} | |
function post() {} | |
function get_xhr() {} | |
function post_xhr() {} | |
} |
<?php | |
Toro::serve(array( | |
"/" => "SplashHandler", | |
"/catalog/page/:number" => "CatalogHandler", | |
"/product/:alpha" => "ProductHandler", | |
"/manufacturer/:string" => "ManufacturerHandler" | |
)); |
<? | |
include("toro.php"); | |
// Domain object, not included, just for following along | |
include("domain/user.php"); | |
class V1UserCreateHandler extends ToroHandler { | |
private function fail($error_type="") { | |
echo json_encode(array("success" => false, "error_type" => $error_type)); | |
exit; |
RewriteEngine on | |
RewriteCond $1 !^(index\.php) | |
RewriteRule ^(.*)$ index.php/$1 [L] |
// Invert the color spectrum | |
Surface::Iter iter(newSurface.getIter()); | |
while(iter.line()) { | |
while(iter.pixel()) { | |
iter.r() = 255 - iter.r(); | |
iter.g() = 255 - iter.g(); | |
iter.b() = 255 - iter.b(); | |
} | |
} |