I would like to create a pure redirect bucket in AWS S3, I am sure the s3client is operational without problems.
$subdomain = 'test.example.com';
$redirectURL = 'https://www.somedomain.com/redirect?someparam';
$bucketID = $s3->createBucket(['Bucket' => $bucket ]);
$arg = array(
'Bucket' => $bucket, // REQUIRED
'WebsiteConfiguration' => array( // REQUIRED
'ErrorDocument' => array( 'Key' => 'err.html', ),
'IndexDocument' => array( 'Suffix' => 'index.html', ),
'RedirectAllRequestsTo' => array('HostName' => $redirectURL, ),
'RoutingRules' => array(
array(
'Redirect' => array(
'HostName' => $redirectURL,
'HttpRedirectCode' => '301',
),
),
),
),
);
$result = $s3->putBucketWebsite($arg);
However, it output following error even i tried to change some other settings.
> Request ID E00C517E4F812581
Error Type client
Error Code MalformedXML
I wonder if there's any hidden setting I need to add on it.
RedirectAllRequestsTo is mutually exclusive with ErrorDocument, IndexDocument, and RoutingRules. If you are redirecting everything elsewhere, there would be no evaluation of the error or index documents, nor would the routing rules be applicable.
RedirectAllRequestsTo
Describes the redirect behavior for every request to this bucket's website endpoint. If this element is present, no other siblings are allowed.
Type: Container
Ancestors: WebsiteConfiguration
http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTwebsite.html
finally i got the solution by this, it works
$subdomain = 'test.example.com';
$protocol = 'https';
$redirectURL = 'www.somedomain.com/redirect?someparam';
$bucketID = $s3->createBucket(['Bucket' => $bucket ]);
$arg = array(
'Bucket' => $bucket,
'WebsiteConfiguration' => array(
'RedirectAllRequestsTo' => array('HostName' => $redirectURL, 'Protocol'=>$protocol),
),
);
$result = $s3->putBucketWebsite($arg);
Related
I am experimenting with WriteRequestBatch from AWS SDK for Dynamodb. Below is my code. Everything works except the WriteRequestBatch part. I have no clue why, and was wondering if the community could help me out here. What might I be doing wrong? I have tried googling and searching here and found only 8 other questions that could be related but unfortunately were of no help.
This is where I started from.
$ddb_client = DynamoDbClient::factory(array(
'region' => 'us-east-1',
'key' => 'my_key',
'secret' => 'my_secret'
));
$ddb_client->createTable(array(
'TableName' => 'my_table',
'AttributeDefinitions' => array(
array(
'AttributeName' => 'id',
'AttributeType' => 'S'
),
array(
'AttributeName' => 'ns',
'AttributeType' => 'S'
)
),
'KeySchema' => array(
array(
'AttributeName' => 'id',
'KeyType' => 'HASH'
),
array(
'AttributeName' => 'ns',
'KeyType' => 'RANGE'
)
),
'ProvisionedThroughput' => array(
'ReadCapacityUnits' => 10,
'WriteCapacityUnits' => 10
)
));
$response = $ddb_client->putItem(array(
"TableName" => "my_table",
"Item" => array(
"id" => array("S" => "exp_id"),
"ns" => array("S" => "exp_ns"),
"version" => array("N" => "0"),
),
));
$item = $response['Item'];
$item['version']['N'] = '1';
$put_batch = WriteRequestBatch::factory($ddb_client);
$put_request = new PutRequest(
array(
"Item" => $item,
"Expected" => array(
"version" => array(
"ComparisonOperator" => "EQ",
"AttributeValueList" => array(
array("N" => "0")
)
),
),
),
"my_table"
);
$putBatch->add($put_request);
$putBatch->flush();
This works instead of WriteRequestBatch. I will just have to manage batches to put myself than use WriteRequestBatch doing it for me:
$response = $ddb_client->batchWriteItem(array(
"RequestItems" => array(
"my_table" => array(
array(
"PutRequest" => array(
"Item" => $item,
"Expected" => array(
"version" => array(
"ComparisonOperator" => "EQ",
"AttributeValueList" => array(
array("S" => "0")
)
),
),
)
)
)
)
));
The answer by Geek Stocks is incomplete, but still helpful. One thing you can do handle the asynchronous aspects of the CreateTable operation is to use a Waiter:
$ddb_client->createTable(array('TableName' => 'my_table', ... ));
$ddb_client->waitUntil('TableExists', array('TableName' => 'my_table'));
However, there is also a problem with how you are using the WriteRequestBatch class. When you create a PutRequest, you must pass in the item, not a whole set of PutItem parameters. The WriteRequestBatch is an abstraction over DynamoDB's BatchWriteItem operation, which does not allow things like the Expected parameter. If you want to do that, then you need to use individual PutItem/UpdateItem/DeleteItem requests.
Here is a modified version of your usage of WriteRequestBatch that is correct:
$putBatch = WriteRequestBatch::factory($ddb_client);
$putBatch->add(new PutRequest($item, 'my_table'));
// ADD MORE...
// ...
// ...
$putBatch->flush();
Here is another example of using the WriteRequestBatch from the SDK's User Guide.
EDIT: One more complete example that works that I just tested, that shows the difference between versions prior to 2.7.0 and afterwards
use Aws\DynamoDb\DynamoDbClient;
use Aws\DynamoDb\Model\BatchRequest\WriteRequestBatch;
use Aws\DynamoDb\Model\BatchRequest\PutRequest;
use Aws\DynamoDb\Model\Item;
$client = DynamoDbClient::factory([/* ... */]);
$batch = WriteRequestBatch::factory($client);
for ($i = 1; $i <= 55; $i++) {
// FOR ANY SDK VERSION
// (NOTE: Does not support new M, L, BOOL, and NULL types)
$item = Item::fromArray(['id' => $i, 'data' => "foo{$i}"]);
// FOR SDK >= 2.7
$item = ['id' => ['N' => $i], 'data' => ['S' => "foo{$i}"]];
$batch->add(new PutRequest($item, 'my-table'));
}
$batch->flush();
Because you currently do not have any "try / catch" error handling around your code you are likely not getting good information on your error.
I placed try/catch blocks on your code and found that the table creates just fine but that the call to putItem fails for the following reason: Requested resource not found
When you create a table it is NOT immediately available. You have to pause until it becomes available. This paragraph of the AWS docs explains this nicely:
CreateTable is an asynchronous operation. Upon receiving a CreateTable request, DynamoDB immediately returns a response with a TableStatus of CREATING . After the table is created, DynamoDB sets the TableStatus to ACTIVE . You can perform read and write operations only on an ACTIVE table. You can use the DescribeTable API to check the table status.
Once you add the call to DescribeTable like it shows, you should be good.
Below is some code of my controller (dont worry, de keys are fake). Im using the ZendService\Twitter\Twitter module. Almost everything is working only the last error is a bit strange and i can not figure it out:
Unable to enable crypto on TCP connection api.twitter.com: make sure the "sslcafile" or "sslcapath" option are properly set for the environment.
As you can see i the code below of my controller, you can see that both the Verify of Peer and Host are set to false. The adapter is already set to Curl instead of HTTP.
<?php
namespace Twitter\Controller;
use QDCore\Controller\AbstractController;
use Zend\Mvc\MvcEvent;
use Zend\View\Model\JsonModel;
use ZendService\Twitter\Twitter;
class GetController extends AbstractController
{
protected $instance;
public function onDispatch(MvcEvent $e)
{
$config = array(
'access_token' => array(
'token' => '1024003resagsDQGyVC5YZ23423PpBNOwefS',
'secret' => 'oES8Jergewagewahsh2hTqrYGDJo',
),
'oauth_options' => array(
'consumerKey' => 'QY360Nersehr234gg4aV2pw',
'consumerSecret' => 'eEfgdagewa0Hkt4z6nCqHPY1M4wwuubY',
),
'username' => 'myusername',
'http_client_options' => array(
'adapter' => 'Zend\Http\Client\Adapter\Curl',
'curloptions' => array(
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_SSL_VERIFYPEER => false,
),
),
);
$this->instance = new Twitter($config);
return parent::onDispatch($e);
}
public function indexAction()
{
$result = new JsonModel(array('message' => 'No valid function call made'));
return $result;
}
public function usertimelineAction()
{
$options = array(
'user_id' => 'myaccountname',
'count' => 30,
);
$twitter = new Twitter($options);
$response = $twitter->statuses->userTimeline();
var_dump($response);
die;
return new JsonModel($response);
}
}
Hope that someone has an idea on how to fix it. My main domain is not running on SSL and is not going to be.
Thanks
NEVER set verify host or peer verification to false, unless you know what you are doing!
You have to point curl to your certification bundle. For Linux (Debian based systems) that is etc/ssl/certs. You could set that as "sslcapath" variable:
'http_client_options' => array(
'adapter' => 'Zend\Http\Client\Adapter\Curl',
'curloptions' => array(
'sslcapath' => '/etc/ssl/certs',
),
),
Because the path varies between systems, it's good to have it as an option set in your config/autoload/global.php file which users could change with a local.php configuration. In your config:
'http_client' => array(
'options' => array(
'sslcapath' => '/etc/ssl/certs',
),
),
Then your code becomes:
public function onDispatch(MvcEvent $e)
{
$app = $e->getApplication();
$sm = $app->getServiceManager();
$cnf = $sm->get('Config');
$config = array(
'access_token' => array(
'token' => '1024003resagsDQGyVC5YZ23423PpBNOwefS',
'secret' => 'oES8Jergewagewahsh2hTqrYGDJo',
),
'oauth_options' => array(
'consumerKey' => 'QY360Nersehr234gg4aV2pw',
'consumerSecret' => 'eEfgdagewa0Hkt4z6nCqHPY1M4wwuubY',
),
'username' => 'myusername',
'http_client_options' => array(
'adapter' => 'Zend\Http\Client\Adapter\Curl',
'curloptions' => $cnf['http_client']['options'],
),
);
$this->instance = new Twitter($config);
return parent::onDispatch($e);
}
I had the same exact problem and found this on Google. I understood I should either disable CURLOPT_SSL_VERIFYHOST and CURLOPT_SSL_VERIFYPEER or specify the correct path to the local certificates, but didn't know how to do that.
This answer has helped me a lot:
$config = array(
'callbackUrl' => 'http://example.com/callback.php',
'siteUrl' => 'http://twitter.com/oauth',
'consumerKey' => 'myConsumerKey',
'consumerSecret' => 'myConsumerSecret'
);
$consumer = new ZendOAuth\Consumer($config);
// this is the key:
$adapter = new \Zend\Http\Client\Adapter\Curl();
$adapter = $adapter->setCurlOption(CURLOPT_SSL_VERIFYHOST, false);
$adapter = $adapter->setCurlOption(CURLOPT_SSL_VERIFYPEER, false);
$httpClient = $consumer->getHttpClient();
$httpClient->setAdapter($adapter);
// now finally fetch a request token
$token = $consumer->getRequestToken();
I'm using the latest version (2) of SDK for php. Below is a snippet of code for assigning a name tag to existing instance:
try {
$result = $ec2->createTags(array(
'Resources' => array($instanceid),
'Tags' => array(
'Name' => 'PWC_cwc'),
));
} catch (Exception $e) {
die("Failed to create tag name: ".$e."<br>");
}
Output:
Failed to create tag name: exception 'Guzzle\Service\Exception\ValidationException' with message 'Validation errors: [Tags][Name][Tag] must be of type object' in /Users/harry/Documents/workspace/BigData/vendor/guzzle/guzzle/src/Guzzle/Service/Command/AbstractCommand.php:394 Stack trace: #0
I'm guessing something is wrong with the way I pass the argument, but just couldn't figure out the correct way of doing this
The API link for createTags method is here: http://docs.aws.amazon.com/aws-sdk-php-2/latest/class-Aws.Ec2.Ec2Client.html#_createTags
You have to specify the 'Key' and 'Value' of each tag.
$args = array(
'DryRun' => False,
'Resources' => array($resource),
'Tags' => array(
array(
'Key' => 'firstkey',
'Value' => $firstkeyvalue),
array(
'Key' => 'secondkey',
'Value' => $secondkeyvalue),
array(
'Key' => 'thirdkey',
'Value' => $thirdkeyvalue)
));
$response = $ec2->createTags($args);
Try this:
$result = $ec2->createTags(array(
'Resources' => array($instanceid),
'Tags' => array(
'Tag' => array(
'Key' => '<key>',
'Value' => '<value>'
)
)
));
You need to have an array of 'Tag' inside the 'Tags' array.
I have a WCF web service with a Login operation taking a company name, user name and password as the three parameters. I am trying to create a PHP client app to communicate with this service. No matter what I pass to the Login operation I get the following error:
OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name 'Login' and namespace ''. Found node type 'Element' with name 'parameters' and namespace ''
My client app:
<?php
try
{
$client = new SoapClient("https://somewhere.com/DataServiceRxPublic.svc?wsdl");
//$params = array(
// 'parameters' => array(
// 'Param' => array(
// array('Name' => 'loginCompany', 'Value' => 'XXX'),
// array('Name' => 'loginId', 'Value' => 'XXX'),
// array('Name' => 'loginPwd', 'Value' => 'XXX')
//)));
//$params = array(
// 'Login' => array(
// array('Name' => 'loginCompany', 'Value' => 'XXX'),
// array('Name' => 'loginId', 'Value' => 'XXX'),
// array('Name' => 'loginPwd', 'Value' => 'XXX')
//));
//$params = array(
// 'Login' => array(
// 'parameters' => array(
// array('Name' => 'loginCompany', 'Value' => 'XXX'),
// array('Name' => 'loginId', 'Value' => 'XXX'),
// array('Name' => 'loginPwd', 'Value' => 'XXX')
//)));
//$params = array(
// array('Name' => 'loginCompany', 'Value' => 'XXX'),
// array('Name' => 'loginId', 'Value' => 'XXX'),
// array('Name' => 'loginPwd', 'Value' => 'XXX')
//);
$params = array(
'loginCompany' => 'XXX',
'loginId' => 'XXX',
'loginPwd' => 'XXX'
);
$obj->loginCompany = 'XXX';
$obj->loginId = 'XXX';
$obj->loginPwd = 'XXX';
//$result = $client->Login($obj);
//$result = $client->Login($params);
}
catch (Exception $e)
{
print_r($e);
}
}
?>
$params being the different array permutations I've based off several different examples online.
Any help is appreciated.
The error message is telling you that there should have been something named "Login", but was named "parameters".
Go get SoapUI and with your WSDL follow the steps I described here to debug what you are actually sending. If you cannot compare what the service expects vs. what you are sending, this will be way too much trial-and-error.
If you need more external help, we'd need the WSDL resource - without it, nobody knows which request structure is expected.
Turns out I needed to extend the SOAPClient and override the __doRequest() method to replace the mismatched soap headers.
I managed to fix this error by modifying service namespace on server side.
[ServiceContract(Name="Service", Namespace = "https://sample.eu")]
Namespace was empty before.
When including the header options to copy_object, the headers DO NOT get updated.
Headers don't get updated until I make a separate call using update_object. I hope I'm doing something wrong, but I've tested this 4-5 different ways even getting into the sdk code to poke around.
Is this a bug?
I'm using the latest 1.4.3 SDK
Here is my call:
$amazonS3->copy_object(
array( //Source
'bucket' => SOURCE_BUCKET,
'filename' => $source_file
),
array( //Target
'bucket' => VIDEO_BUCKET,
'filename' => $dest_file,
),
array( //Options
'acl' => AmazonS3::ACL_PRIVATE,
'headers' => array(
'Content-Type' => 'application/octet-stream',
'Content-Disposition' => 'attachment'
)
);
I had this problem myself and solved it iamdev. After about a half-day of going insane, I started looking at the actual API rather than just trying to use it.
In sdk.class.php, on line 1690, you'll see the following:
if (isset($opt['metadataDirective']))
$opt['headers']['x-amz-metadata-directive'] = $opt['metadataDirective'];
unset($opt['metadataDirective']);
}
This means if you are not copying an object to itself, it will not replace the key, hence not update it.
What worked for me was explicitly setting the metadataDirective in my opts in my call, so:
$amazonS3->copy_object(
array( //Source
'bucket' => SOURCE_BUCKET,
'filename' => $source_file
),
array( //Target
'bucket' => VIDEO_BUCKET,
'filename' => $dest_file,
),
array( //Options
'acl' => AmazonS3::ACL_PRIVATE,
'headers' => array(
'Content-Type' => 'application/octet-stream',
'Content-Disposition' => 'attachment'
),
'metadataDirective' => 'REPLACE',
);
Hope this works for you, although this is an old post and you've probably found a workaround.
Best,
HG