My Guzzle POST request to https://api.scarif.dev/auth gives back a 404, while the page exists through Postman, or browser, or javascript. It should return a 200 with a 401 message, but Guzzle gives back a 404. In both POST and GET mode that is.
I've tried multiple Client setups, including different headers and disabling SSL verification, but without any success. Now I've copied the exact same headers that made it work in postman, but still no success.
I've been searching through google and stackoverflow, but couldn't find an answer that fixed my problem.
Request in PHP:
<?php
$client = new Client([
'header' => [
'Accept' => 'application/json',
'Content-Type' => 'application/x-www-form-urlencoded'
],
'verify' => false
]);
$response = $client->request('POST', 'https://api.scarif.dev/auth', [
'form_params' => []
]);
echo $response->getBody()->getContents();
?>
Expected result:
{
"detail": "https://login.scarif.dev",
"status": 401,
"title": "Unauthorized",
"type": "http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html"
}
Actual result:
Fatal error: Uncaught GuzzleHttp\Exception\ClientException: Client
error: POST https://api.scarif.dev/auth resulted in a 404 Not
Found response:
404 Not Found Not Found
(truncated...) in
/home/admin/domains/login.scarif.dev/framework/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php:113
Stack trace: #0
/home/admin/domains/login.scarif.dev/framework/vendor/guzzlehttp/guzzle/src/Middleware.php(66):
GuzzleHttp\Exception\RequestException::create(Object(GuzzleHttp\Psr7\Request),
Object(GuzzleHttp\Psr7\Response)) #1
/home/admin/domains/login.scarif.dev/framework/vendor/guzzlehttp/promises/src/Promise.php(203):
GuzzleHttp\Middleware::GuzzleHttp{closure}(Object(GuzzleHttp\Psr7\Response))
2 /home/admin/domains/login.scarif.dev/framework/vendor/guzzlehttp/promises/src/Promise.php(156):
GuzzleHttp\Promise\Promise::callHandler(1,
Object(GuzzleHttp\Psr7\Response), Array) #3
/home/admin/domains/login.scarif.dev/framework/ven in
/home/admin/domains/login.scarif.dev/framework/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php
on line 113
API endpoint controller:
<?php
namespace Controller;
use Core\Config;
use Core\Request;
use Core\Response;
use Model\Token;
use Model\User;
use MongoDB\BSON\UTCDateTime;
class AuthController extends Controller
{
public function view(User $user, Token $token)
{
extract(Request::getPostData());
if (isset($access_token) && !empty($access_token)) {
$_token = $token->getTokenByToken($access_token);
if (
$_token['type'] !== Token::TYPE_ACCESS_TOKEN ||
$_token['expires_on'] <= new UTCDateTime()
) {
return $this->view->display('json', [
'payload' => Response::apiResponse(
$this->config->get('url.login'), 401
)
]);
}
$token->delete($_token['_id']);
$newToken = $token->create(Token::TYPE_ACCESS_TOKEN, $_token['user_id']);
return $this->view->display('json', [
'payload' => Response::apiResponse($newToken['token'])
]);
}
if (!isset($email) || !isset($password) || empty($email) || empty($password)) {
return $this->view->display('json', [
'payload' => Response::apiResponse(
$this->config->get('url.login'), 401
)
]);
}
if (!$user->checkCredentials($email, $password)) {
return $this->view->display('json', [
'payload' => Response::apiResponse(
"The email address or password you've entered is invalid. Please check your entry and try again.",
422
)
]);
}
$user = $user->getUserByEmail($email);
$token = $token->create(Token::TYPE_ACCESS_TOKEN, $user['_id']);
return $this->view->display('json', [
'payload' => Response::apiResponse($token['token'])
]);
}
}
It seems like the issue is coming from the API you are consuming. When using your code with a different url it works just fine:
$client = new Client([
'header' => [
'Accept' => 'application/json',
'Content-Type' => 'application/x-www-form-urlencoded'
],
'verify' => false
]);
$response = $client->request('POST', 'https://jsonplaceholder.typicode.com/posts', [
'form_params' => []
]);
echo $response->getBody()->getContents();
Could you show the code for the API endpoints?
I had the same issue and was looking for solutions until I landed here. Didn't get any help online though and solutions of other people didn't work for me but later I solved myself through extensive debugging and I am sharing the solution in a hope it might help someone else in the future.
Scenario: In my case I had an API gateway and client (Postman in my case) was making request to the API gateway and gateway in turn was making request to a microservice using Guzzle 7 in Laravel 8. I used to pass all headers I received from the client to microservice as is and that was causing 404 error. When I changed that and passed only my own headers in the request to the microservice, there was light and 404 was gone.
These were default headers of Postman and I was passing in the request as is:
{
"authorization": [
"Bearer eyJ0eXAiOiJKV1 .."
],
"user-agent": [
"PostmanRuntime/7.29.0"
],
"accept": [
"*/*"
],
"postman-token": [
"ca180f3a-ec65-4212-bd9f-dc294846dc65"
],
"host": [
"sagateway.com"
],
"accept-encoding": [
"gzip, deflate, br"
],
"connection": [
"keep-alive"
]
}
I removed all of it and only passed one thing in the header:
['Authorization' => "<Key Here>"]
It then worked fine and I took a breath of relief after a few days of continuous googling.
Related
I am trying to disable a webhook of Paymongo via the web console, but it seems I can not disable the webhook. When I do so, the interface shows the error like so:
{
"errors": [
{
"code": "resource_processing_state",
"detail": "Webhook with id hook_L0r3mIp5umD0L0r5itAm3t is still being processed."
}
]
}
It also has a 400 HTTP status code and its PHP code look like so:
<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'https://api.paymongo.com/v1/webhooks/hook_L0r3mIp5umD0L0r5itAm3t/disable', [
'headers' => [
'accept' => 'application/json',
'authorization' => 'Basic someBase64encodedStringOfAKey',
],
]);
echo $response->getBody();
Note: The shown codes above don't contain the exact credentials. I edited these before posting here for privacy reasons.
What does it mean by "Webhook with id hook_L0r3mIp5umD0L0r5itAm3t is still being processed."?
I'm trying to create a google chat space via making a post request to https://chat.googleapis.com/v1/spaces with Guzzle.
$scopes = [
'https://www.googleapis.com/auth/chat.spaces.create',
'https://www.googleapis.com/auth/chat.bot'
];
// create middleware
$middleware = ApplicationDefaultCredentials::getMiddleware($scopes);
$stack = HandlerStack::create();
$stack->push($middleware);
// create the HTTP client
$client = new Client([
'headers' => ['Content-Type' => 'application/json'],
'handler' => $stack,
'base_uri' => 'https://www.googleapis.com',
'auth' => 'google_auth' // authorize all requests
]);
// make the request
$response = $client->post( 'https://chat.googleapis.com/v1/spaces', [
RequestOptions::JSON => [
'name' => 'ABCDEFG',
'spaceType' => 'DIRECT_MESSAGE',
'threaded' => false,
'displayName' => 'TestSpace'
],
]);
In response I'm getting:
Client error: `POST https://chat.googleapis.com/v1/spaces` resulted in a `404 Not Found` response:
{
"error": {
"code": 404,
"message": "Method not found.",
"status": "NOT_FOUND"
}
}
But if I change the body of the request and add some new invalid fields like this:
$response = $client->post( 'https://chat.googleapis.com/v1/spaces', [
RequestOptions::JSON => [
'name' => 'ABCDEFG',
'spaceType' => 'DIRECT_MESSAGE',
'threaded' => false,
'displayName' => 'TestSpace',
'foo' => 'bar', //added invalid field
],
]);
I'm getting the next response:
Client error: `POST https://chat.googleapis.com/v1/spaces` resulted in a `400 Bad Request` response:
{
"error": {
"code": 400,
"message": "Invalid JSON payload received. Unknown name \"foo\" at 'space': Cannot find field.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "space",
"description": "Invalid JSON payload received. Unknown name \"foo\" at 'space': Cannot find field."
}
]
}
]
}
}
docs:
https://developers.google.com/chat/api/reference/rest/v1/spaces/create
What’s wrong with my original request?
Thanks.
The spaces.create documentation explains this at the top of the page:
Developer Preview: Available as part of the Google Workspace Developer Preview Program, which grants early access to certain features.
This means that the method is only available for users in Google's Developer Preview Program, which seems kind of like a closed beta for some developer features. The link above has a form that you can fill out to join this program, though do note that you also need to be part of the Google Cloud Partner Advantage program to apply.
In short, the method was released not long ago, and is not currently available for everyone. There's also an official blog post explaining this. It may become public in the future, so you'll have to either wait or fill out the applications to become a partner and then join the developer preview.
If you happen to be part of the program already and are still having issues you probably won't find answers among us commoners. You'd want to check out the Partner Advantage support to make sure that the features were enabled for your domain. The developer program documentation above also has a link to the issue tracker to send feedback about this API. You'll only be able to do this as a member, of course.
I was working on the Quickbooks API for one of my projects. I'm getting the following error:
GuzzleHttp\Exception\ClientException Client error: POST https://sandbox-quickbooks.api.intuit.com//*Private Info */ resulted in a 400 Bad Request response: {"Fault":{"Error":[{"Message":"Request has invalid or unsupported property","Detail":"Property Name:Unrecognized field \ (truncated...)
The Code:
I have no idea what it is saying to me to fix it. Can anyone help me with this?
Please find the updated code
if(!$buyer->details->quickbooks_id){
$customer = $http->post(
// Sandbox API hidden for security reason
[
'headers' => [
'Accept'=> 'application/json',
'Content-type'=> 'application/json',
'Authorization'=> 'Bearer '.$oauth['access_token']
],
'body' => json_encode(
[
'PrimaryEmailAddr' => [
'Address' => $buyer->email
],
'DisplayName' => $buyer->first_name.' '.$buyer->last_name.' - '.$buyer->details->business_name,
'PrimaryPhone'=>[
'FreeFormNumber'=> $buyer->phone
],
'CompanyName'=>$buyer->details->business_name,
'GivenName'=>$buyer->first_name,
'FamilyName'=>$buyer->last_name,
'BillAddr'=> [
"CountrySubDivisionCode" => $buyer->details->state,
"City" => $buyer->details->city,
"PostalCode" => $buyer->details->zip,
"Line1" => $buyer->details->address,
"Country" => $buyer->details->country
]
])
]
);
$customer = json_decode((string)$customer->getBody(), true);
$buyer->details->quickbooks_id = $customer['Customer']['Id'];
$buyer->details->save();
}
dd($buyer, $buyer->details, $buyer->details->quickbooks_id);
Probably the issue is with the request body. I had the same issue with the data i pass.
I need to integrate an API into my app.
The docs say:
HTTP POST
The following is a sample HTTP POST request and response. The placeholders shown need to be replaced with actual values.
POST /partnerhubwebservice.asmx/Authorise HTTP/1.1
Host: stage.example.co.uk
Content-Type: application/x-www-form-urlencoded
Content-Length: length
username=string&password=string
and response is:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: length
<?xml version="1.0" encoding="utf-8"?>
<AuthorisationResult xmlns="http://webservice.example.co.uk/">
<Token>string</Token>
</AuthorisationResult>
Reading the docs I create this function in Laravel Controller:
public function testRld() {
$client = new GuzzleHttp\Client();
try {
$res = $client->post('http://stage.example.co.uk/partnerhubwebservice.asmx/Authorise', [
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
],
'x-www-form-urlencoded' => [
'Username' => 'MMM_bookings',
'Password' => 'passwordaaaa',
]
]);
return $res;
}
catch (GuzzleHttp\Exception\ClientException $e) {
$response = $e->getResponse();
$result = json_decode($response->getBody()->getContents());
return response()->json(['data' => $result]);
}
}
but I got a message:
ServerException in RequestException.php line 111: Server error: POST
http://stage.example.co.uk/partnerhubwebservice.asmx/Authorise
resulted in a 500 Internal Server Error response: Missing parameter:
username.
When I try this at POSTMAN app everything is fine and there I get response ike:
<?xml version="1.0" encoding="utf-8"?>
<AuthorisationResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://webservice.example.co.uk/">
<RequestSuccessful>true</RequestSuccessful>
<ErrorMessage />
<Token>27d67d31-999-44e0-9851-d6f427fd2181</Token>
</AuthorisationResult>
Please help me to solve this problem? What is wrong with my code? WHy I got the error , and POSTMAN request works fine ...
Try sending username and password inside of a body as body or json, instead of as application/x-www-form-urlencoded, like so:
$res = $client->post('http://stage.example.co.uk/partnerhubwebservice.asmx/Authorise', [
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
],
'json' => [
'username' => 'MMM_bookings',
'password' => 'passwordaaaa',
]
]);
or
$res = $client->post('http://stage.example.co.uk/partnerhubwebservice.asmx/Authorise', [
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
],
'body' => [
'username' => 'MMM_bookings',
'password' => 'passwordaaaa',
]
]);
Use form_params:
$client->request('POST', 'http://stage.example.co.uk/partnerhubwebservice.asmx/Authorise', [
'headers' => [
'Content-Type' => 'application/x-www-form-urlencoded',
],
'form_params' => [
'username' => 'MMM_bookings',
'password' => 'password'
]
]);
The PSR-7 standard specifies interfaces for HTTP messages, including requests and responses. If you would like to obtain an instance of a PSR-7 request instead of a Laravel request, you will first need to install a few libraries. Laravel uses the Symfony HTTP Message Bridge component to convert typical Laravel requests and responses into PSR-7 compatible implementations:
Install the necessary dependencies as well:
composer require symfony/psr-http-message-bridge
composer require zendframework/zend-diactoros
I am sending a POST request to the following resource and getting a 400. I understand what the error means, but still am unsure why I'm getting it when a GET request to the same resource works.
/lists/{list_id}/members
Here is a exerpt of the code:
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', // <-- Drop in a GET here and it works, other than it's not the behavior I need.
env('MAILCHIMP_API_URL') . 'lists/' . env('MAILCHIMP_LIST_KEY') . '/members',
[
'auth' => ['app', env('MAILCHIMP_API_KEY')],
'query' => [
'email_address' => 'donnie#test.com',
'email_type' => 'html',
'status' => 'subscribed',
]
]);
dd($response->getStatusCode());
Response
Client error: `POST https://XXXX.api.mailchimp.com/3.0/lists/XXXX/members?email_address=donnie%40test.com&email_type=html&status=subscribed`
resulted in a `400 Bad Request`
response: {
"type": "http://developer.mailchimp.com/documentation/mailchimp/guides/error-glossary/",
"title": "Invalid Resource",
"status": 400,
"detail": "The resource submitted could not be validated. For field-specific details, see the 'errors' array.",
"instance": "f32e7076-b970-4f5c-82c6-eec5875e83b4",
"errors": [{
"field": "",
"message": "Schema describes object, NULL found instead"
}]
}
You are sending a POST request with query parameters. You need to send JSON encoded body!
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', // <-- Drop in a GET here and it works, other than it's not the behavior I need.
env('MAILCHIMP_API_URL') . 'lists/' . env('MAILCHIMP_LIST_KEY') . '/members',
[
'auth' => ['app', env('MAILCHIMP_API_KEY')],
'json' => [
'email_address' => 'donnie#test.com',
'email_type' => 'html',
'status' => 'subscribed',
]
]);
dd($response->getStatusCode());