I am building an API Gateway and I am having a small problem returning the pagination urls from a microservice to the API Gateway.
This is the current structure of my API Gateway:
When I call the microservice, I can easily pass the paging parameters using the request data:
HTTP::get('http://api.billing.microservice.test/v2/invoices', $request->all());
However, when I make a request for a microservice, it returns the requested data, but with the URL of the microservice:
{
"data": [
# data returned from billing microservice with the billing API URL
],
"links": {
"first": "http://api.billing.microservice.test/v2/invoices?page=1",
"last": "http://api.billing.microservice.test/v2/invoices?page=10",
"prev": null,
"next": "http://api.billing.microservice.test/v2/invoices?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 10,
"path": "http://api.billing.microservice.test/v2/invoices",
"per_page": 30,
"to": 30,
"total": 300
}
}
However I need the return to have the main API URL:
{
"data": [
# data returned from billing microservice with the main API Address
],
"links": {
"first": "http://api.main.test/v2/invoices?page=1",
"last": "http://api.main.microservice.test/v2/invoices?page=10",
"prev": null,
"next": "http://api.main.test/v2/invoices?page=2"
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 10,
"path": "http://api.main.test/v2/invoices",
"per_page": 30,
"to": 30,
"total": 300
}
}
Has anyone had to do something similar? What is the best way to achieve the desired results? Do a replace using some kind of regex? Is there anything I can do inside the microservice?
I was able to solve my problem with a simple method that already exists:
Model::paginate()->setPath('http://api.main.microservice.test/v2/invoices');
The result is:
{
"data": [
# data
],
"links": {
"first": "http://api.main.microservice.test/v2/invoices?page=1",
"last": "http://api.main.microservice.test/v2/invoices?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "http://api.main.microservice.test/v2/invoices",
"per_page": 30,
"to": 3,
"total": 3
}
}
Related
Here is my code.
$orders = Order::with('customer')->withCount('orderItems')->paginate(50)->toArray();
This code return me the blank page. No data return. So here's what I did wrong?
When you are using Laravel pagination, it simply gives you an array of Data.
You don't need to convert to toArray().Use the following code :
$orders = Order::with('customer')->withCount('orderItems')->paginate(15);
The response of the pagination will be the following :
Content-Type: application/vnd.api+json
{
"meta": {
"page": {
"current-page": 2,
"per-page": 15,
"from": 16,
"to": 30,
"total": 50,
"last-page": 4
}
},
"links": {
"first": "http://localhost/api/v1/posts?page[number]=1&page[size]=15",
"prev": "http://localhost/api/v1/posts?page[number]=1&page[size]=15",
"next": "http://localhost/api/v1/posts?page[number]=3&page[size]=15",
"last": "http://localhost/api/v1/posts?page[number]=4&page[size]=15"
},
"data": [...]
}
I'm using Laravel 8.20.1 and my API route returns a paginated JSON response.
Is there a better way than str_replace() to remove the arrows from the labels?
routes/api.php:
Route::middleware('auth:sanctum')->get('/items', function (Request $request) {
return new ItemCollection(Item::paginate(5));
});
response.data.meta
{
"current_page": 1,
"from": 1,
"last_page": 3,
"links": [
{
"url": null,
"label": "« Previous",
"active": false
},
....
{
"url": "http://localhost/api/items?page=2",
"label": "Next »",
"active": false
}
],
"path": "http://localhost/api/items",
"per_page": 5,
"to": 5,
"total": 15
}
Those labels for Next and Previous are in the translation files, resources/lang/en/pagination.php. If you look at Illuminate\Pagination\LengthAwarePaginator::linkCollection you can see it building the links part of the response.
A hypermedia response that needs to be consumed by one of my services looks like this:
{
"_embedded": {
"content": [
{
"createdBy": "...",
"createdDate": "2020-03-07T14:21:27.507Z",
"id": "...",
"name": "item1",
"_links": {
"self": {
"href": ".."
}
}
}
]
},
"_links": {
"self": {
"href": "..."
},
},
"pageNumber": 1,
"totalItems": 20,
"pageSize": 10
}
See how the paging related info is not what's expected by Spring Hateoas PagedModel which should have a single "page" property instead of individual ones for pageNumber, totalItems and pageSize:
"page": {
"size": 2,
"totalElements": 1000,
"totalPages": 500,
"number": 5
}
What I did in the end was to extend CollectionModel by adding those individual properties. This does work correctly deserialising a response shown above. But, all the CollectionModel constructors are now deprecated and the alternative is to use "CollectionModel.of", which however returns just CollectionModel.
What's the right way of customising paging information in using Spring Hateoas?
Many thanks!
I'm developing an API, and for index routes, I return paginated but now I should using eloquent resources, but pagination JSON structure of these two are different and front-end code doesn't work anymore.
my codes are:
// AdminUserController.php
public function index()
{
return User::paginate();
}
// ClientUserController.php
public function index()
{
return new UserCollection(User::paginate());
}
the first JSON structure like :
{
"total": 50,
"per_page": 15,
"current_page": 1,
"last_page": 4,
"next_page_url": "http://my.app/api/admin/users?page=2",
"prev_page_url": null,
"from": 1,
"to": 15,
"data": [
{
// Result Object
},
{
// Result Object
}
]
}
But the second is like:
{
"data": [
{
// Result Object
},
{
// Result Object
}
],
"links":{
"first": "http://my.app/api/app/users?page=1",
"last": "http://my.app/api/app/users?page=2",
"prev": null,
"next": null
},
"meta":{
"current_page": 1,
"from": 1,
"last_page": 2,
"path": "http://my.app/api/admin/users",
"per_page": 15,
"to": 15,
"total": 25
}
}
why laravel paginated responses have different JSON structure?
What does your UserCollection class look like?
At first glance, it looks like this is because the first method AdminUserController#index is converting the response to JSON, while the second method ClientUserController #index is returning a collection.
My REST contorller:
#GetMapping("/test")
public Page<MyObject> pathParamTest(Pageable pageable) {
return myService.getPage(pageable);
}
I send a request like following:
localhost:8091/endpoint/test?page=0&size=3&sort=id&direction=DESC
It's my response from server:
{
"content": [
{
"id": 1
},
{
"id": 2
},
{
"id": 3
}
],
"last": true,
"totalPages": 1,
"totalElements": 3,
"first": true,
"sort": [
{
"direction": "ASC",
"property": "id",
"ignoreCase": false,
"nullHandling": "NATIVE",
"descending": false,
"ascending": true
}
],
"numberOfElements": 3,
"size": 3,
"number": 0
}
but the request has still direction = ASC.
How can I send to server direction = DESC?
And why response has a field "last" = true, because next page has one element more?
try
localhost:8091/endpoint/test?page=0&size=3&sort=id,DESC
from spring data rest 6.2. Sorting
curl -v
"http://localhost:8080/people/search/nameStartsWith?name=K&sort=name,desc"
sort Properties that should be sorted by in the format
property,property(,ASC|DESC). Default sort direction is ascending. Use
multiple sort parameters if you want to switch directions, e.g.
?sort=firstname&sort=lastname,asc.