Currently, for my GET endpoints in RESTFUL Zend Framework 3, if I can't find the item the user requests through the paramaters I send 400 with JSON API errors like so:
$this->response->setStatusCode(Response::STATUS_CODE_400);
return JsonModel([
'errors' => [
[ 'title' => 'Not found' ]
]
]);
The correct status of course is 404. However as soon as I set $this->response->setStatusCode(Response::STATUS_CODE_404); the default 404 route is displayed. How do I disable it?
I tried commenting out the following in module.config.php
. . .
'view_manager' => [
// 'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
// 'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'strategies' => [
'ViewJsonStrategy',
],
. . .
],
That works, except I have two problems:
I'd like the 404 route for some endpoints
It adds information to the return JSON I don't want sent
{
"errors": [
{
"title": "Not Found",
}
],
"message": "Page not found.",
"display_exceptions": true,
"controller": "Company\Module\Controller\RestfulController",
"controller_class": null
}
What are my options?
Your issue is caused by Zend\Mvc\View\Http\RouteNotFoundStrategy, which is registered by your default view manager. You can see that at Zend\Mvc\View\Http\ViewManager:
$routeNotFoundStrategy = $services->get('HttpRouteNotFoundStrategy');
Even if you use 'display_exceptions' => false, message is still appended.
To overcome this, one solution is to inject the model content to the response and return the latter directly on your view:
$this->response->setStatusCode(Response::STATUS_CODE_404);
$model = new JsonModel([
'errors' => [
[ 'title' => 'Not found' ]
]
]);
return $this->getResponse()->setContent($model->serialize());
Related
I created an api named valid which is not working. Postman says
"name": "Not Found",
"message": "Page not found.",
"code": 0,
"status": 404,
"type": "yii\\web\\NotFoundHttpException",
"previous": {
"name": "Invalid Route",
"message": "Unable to resolve the request \"user/valid/1\".",
"code": 0,
"type": "yii\\base\\InvalidRouteException"
}
}
My controller name is user controller.
Here is my function
public function actionValid($id)
{
return 'example';
}
i called my route as /user/valid/1.
Any reason why this is happening?
This is how i solved this.
If you want to create your own apis in yii, You must follow these steps.
First add your route in UrlManager Like this
'urlManager' => [
'enablePrettyUrl' => true,
'enableStrictParsing' => true,
'showScriptName' => false,
'rules' => [
[
'class' => 'yii\rest\UrlRule',
'controller' => 'user',
'extraPatterns' => [
'POST valid/<id>' => 'valid',
'GET listing' => 'listing
]
],
],
]
Now, call your route like this users/valid/{your-id} and users/listing. Make sure to use a plural of your controller's name.
For example, a request of POST /users/data would mean accessing the actiondata function in your usercontroller.
Below is the link to the Scout Elasticsearch Drive which I am using in my Laravel project.
https://github.com/babenkoivan/scout-elasticsearch-driver
I have database table users with the following columns:
id Integer
name String
created_at DateTime
Following the documentation on GitHub, my mapping in the User model looks like followings:
use Searchable; // using Searchable trait.
protected $mapping = [
'properties' => [
'name' => [
'type' => 'text',
'fields' => [
'raw' => [
'type' => 'keyword',
],
],
],
'created_at' => [
'type' => 'date',
'format' => 'dd-MM-yyyy HH:mm',
'fields' => [
'raw' => [
'type' => 'keyword',
],
],
],
// Custom field...
'created_date' => [
'type' => 'date',
'format' => 'dd-MM-yyyy',
'fields' => [
'raw' => [
'type' => 'keyword',
],
],
],
// Custom field...
'created_time' => [
'type' => 'date',
'format' => 'HH:mm',
'fields' => [
'raw' => [
'type' => 'keyword',
],
],
],
]
]
Below is the implementation of the toSearchableArray() function.
public function toSearchableArray()
{
$array = $this->toArray();
// Pre-format the custom fields before inserting them into Elasticsearch.
$array['created_date'] = $this->created_at->format('d-m-Y');
$array['created_time'] = $this->created_at->format('h:i');
return $array;
}
When using curl -X GET command I get the following results and of course with the custom fields.
"hits" : [
{
"_source" : {
"id" : 3,
"name": "John Doe",
"created_at": "31-12-2018 23:59",
"created_date": "31-12-2018", // My custom field.
"created_time": "23:59" // My custom field.
}
]
In my index() action in my controller, I query the data using the following code.
public function index()
{
return User::search("*")->get();
}
I get the records with only the original attributes, matching those columns in the database table as following.
[
{
"id" : 3,
"name": "John Doe",
"created_at": "31-12-2018 23:59",
}
]
Note that this is a JSON response provided by default by Laravel, responding to API calls. My custom attributes created_date and created_time do exist in Elasticsearch as well. How can I get them too as result? The reason I created these custom fields is to format the date and time on the server side beforehands so that my client-side does not need to worry about formating the date and time in the for-loop.
When I use User::search("*")->explain(); I do get my custom fields as well in the hits.hits._source{} object.
This should give you results directly from Elastic Search without matching up with your related models. I think thats the reason why your custom fields get lost.
public function index()
{
return User::search("*")->raw();
}
Documentation
I'm adding a REST API onto an existing cakephp codebase.
It is working as I expect. I hit /api/v1/contacts/12312 and get json data back for contact 12312. If put an id of a contact that doesn't exist then I get the html 404 page error rather than json.
This happens internally on the contacts->get($id) line.
In the api app controller I have
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Crud.Crud', [
'actions' => [
'Crud.Index',
'Crud.View',
'Crud.Add',
'Crud.Edit',
'Crud.Delete'
],
'listeners' => [
'CrudJsonApi.JsonApi',
'CrudJsonApi.Pagination', // Pagination != ApiPagination
'Crud.ApiQueryLog',
],
'Error' => [
'errorLevel' => E_ALL,
'exceptionRenderer' => 'CrudJsonApi\Error\JsonApiExceptionRenderer',
'skipLog' => [],
'log' => true,
'trace' => true,
],
]);
$this->Crud->config(['listeners.jsonApi.exceptionRenderer' => 'CrudJsonApi\Error\JsonApiExceptionRenderer']);
$this->setJsonResponse();
}
public function beforeRender(Event $event)
{
$this->RequestHandler->renderAs($this, 'json');
$this->response->type('application/json');
$this->set('_serialize', true);
}
I thought using the JsonApiExceptionRenderer 404 errors would be handled with json output.
Also the Pagination works but the Pagination data isnt returned with the response...
{
"viewVar": "crmContacts",
"crmContacts": [
{
"id": 1,
"lastname": "testname1"
},
{
"id": 2,
"lastname": "smith"
}
],
"success": true
}
Any ideas?
Thanks
I want to redirect or send ajax response about the session expired in YII2.
Currently i am getting Forbidden(402) Login Required message as ajax response
you have an action that ajax request sent to it ,
you have to change accessControll to public for that action , to Anonymous access . (input this function in your controller )
use yii\filters\AccessControl;
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'actions' => ['view','you-action-name-for-ajax'],
'allow' => true,
// 'roles' => ['?'],
],
],
],
];
}
be sure to remove to Roles line .. I comment it .
I test app on local is ok. I deploy to server with https domain. When i submit form then show 400 Error: Bad Request (#400): Unable to verify your data submission.
And have problem with Https, how can i fix it
Maybe you have got non-secure cookies blocked when sending over https. Try this in configuration:
return [
// ...
'components' => [
// ...
'request' => [
'class' => 'yii\web\Request',
'csrfCookie' => [
'httpOnly' => true,
'secure' => true,
],
],
],
];