postmark-php
postmark-php copied to clipboard
InvalidArgumentException: Invalid resource type: boolean
I am occasionally seeing InvalidArgumentExceptions when sending emails. It appears that Postmark is passing bad values to Guzzle.
"InvalidArgumentException: Invalid resource type: boolean"
Here is my question on SO: http://stackoverflow.com/questions/33085043/postmark-guzzle-invalidargumentexception-invalid-resource-type-boolean
There is also an issue logged in the Guzzle project: https://github.com/guzzle/guzzle/issues/628
This turned out to be a character encoding issue on my end (see my SO answer).
Should the Postmark SDK check for such things that would prevent successful interaction with the API? Maybe thrown a character encoding exception?
If that would be helpful to others (it certainly would have saved me a number of hours), I'd be happy to code it up and submit a PR.
@karlwilbur Hi Karl, sorry for the confusion on this. I'd love to see an example of how this was fixed, it might be something we can integrate into the library. I would have also expected Guzzle to handle encoding to UTF-8, which is a requirement of JSON, but it sounds like that didn't happen.
No, Guzzle doesn't make any changes to the input.
If you follow the stack trace in my SO post, you see that the data in the $body
param to PostmarkClientBase::processRestRequest
just is pretty much just passed along the line. It gets passed in as the $options['json']
param to GuzzleHttp\Client::createRequest
(remember, I'm using the v5.3 client here: https://github.com/guzzle/guzzle/blob/5.3/src/Client.php). In there it hands off to GuzzleHttp\Message\MessageFactory::createRequest
which in turn hands it off to GuzzleHttp\Message\MessageFactory::applyOptions
where is it run through json_endode()
.
No change at all to my data that gets passed in ...nor is there any validation of my data. Which is fine. I can accept that it is totally up to me to validate my data. It was yet another time that PHP's poor handling of character encoding took away hours of my life.
My solution was pretty much just:
$html_body = utf8_encode($html_body);
$text_body = utf8_encode($text_body);
I think that maybe in Postmark\PostmarkClientBase::processRestRequest
we could do some validation for the json
params. We could change line 92 to be something like this:
$options['json'] = static::validateJsonParams($cleanParams);
Then create a new Postmark\PostmarkClientBase::validateJsonParams
which could be something like:
public static function validateJsonParams($params) {
$json = false;
try {
$json = json_encode($params);
if (!$json) {
$json_error_code = last_json_error();
switch ($json_error_code) {
case: JSON_ERROR_NONE
$json_error_message = "No error has occurred."
break;
case: JSON_ERROR_DEPTH
$json_error_message = "The maximum stack depth has been exceeded."
break;
case: JSON_ERROR_STATE_MISMATCH
$json_error_message = "Invalid or malformed JSON.";
break;
case: JSON_ERROR_CTRL_CHAR
$json_error_message = "Control character error, possibly incorrectly encoded.";
break;
case: JSON_ERROR_SYNTAX
$json_error_message = "Syntax error.";
break;
case: JSON_ERROR_UTF8
$json_error_message = "Malformed UTF-8 characters, possibly incorrectly encoded.";
break;
case: JSON_ERROR_RECURSION
$json_error_message = "One or more recursive references in the value to be encoded.";
break;
case: JSON_ERROR_INF_OR_NAN
$json_error_message = "One or more NAN or INF values in the value to be encoded.";
break;
case: JSON_ERROR_UNSUPPORTED_TYPE
$json_error_message = "A value of a type that cannot be encoded was given.";
break;
}
}
} catch (Exception $e) {
$json_error_code = $e->getCode();
$json_error_message = $e->getMessage();
}
if (!$json) {
$ex = new PostmarkException();
$ex->httpStatusCode = 400;
$ex->message = 'Bad Request: There appears to be something wrong with your data syntax.' .
'This error was "['.$json_error_code.'] '.$json_error_message.'".';
throw $ex;
}
return $params;
}