Amazon s3 | MalformedXML Status Code: 400 - php

I am receiving the following error when using the putObject() function of the aws-sdk for php:
PHP Fatal error: Uncaught Aws\S3\Exception\MalformedXMLException: AWS Error Code: MalformedXML,
Status Code: 400, AWS Request ID: 7E36EB414B2A9436, AWS Error Type: client,
AWS Error Message: The XML you provided was not well-formed or did not validate against our published schema,
User-Agent: aws-sdk-php2/2.5.4 Guzzle/3.8.1 curl/7.26.0 PHP/5.5.19-1~dotdeb.1
thrown in /sites/sitename/vendor/aws/aws-sdk-php/src/Aws/Common/Exception/NamespaceExceptionFactory.php on line 91
Even though I am receiving the error, the process continues to run successfully and the files are moved to s3. I know this more than likely has something to do with the parameters that I am including in the function but I'm not sure what else needs to be there as the aws api for php only shows the 'bucket' and 'key' parameters as being required. My configuration is as follows:
$config = array();
$config['Bucket'] = IMAGE_BUCKET;
$config['Key'] = $imageName;
$config['SourceFile'] = $sourceImageDir;
$config['ACL'] = 'public-read';
$config['ContentLength'] = filesize($sourceImageDir);
$response = $s3->putObject($config);
If I knew what format the service was requiring I'm sure I could grab the request that I'm sending after it's turned into an xml string and compare it with that, but I can't seem to find it. If it exists. I would assume there is such a thing?

Thanks to the comment from Michael I was able to track the issue down further. It turns out that the issue was actually coming from a call to deleteObjects(). These commands are being executed within a shell script on the cli and it turns out there was another call preceeding the last call to putObject(). It was trying to send empty arrays to the s3 service...which would obviously return the given MalformedXML Status code.

Related

Facebook Business SDK for PHP - Failed sending HTTP request: Header overflow

I am trying to gather a year's worth of data for a select ad account but I get the following exception:
FacebookAds\Exception\Exception
Failed sending HTTP request: Header overflow
The exception happens at the following line of code:
$adData = [];
foreach ($fbadaccount->getAds($adFields, $adParams) as $object) {
$adData[] = $object->getData();
}
This code works perfectly fine for smaller time frames.
I understand it is attempting to get a lot of data but I'm trying to find a solution.
Could this potentially be environment-related? i.e. nginx
The "Header overflow" error occurs when the HTTP request header is too large.
Perhaps because of the cookies being sent.

Unable to CloudFront Create Invalidation [ AWS PHP SDK 3.X ]

Unable to understand what mistake i doing while invalidating Cloud front resource using AWS PHP SDK Version 3,
My Code
public function cfCreateInvalidation()
{
$item = "http://mycdn.domain.com/resourcepath?queryString" ;
try {
$data = [
'DistributionId' => 'ActualValueHereID',
'InvalidationBatch' => [
'CallerReference' => '16 Char Random String',
'Paths' => [
'Items' => [$item],
'Quantity' => 1,
],
]
];
$result = $this->cloudFrontConnection->createInvalidation($data);
}catch (\Exception $exception) {
echo json_encode($exception->getMessage());
}
}
Every time I am getting:
Error executing "CreateInvalidation" on "https://cloudfront.amazonaws.com/2017-03-25/distribution/AAABBBBCCCCD/invalidation";
AWS HTTP error: Client error: `POST https://cloudfront.amazonaws.com/2017-03-25/distribution/AAABBBBCCCCD/invalidation` resulted in a `400 Bad Request` response:
<?xml version="1.0"?>
<ErrorResponse xmlns="http://cloudfront.amazonaws.com/doc/2017-03-25/"><Error><Type>Sender</Type>< (truncated...)
MalformedInput (client): Could not parse XML - <?xml version="1.0"?>
<ErrorResponse xmlns="http://cloudfront.amazonaws.com/doc/2017-03-25/"><Error><Type>Sender</Type><Code>MalformedInput</Code><Message>Could not parse XML</Message></Error><RequestId>ad9b467c-211e-11e8-ba32-45e52ff9e8b3</RequestId></ErrorResponse>
The error message suggests there may be other issues as well, but your $item expects a path, rather than a URL.
/resourcepath* is expected, here. All cached objects for the specified path will be invalidated, regardless of scheme, method, headers, or cookies that may also be part of the cache key.
The documentation seems ambiguous, but suggests that the * at the end is needed to catch query strings if your distribution is configured to cache on them. (The * matches 0 or more characters). There is no documented example of actually including the query string in the path you submit.
I've encountered the same problem with a Wordpress plugin that handles cleaning cache when updating published posts.
When calling createInvalidation($data) (the $data structure is the same in post question) I got that error
AWS HTTP error: Client error: POST
https://cloudfront.amazonaws.com/2017-10-30/distribution/E3QES3NJL8EBYN/invalidation
resulted in a 400 Bad Request
(that could only be retrieved on log error file while the page output was the generic one
"Access Denied"...)
Reading the CloudFront documentation I found out that the createInvalidation method has its asyncronous version that is:
createInvalidationAsync($data)
You can do this for every CloudFront method indeed as it is written in https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-cloudfront-2016-01-28.html (appending the Async word to the operation name)
With this one all is working properly and no error is retrieved because the system returns an "ok I'll do it soon later" response and all the process of publication post can be carried out with success.
I know this is a workaround because this doesn't eliminate the root cause of the problem but it is working for me and I hope this could help anyone.

Invoking WCF service with PHP (with federated security)

I’m trying to invoke a WCF service (.NET) from PHP. It’s a little more complicated than just using a SoapClient since the service uses a WS2007FederationHttpBinding to authenticate.
Here’s the code I’m using at the moment. I haven’t even added credentials as I’m not sure how, but regardless, I’m not even at the point where I’m getting access denied errors.
$wsdl = "https://slc.centershift.com/sandbox40/StoreService.svc?wsdl";
$client = new SoapClient($wsdl,array(
//'soap_version'=>SOAP_1_2 // default 1.1, but this gives 'Uncaught SoapFault exception: [HTTP] Error Fetching http headers'
));
$params = array();
$params['SiteID'] = 123;
$params['GetPromoData'] = false;
$ret = $client->GetSiteUnitData(array('GetSiteUnitData_Request'=>$params));
print_r($ret);
Which WSDL should I be pointing to?
https://slc.centershift.com/Sandbox40/StoreService.svc?wsdl
Seems to be very short, but includes a reference to (note the wsdl0) https://slc.centershift.com/Sandbox40/StoreService.svc?wsdl=wsdl0
https://slc.centershift.com/Sandbox40/StoreService.svc?singleWsdl
Seems to have everything in it.
Do I need to specify SOAP 1.2? When I do, I get a connection timeout ([HTTP] Error Fetching http headers). When I don’t, the default of SOAP 1.1 is used and I get a [HTTP] Cannot process the message because the content type 'text/xml; charset=utf-8' was not the expected type 'application/soap+xml; charset=utf-8'. Is this because I’m not authenticated yet, or because I’m using the wrong SOAP version?
How to authenticate in PHP? Here’s the corresponding .NET/C# code. Do I need to somehow put these as SOAP headers? Or am I thinking about it all wrong, and I need to do some kind of authentication before I even call the method (from what I read, I’m supposed to get a token back and then use it for all future method calls – I think I see an example of this in an answer here on Stack Overflow.
If I call $client->__getFunctions(), using either WSDL and either SOAP version, I’m getting a valid list of all functions, so I assume either of these is fine and my real issue is the authentication.
Other programmers I’ve talked to had spent time trying to get this to work, but gave up and instead implemented a proxy in .NET. They pass their parameters from PHP to their own unsecured .NET service, which in turn calls this secure service. It works, but seems crazily inefficient to me, and counter-productive, as the purpose of WCF is to support all types of clients (even non-HTTP ones!).
I’ve read How to: Create a WSFederationHttpBinding on MSDN, but it didn’t help.
You can use this URL for WSDL https://slc.centershift.com/Sandbox40/StoreService.svc?singleWsdl. This WSDL has all definitions.
You have to use 1.2 because this webservice works with SOAP 1.2 version. I tried it with 1.1 and 1.2 and both of them gived error. 1.1 is version error, 1.2 is timeout error. I think there is an error at this test server. I used it with svcutil to generate code but it gived error too. Normaly it should get information and generate the code example to call service.
Normally you can add authenticate parameters with SoapHeader or directly add to options in SoapClient consruct (if service authentication is basic authentication). I write below code according to your screenshot. But it gives timeout after long wait.
$wsdl = "https://slc.centershift.com/sandbox40/StoreService.svc?wsdl";
$client = new SoapClient($wsdl,array('trace' => 1,'soap_version' => SOAP_1_2));
$security = array(
'UserName' => array(
'UserName'=>'TestUser',
'Password'=>'TestPassword',
'SupportInteractive'=>false
)
);
$header = new SoapHeader('ChannelFactory','Credentials',$security, false);
$client->__setSoapHeaders($header);
$params = array();
$params['SiteID'] = 100000000;
$params['Channel'] = 999;
try {
$ret = $client->GetSiteUnitData($params);
print_r($ret);
}catch(Exception $e){
echo $e->getMessage();
}
__getFunctions works, because it prints functions defined in WSDL. There is no problem with getting WSDL information at first call. But real problem is communication. PHP gets WSDL, generates required SOAP request then sends to server, but server is not responding correctly. SOAP server always gives a response even if parameters or request body are not correct.
You should communicate with service provider, I think they can give clear answer to your questions.
Having worked with consuming .NET WS from PHP before I believe you would need to create objects from classes in PHP that matches the names that .NET is expecting. The WSDL should tell you the types it is expecting. I hope this assist with your path forward!
If the SOAP call works from a C# application, you could use Wireshark (with the filter ip.dst == 204.246.130.80) to view the actual request being made and then construct a similar request from php.
Check this answer to see how you can do a custom SOAP call.
There's also the option of doing raw curl requests, since it might be easier to build your xml body, but then you would have to parse the response yourself with simplexml.

twitter api returning xml on one server, empty string on another

I have a php Twitter app which lets you mark tweets as favorite.
I'm doing something like this:
$fav = $twitter->createFavorite("xml", $get_id);//handles api call (using curl)
$fav_result = new SimpleXMLElement($fav);
On my localhost and on one online server all goes well: the tweet is marked as favorite, and the api call returns xml. On another online server, the tweet is also marked as favorite, but php gives an error: Fatal error: Uncaught exception 'Exception' with message 'String could not be parsed as XML'
On the second server, I seem to get an empty string as return value. When I look at the http status codes, when all is well I get a 200, but when things go wrong I get a status code of 0.
When I check the curl_error it says "Failed to open/read local data from file/application"
I think it has to do something with my server configuration. Does anyone have an idea what might be causing this?
I found the solution here: http://www.milk-hub.net/blog/2008/08/26/curl_error_26
Since no separate postvars are sent, you have to explicitly set the to an empty string:
curl_setopt($curl_handle, CURLOPT_POSTFIELDS, '');

Does NuSoap have to be configured a certain way when calling from WCF?

I'm trying to call a php webservice using WCF. I googled some public php services to see if I could replicate the error I was receiving and I created 2 different unit tests to demonstrate.
The test that failed I get the following error:
System.ServiceModel.ProtocolException: The content type text/xml; charset=ISO-8859-1 of the response message does not match the content type of the binding (text/xml; charset=utf-8). If using a custom encoder, be sure that the IsContentTypeSupported method is implemented properly. The first 601 bytes of the response were: '
Here are the unit tests:
[TestMethod]
public void WCF_Call_To_SiteInspect() {
//This service doesn't work. It gets the same communication error as our own servers
var soapClien = new SiteInspect.SiteInspectPortClient();
var response = soapClien.doSiteInspect("Any", "Any", "www.google.com");
Assert.IsTrue(response.serverTime.Length > 0);
}
[TestMethod]
public void WCF_Call_To_FinnService() {
//This service works.... in looking at the wsdl it appears that it references a separate wsdl file. Is this the reason?
var soapClient = new NuSoapFinnService.finnwordsPortTypeClient();
var finnLyric = soapClient.getRandomNeilFinnLyric("text");
Assert.IsTrue(finnLyric.Length > 0);
}
The test case on the bottom (the Finn service) passed at the following URL: http://www.nickhodge.com/nhodge/finnwords/finnwords.wsdl
The first test case failed given the following URL: http://www.flash-db.com/services/ws/siteInspect.wsdl
The only difference I can see in the wsdl is the Finn service references an extraneous file. xmlns:tns="http://www.nickhodge.com/nhodge/finnwords/finnwords.wsdl . Is this bug with WCF that expects the wsdl in a specific format?
Make sure to set the UTF-8 encoding using soap_defencoding in the PHP code.
If you want some more related information, see this blog post.

Categories