Your application calls the Amazon Mechanical Turk web service to perform an operation, and receive the results of that operation. A request sent by your application to the service contains:
The name of the operation to call
Parameters for the operation, if any
Authentication parameters that verify your application is allowed to make requests on your behalf
In the next steps for the sample project, you will set up the tools
used to make the request, create the routines to authenticate the
request, then call the service's
GetAccountBalance operation.
In this section, you include the libraries and set up the tools to make the request.
To make a request for the Java project, use Apache Axis and the SOAP proxy classes you generated in the previous section.
To set up the Apache Axis SOAP proxy classes
In the main routine, create and initialize the objects for
calling the GetAccountBalance
operation.
public static void main( String [] args ) {
try {
// Set up the web service client
AWSMechanicalTurkRequester locator = new AWSMechanicalTurkRequesterLocator();
AWSMechanicalTurkRequesterPortType service = locator.getAWSMechanicalTurkRequesterPort();
// Construct the request
GetAccountBalance getAccountBalance = new GetAccountBalance();
To make a request for the C# project, use the .NET Web Resource classes you generated in the previous section.
To set up the .NET Web Resource classes
In the main routine, create and initialize objects for
calling the GetAccountBalance
operation.
static void Main(string[] args)
{
try
{
// Set up the web service client
AWSMechanicalTurkRequester service = new AWSMechanicalTurkRequester();
// Construct the request
GetAccountBalance getAccountBalance = new GetAccountBalance();
For the Perl project, use the LWP module
to make a REST request.
For the PHP project, use PHP's built-in routines to make a REST request. You don't need to set anything up.
For the Python (REST) project, use Python's
urllib library to make a REST request.
For the Python (SOAP) project, use Python's
SOAPpy library to make a request.
To set up SOAPpy
Import the SOAPpy library.
# Import libraries import SOAPpy
Set up the SOAP proxy with the Amazon Mechanical Turk WSDL.
# Define constants
SERVICE_VERSION = '2006-10-31'
[...]
# Set up the web service client
wsdl = 'http://mechanicalturk.amazonaws.com/AWSMechanicalTurk/' + SERVICE_VERSION + '/AWSMechanicalTurkRequester.wsdl'
server = SOAPpy.WSDL.Proxy(wsdl)
For the Ruby (REST) project, use Ruby's
net/http library to make a REST request.
For the Ruby (SOAP) project, use Ruby's
soap/wsdlDriver library to make a request.
To set up soap/wsdlDriver
Require the soap/wsdlDriver library.
# Require libraries require 'soap/wsdlDriver'
Set up the SOAP proxy with the Amazon Mechanical Turk WSDL.
# Define constants
SERVICE_VERSION = '2006-10-31'
[...]
# Set up the web service client
wsdl = "http://mechanicalturk.amazonaws.com/AWSMechanicalTurk/#{SERVICE_VERSION}/AWSMechanicalTurkRequester.wsdl"
server = SOAP::WSDLDriverFactory.new( wsdl ).create_rpc_driver
When you make a request to the web service, the service needs to know who you are so it can verify that you are authorized to make the request. You tell the web service who you are by providing two pieces of information with your request:
To get your AWS access key ID and secret key
Go to the Amazon Web Services web site:
Move your mouse over the Your Web Services Account button in the upper-right-hand corner. From the pop-up menu that appears, select View Access Key Identifiers.
Sign in with your e-mail address and password. Your AWS access key ID appears on the screen, as a string of numbers and letters.
To view your secret key, click Show in the corresponding box. Your secret key is a string of numbers, letters and symbols.
The general procedure for calculating a signature for a request is as follows. The code to perform these steps is shown below.
To calculate a signature for a request (general)
Generate a timestamp in a standard format. Set the
Timestamp parameter in the request to
this value.
Important: | Make sure that your system clock is set correctly. Your system's clock must be within 5 minutes of the web service's internal clock for the timestamp to be considered valid. |
Produce the value to encrypt by concatenating the name of the service, the name of the operation being called, and the timestamp.
Apply the HMAC algorithm with the SHA-1 digest algorithm (HMAC-SHA1) to the value, using your AWS secret key as the key for the SHA-1 algorithm.
Apply the base-64 encoding algorithm to the result of the
previous step. Set the Signature
parameter of your request to be this base-64-encoded value.
These steps vary in detail depending on your language and toolkits.
For the Java project, define functions for generating the timestamp and signature values, using the time, HMAC-SHA1, and Base64 routines that the Java runtime environment provides.
To calculate a signature for a request in Java
Import the classes.
// Import classes
[...]
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Date;
import java.util.TimeZone;
import org.apache.axis.encoding.Base64;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.SignatureException;
Define constant String values for your AWS access key ID and secret key, as well as for the name of the service.
// Define constants
private final static String SERVICE_NAME = "AWSMechanicalTurkRequester";
private final static String AWS_ACCESS_KEY_ID = "[INSERT YOUR ACCESS KEY ID]";
private final static String SECRET_KEY = "[INSERT YOUR SECRET ACCESS KEY]";
Define routines for generating the timestamp and signature values.
// Define authentication routines
private final static String TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
private final static String TIME_ZONE = "UTC";
private final static SimpleDateFormat df = new SimpleDateFormat( TIMESTAMP_FORMAT );
static {
df.setTimeZone( TimeZone.getTimeZone( TIME_ZONE ) );
}
public static String generateTimestamp( Calendar time ) {
return df.format( time.getTime() );
}
public static String generateSignature( String serviceName,
String operation,
String timestamp,
String key )
throws java.security.SignatureException {
String data = serviceName + operation + timestamp;
final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
String signature;
try {
SecretKeySpec signingKey = new SecretKeySpec( key.getBytes(),
HMAC_SHA1_ALGORITHM );
Mac mac = Mac.getInstance( HMAC_SHA1_ALGORITHM );
mac.init( signingKey );
byte[] rawHmac = mac.doFinal( data.getBytes() );
signature = Base64.encode( rawHmac );
} catch ( Exception e ) {
throw new SignatureException( "Failed to generate Signature: "
+ e.getMessage() );
}
return signature;
}
In the main routine, calculate and set the authentication parameters for the request.
public static void main( String [] args ) {
try {
[...]
// Calculate and set the request authentication parameters
getAccountBalance.setAWSAccessKeyId( AWS_ACCESS_KEY_ID );
Calendar time = new GregorianCalendar();
time.setTime( new Date() );
getAccountBalance.setTimestamp( time );
String timestamp = generateTimestamp( time );
String signature = generateSignature( SERVICE_NAME,
"GetAccountBalance",
timestamp,
SECRET_KEY
);
getAccountBalance.setSignature( signature );
For the C# project, define functions for generating
the timestamp and signature values, using the time, HMAC-SHA1, and
Base64 routines provided by the System resources.
To calculate a signature for a request in C#
Use the namespaces of the System resources.
(These resources have already been added to your project
as part of the Console Application template.)
// Use namespaces
[...]
using System.Security.Cryptography;
using System.IO;
Define constant String values for your AWS access key ID and secret key, as well as for the name of the service.
// Define constants
private static string SERVICE_NAME = "AWSMechanicalTurkRequester";
private static string AWS_ACCESS_KEY_ID = "[INSERT YOUR ACCESS KEY ID]";
private static string SECRET_KEY = "[INSERT YOUR SECRET ACCESS KEY]";
Define routines for generating the timestamp and signature values.
Note: |
The string value of the timestamp used to calculate the
signature must be identical to the value of the
One method is to format the DateTime value into a String using the desired format, then re-parse the String value back to a DateTime value. When you pass the result to .NET, the value sent over the wire matches the String value. |
// Define authentication routines
private static String TIMESTAMP_FORMAT = "yyyy-MM-ddTHH:mm:ss.fffZ";
static String generateTimestampAsString(DateTime time)
{
return time.ToUniversalTime().ToString(TIMESTAMP_FORMAT);
}
static DateTime generateTimestampAsDateTime(DateTime time)
{
return DateTime.ParseExact(generateTimestampAsString(time),
TIMESTAMP_FORMAT, null).ToUniversalTime();
}
static String generateSignature(
String serviceName,
String operation,
String timestamp,
String key)
{
String data = serviceName + operation + timestamp;
byte[] rawData = Encoding.UTF8.GetBytes(data);
byte[] rawKey = Encoding.UTF8.GetBytes(key);
HMACSHA1 hmac = new HMACSHA1(rawKey);
CryptoStream cryptoStream =
new CryptoStream(Stream.Null, hmac, CryptoStreamMode.Write);
cryptoStream.Write(rawData, 0, rawData.Length);
cryptoStream.Close();
return Convert.ToBase64String(hmac.Hash);
}
In the main routine, calculate and set the authentication parameters for the request.
static void Main(string[] args)
{
try
{
[...]
// Calculate and set the request authentication parameters
getAccountBalance.AWSAccessKeyId = AWS_ACCESS_KEY_ID;
DateTime time = DateTime.Now;
String timestampAsString = generateTimestampAsString(time);
DateTime timestampAsDateTime = generateTimestampAsDateTime(time);
getAccountBalance.Timestamp = timestampAsDateTime;
String signature = generateSignature(SERVICE_NAME,
"GetAccountBalance",
timestampAsString,
SECRET_KEY);
getAccountBalance.Signature = signature;
For the Perl project, define functions for generating
the timestamp and signature values, using the
Digest::HMAC_SHA1 and MIME::Base64
modules.
To calculate a signature for a request in Perl
Use the modules.
# Use modules
[...]
use Digest::HMAC_SHA1 qw(hmac_sha1);
use MIME::Base64;
Define constants for your AWS access key ID and secret key, as well as the name of the service.
# Define constants my $AWS_ACCESS_KEY_ID = "[INSERT YOUR ACCESS KEY ID]"; my $AWS_SECRET_ACCESS_KEY = "[INSERT YOUR SECRET ACCESS KEY]"; my $SERVICE_NAME = "AWSMechanicalTurkRequester"; my $SERVICE_VERSION = "2006-10-31";
Define routines for generating the timestamp and signature values.
# Define authentication routines
sub generate_timestamp {
my ($t) = @_;
return time2str('%Y-%m-%dT%H:%M:%SZ', $t, 'GMT');
}
sub generate_signature {
my ($service, $operation, $timestamp, $secret_access_key) = @_;
my $string_to_encode = $service . $operation . $timestamp;
my $hmac = hmac_sha1($string_to_encode, $secret_access_key);
my $signature = encode_base64($hmac);
chop $signature;
return $signature;
}
Generate the timestamp and signature values with the new routines.
# Calculate the request authentication parameters my $operation = "GetAccountBalance"; my $timestamp = generate_timestamp(time); my $signature = generate_signature($SERVICE_NAME, $operation, $timestamp, $AWS_SECRET_ACCESS_KEY);
For the PHP project, define functions for generating the timestamp and signature values, as well as a support function for calculating the HMAC. Use PHP's built-in routines for SHA-1 digests and base-64 encoding.
To calculate a signature for a request in PHP
Define constants for your AWS access key ID and secret key, as well as the name of the service.
// Define constants $AWS_ACCESS_KEY_ID = "[INSERT YOUR ACCESS KEY ID]"; $AWS_SECRET_ACCESS_KEY = "[INSERT YOUR SECRET ACCESS KEY]"; $SERVICE_NAME = "AWSMechanicalTurkRequester"; $SERVICE_VERSION = "2006-10-31";
Define routines for calculating the HMAC and for generating the timestamp and signature values.
// Define authentication routines
function generate_timestamp($time) {
return gmdate("Y-m-d\TH:i:s\\Z", $time);
}
function hmac_sha1($key, $s) {
return pack("H*", sha1((str_pad($key, 64, chr(0x00)) ^ (str_repeat(chr(0x5c), 64))) .
pack("H*", sha1((str_pad($key, 64, chr(0x00)) ^ (str_repeat(chr(0x36), 64))) . $s))));
}
function generate_signature($service, $operation, $timestamp, $secret_access_key) {
$string_to_encode = $service . $operation . $timestamp;
$hmac = hmac_sha1($secret_access_key, $string_to_encode);
$signature = base64_encode($hmac);
return $signature;
}
Generate the timestamp and signature values using the new routines.
// Calculate the request authentication parameters $operation = "GetAccountBalance"; $timestamp = generate_timestamp(time()); $signature = generate_signature($SERVICE_NAME, $operation, $timestamp, $AWS_SECRET_ACCESS_KEY);
For the Python (REST) project, define functions for
generating the timestamp and signature values, using the
time, hmac, sha and
base64 libraries that are part of the standard
Python distribution.
To calculate a signature for a request in Python
Import the libraries.
# Import libraries import time import hmac import sha import base64
Define constants for your AWS access key ID and secret key, as well as the name of the service.
# Define constants AWS_ACCESS_KEY_ID = '[INSERT YOUR ACCESS KEY ID]' AWS_SECRET_ACCESS_KEY = '[INSERT YOUR SECRET ACCESS KEY]' SERVICE_NAME = 'AWSMechanicalTurkRequester' SERVICE_VERSION = '2006-10-31'
Define routines for generating the timestamp and signature values.
# Define authentication routines
def generate_timestamp(gmtime):
return time.strftime("%Y-%m-%dT%H:%M:%SZ", gmtime)
def generate_signature(service, operation, timestamp, secret_access_key):
my_sha_hmac = hmac.new(secret_access_key, service + operation + timestamp, sha)
my_b64_hmac_digest = base64.encodestring(my_sha_hmac.digest()).strip()
return my_b64_hmac_digest
Generate the timestamp and signature values using the new routines.
# Calculate the request authentication parameters
operation = 'GetAccountBalance'
timestamp = generate_timestamp(time.gmtime())
signature = generate_signature('AWSMechanicalTurkRequester', operation, timestamp, AWS_SECRET_ACCESS_KEY)
For the Python (SOAP) project, define functions for
generating the timestamp and signature values, using the
time, hmac, sha and
base64 libraries that are part of the standard
Python distribution.
To calculate a signature for a request in Python
Import the libraries.
# Import libraries import time import hmac import sha import base64
Define constants for your AWS access key ID and secret
key, as well as the operation name
(GetAccountBalance).
# Define constants AWS_ACCESS_KEY_ID = '[INSERT YOUR ACCESS KEY ID]' AWS_SECRET_ACCESS_KEY = '[INSERT YOUR SECRET ACCESS KEY]' SERVICE_VERSION = '2006-10-31'
Define routines for generating the timestamp and signature values.
# Define authentication routines
def generate_timestamp(gmtime):
return time.strftime("%Y-%m-%dT%H:%M:%SZ", gmtime)
def generate_signature(service, operation, timestamp, secret_access_key):
my_sha_hmac = hmac.new(secret_access_key, service + operation + timestamp, sha)
my_b64_hmac_digest = base64.encodestring(my_sha_hmac.digest()).strip()
return my_b64_hmac_digest
Generate the timestamp and signature values using the new routines.
# Calculate the request authentication parameters
operation = 'GetAccountBalance'
timestamp = generate_timestamp(time.gmtime())
signature = generate_signature('AWSMechanicalTurkRequester', operation, timestamp, AWS_SECRET_ACCESS_KEY)
For the Ruby (REST) project, define functions for
generating the timestamp and signature values, as well as a
support function for calculating the HMAC. Use the
digest/sha1 and base64 libraries
that are part of the standard Ruby distribution.
To calculate a signature for a request in Ruby
Require the libraries.
# Require libraries
[...]
require 'digest/sha1'
require 'base64'
Define constants for your AWS access key ID and secret key, as well as the name of the service.
# Define constants AWS_ACCESS_KEY_ID = '[INSERT YOUR ACCESS KEY ID]' AWS_SECRET_ACCESS_KEY = '[INSERT YOUR SECRET ACCESS KEY]' SERVICE_NAME = 'AWSMechanicalTurkRequester' SERVICE_VERSION = '2006-10-31'
Define routines for calculating the HMAC and for generating the timestamp and signature values.
# Define authentication routines
def generate_timestamp(time)
return time.gmtime.strftime('%Y-%m-%dT%H:%M:%SZ')
end
def hmac_sha1(key, s)
ipad = [].fill(0x36, 0, 64)
opad = [].fill(0x5C, 0, 64)
key = key.unpack("C*")
key += [].fill(0, 0, 64-key.length) if key.length < 64
inner = []
64.times { |i| inner.push(key[i] ^ ipad[i]) }
inner += s.unpack("C*")
outer = []
64.times { |i| outer.push(key[i] ^ opad[i]) }
outer = outer.pack("c*")
outer += Digest::SHA1.digest(inner.pack("c*"))
return Digest::SHA1.digest(outer)
end
def generate_signature(service, operation, timestamp, secret_access_key)
msg = "#{service}#{operation}#{timestamp}"
hmac = hmac_sha1( secret_access_key, msg )
b64_hmac = Base64::encode64(hmac).chomp
return b64_hmac
end
Generate the timestamp and signature values using the new routines.
# Calculate the request authentication parameters
operation = 'GetAccountBalance'
timestamp = generate_timestamp(Time.now)
signature = generate_signature('AWSMechanicalTurkRequester', operation, timestamp, AWS_SECRET_ACCESS_KEY)
For the Ruby (REST) project, define functions for
generating the timestamp and signature values, as well as a
support function for calculating the HMAC. Use the
digest/sha1 and base64 libraries
that are part of the standard Ruby distribution.
To calculate a signature for a request in Ruby
Require the libraries.
# Require libraries
[...]
require 'digest/sha1'
require 'base64'
Define constants for your AWS access key ID and secret key, as well as the name of the service.
# Define constants AWS_ACCESS_KEY_ID = '[INSERT YOUR ACCESS KEY ID]' AWS_SECRET_ACCESS_KEY = '[INSERT YOUR SECRET ACCESS KEY]' SERVICE_NAME = 'AWSMechanicalTurkRequester' SERVICE_VERSION = '2006-10-31'
Define routines for calculating the HMAC, and for generating the timestamp and signature values.
# Define authentication routines
def generate_timestamp(time)
return time.gmtime.strftime('%Y-%m-%dT%H:%M:%SZ')
end
def hmac_sha1(key, s)
ipad = [].fill(0x36, 0, 64)
opad = [].fill(0x5C, 0, 64)
key = key.unpack("C*")
key += [].fill(0, 0, 64-key.length) if key.length < 64
inner = []
64.times { |i| inner.push(key[i] ^ ipad[i]) }
inner += s.unpack("C*")
outer = []
64.times { |i| outer.push(key[i] ^ opad[i]) }
outer = outer.pack("c*")
outer += Digest::SHA1.digest(inner.pack("c*"))
return Digest::SHA1.digest(outer)
end
def generate_signature(service, operation, timestamp, secret_access_key)
msg = "#{service}#{operation}#{timestamp}"
hmac = hmac_sha1( secret_access_key, msg )
b64_hmac = Base64::encode64(hmac).chomp
return b64_hmac
end
Generate the timestamp and signature values using the new routines.
# Calculate the request authentication parameters
operation = 'GetAccountBalance'
timestamp = generate_timestamp(Time.now)
signature = generate_signature('AWSMechanicalTurkRequester', operation, timestamp, AWS_SECRET_ACCESS_KEY)
In this procedure, you set the parameters and make the request to
call the GetAccountBalance operation.
So far, you have instantiated the proxy objects that manage
communication with the web service and the object that
contains the parameter data for the call to
GetAccountBalance. Here, you
construct the request object with the parameter data
object, then make the request using the service proxy object.
To make the web service request in Java
Construct the request object.
// Set other parameters
GetAccountBalanceRequest request = new GetAccountBalanceRequest();
getAccountBalance.setRequest( new GetAccountBalanceRequest [] { request } );
Make the request and store the response object.
// Make the request
GetAccountBalanceResponse response = service.getAccountBalance( getAccountBalance );
So far, you instantiated the proxy object that
manages communication with the web service, and you instantiated
the object that contains the parameter data for the call to
GetAccountBalance. Here, you
construct the request object using the parameter data object,
then make the request using the service proxy object.
To make the web service request in C#
Construct the request object.
// Set other parameters
GetAccountBalanceRequest request = new GetAccountBalanceRequest();
getAccountBalance.Request = new GetAccountBalanceRequest[] { request };
Make the request and store the response object.
// Make the request
GetAccountBalanceResponse response = service.GetAccountBalance(getAccountBalance);
To make a REST request in Perl, set up a hash of parameter data, then make the HTTP request.
To make the web service request in Perl
Construct a hash containing the parameter data.
# Construct the request
my $parameters = {
Service => $SERVICE_NAME,
Version => $SERVICE_VERSION,
AWSAccessKeyId => $AWS_ACCESS_KEY_ID,
Timestamp => $timestamp,
Signature => $signature,
Operation => $operation,
};
Use LWP::UserAgent to make the HTTP POST
request with the parameter data, and store the response.
# Make the request my $url = "http://mechanicalturk.amazonaws.com/onca/xml?"; my $ua = LWP::UserAgent->new; my $response = $ua->post($url, $parameters);
To make a REST request in PHP, construct an HTTP GET URL with the parameter data, then use a PHP built-in function to make the HTTP GET request and treat the results as XML data.
To make the web service request in PHP
Construct the HTTP GET URL with the parameter data.
// Construct the request $url = "http://mechanicalturk.amazonaws.com/onca/xml" . "?Service=" . urlencode($SERVICE_NAME) . "&Operation=" . urlencode($operation) . "&Version=" . urlencode($SERVICE_VERSION) . "&Timestamp=" . urlencode($timestamp) . "&AWSAccessKeyId=" . urlencode($AWS_ACCESS_KEY_ID) . "&Signature=" . urlencode($signature);
Make the HTTP GET request, parse the response as XML data and store the response.
// Make the request $xml = simplexml_load_file($url);
To make a REST request in Python, construct a
dictionary of parameter data, then use the urllib
module to make the HTTP request. Use the
xml.dom.minidom module to parse the response as
XML data.
To make the web service request in Python (REST)
Construct a dictionary with the parameter data.
# Construct the request
parameters = {
'Service': SERVICE_NAME,
'Version': SERVICE_VERSION,
'AWSAccessKeyId': AWS_ACCESS_KEY_ID,
'Timestamp': timestamp,
'Signature': signature,
'Operation': operation,
}
Make the HTTP request, then parse the response as XML data and store the parsed response.
# Make the request url = 'http://mechanicalturk.amazonaws.com/onca/xml?' result_xmlstr = urllib.urlopen(url, urllib.urlencode(parameters)).read() result_xml = xml.dom.minidom.parseString(result_xmlstr)
To make a SOAP request in Python, call a method on the
SOAPpy service proxy you instantiated with the
parameter data. The proxy provides methods for each operation
described in the WSDL.
To make a REST request in Ruby, construct a dictionary of parameter data, construct the HTTP GET URL using those parameters, make the HTTP request, then parse the response as XML data.
To make the web service request in Ruby (REST)
Construct a dictionary containing the parameter data.
# Construct the request
parameters = {
:Service => SERVICE_NAME,
:Version => SERVICE_VERSION,
:AWSAccessKeyId => AWS_ACCESS_KEY_ID,
:Operation => operation,
:Signature => signature,
:Timestamp => timestamp,
}
Construct the HTTP GET URL for the request.
# Make the request
param_string = (parameters.collect { |key,value| "#{key}=#{CGI::escape(value)}" }).join('&')
url = URI.parse( 'http://mechanicalturk.amazonaws.com/onca/xml?' + param_string )
Make the request and parse the response as XML data.
xml = REXML::Document.new( Net::HTTP.get(url) )
To make a SOAP request in Ruby, construct a dictionary with the parameter data, then call a method on the SOAP proxy object.
To make the web service request in Ruby (SOAP)
Construct a dictionary with the parameter data.
# Construct the request
parameters = {
:AWSAccessKeyId => AWS_ACCESS_KEY_ID,
:Timestamp => timestamp,
:Signature => signature,
:Request => {},
}
Make the request by calling the
GetAccountBalance method on the SOAP
proxy object.
# Make the request result = server.GetAccountBalance( parameters )