yii2 rest api exception handling - php

I am using yii2 rest api module in which controller class extends an ActiveController and i have a problem dealing with the error exception . i need a proper json response when HTTP status code that are used by the Yii REST framework like 500 , 400. If i try a wrong method call on access api it show a exception object
object(yii\web\NotFoundHttpException)#170 (8) { ["statusCode"]=> int(404)
In my config/main.php set the response
'response' => [
'class' => 'yii\web\Response',
'on beforeSend' => function ($event) {
$response = $event->sender;
if ($response->data !== null) {
$response->data = [
'success' => $response->isSuccessful,
'data' => $response->data,
];
$response->statusCode = 200;
}
},
]
It should display a msg like:
{
"status": 0,
"error_code": 400,
"message": "Bad request"
}
I have try to add the behaviour verbs in controller using this link : click here
My whole application is based on api so please help me for handling all kind of errors

Also depends on your server configs but usually you don't need any of that. this should be enough:
'response' => [
'format' => yii\web\Response::FORMAT_JSON,
'charset' => 'UTF-8',
],
Here is an output example using those configs: https://yii2-f4a.rhcloud.com/api/tags

Related

Insecure use of middleware over HTTP denied by configuration /tuupola/slim-jwt-auth

I'm using JWT token in my PHP Slim 4 framework. The code is working fine on local machine but when I push the code to google cloud, I'm getting error as Insecure use of middleware over HTTP denied by configuration.
Attaching screenshot of the error log :
Below is my JWT Config:
<?php
$ignoreUrl = "";
$app->add(new Tuupola\Middleware\JwtAuthentication([
"header" => "X-Token",
"regexp" => "/(.*)/",
"path" => "/public",
"secure" => true,
"secret" => "123456789",
"algorithm" => ["HS256"],
"ignore" => [
$ignoreUrl."/public/account/login",
$ignoreUrl."/public/account/logout"
],
"error" => function ($response, $arguments) {
$data["status"] = false;
$data["message"] = $arguments["message"];
return $response
->withHeader("Content-Type", "application/json")
->getBody()->write(json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT));
}
]));
Tried a lot for the solution but nothing is working. Can you please suggest what's wrong in my code. Thank you in advance

Google Chat API. Can’t create space. Method not found

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.

Get empty result api firebase [FCM]

I've saved some of my mobile registration_codes that are connected with my development environment of Firebase. Once I send a manual notification by the api I receive empty feedback from Firebase himself. After debugging I found that the notification has not been send. What's wrong with my call, because the call I make is the same in the examples and the registration_code is exactly the code what I receive from Flutter libary of Firebase.
code:
$response = Http::withToken(env('FCM_TOKEN'))->post(self::GLOBAL_URL, [
'registration_ids' => $request->users,
'data' => [
'title' => $request->title,
'message' => $request->message,
],
]);
return response()->json(["result" => $response]);
result:
{
"result": {
"cookies": {},
"transferStats": {}
}
}
First, you should not use env directly, because your .env file will not be used when the configuration is cached. Instead, you should set this value in your config/services.php file:
return [
'firebase' => [
'fcm_token' => env('FCM_TOKEN')
]
];
Second, your issue is that you are serializing the Illuminate\Http\Client\Response object instead of getting its value. To return the JSON result of your request, call json():
$response = Http::withToken(config('firebase.fcm_token'))->post(self::GLOBAL_URL, [
'registration_ids' => $request->users,
'data' => [
'title' => $request->title,
'message' => $request->message,
],
])->json(); // Notice the `json` call here
return response()->json(["result" => $response]);
If you inspect the Illuminate\Http\Client\Response object itself, you will see that it contains cookies and transferStats properties (specifically, they are on the PendingRequest object). That's why you are seeing this in your result.

Error: Failure when receiving data from the peer php GuzzleHttp

I'm trying to make post request and the post request is working but I'm not getting the response
$client = new \GuzzleHttp\Client(['headers' => ['Authorization' => 'Basic ' . 'token==']]);
$data = $client->post(
'url',
[
'form_params' => [
'address' => 'addreww',
'name' => 'Zia Sultan',
'phone_number' => '2136000000',
]
]
);
return $data;
What I'm getting in my insomnia
Error: Failure when receiving data from the peer
You're code is working, post method returns ResponseInterface, we need to fetch the content from it, we need to first fetch the StreamInterface by calling getBody() and chaining it will getContents() gives us the actual response. Keep debug mode On, to get find the exact error for Error: Failure when receiving data from the peer, and when this error occurs, share the entire trace with us
try {
$response = (new \GuzzleHttp\Client())->post(
'url',
[
'headers' => [
'Authorization' => 'Basic ' . 'token=='
],
'form_params' => [
'address' => 'addreww',
'name' => 'Zia Sultan',
'phone_number' => '2136000000',
],
// 'http_errors' => false, // Set to false to disable throwing exceptions on an HTTP protocol errors (i.e., 4xx and 5xx responses)
// 'debug' => true,
// 'connect_timeout' => 30 // number of seconds to wait while trying to connect to a server, Use 0 to wait indefinitely (the default behavior)
// 'read_timeout' => 10 // timeout to use when reading a streamed body, default value is default_socket_timeout in php.ini
// 'timeout' => 30 // the total timeout of the request in seconds. Use 0 to wait indefinitely (the default behavior).
]
);
return $response->getBody()->getContents();
} catch (Throwable $exception) {
print_r($exception);
}
I was returning the data only but I needed to return getBody() like this way
$data->getBody()
Its working now

GuzzleHTTP returns 404 on existing page

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.

Categories