Internal GET request returns null for every other call, might be some issue with caching
- Dominant language
- PHP
- Stars
- 9.4k
- Forks
- 1.3k
- PR merge metrics
- No merged PRs in 30d
Description
| Q | A
| ----------------- | ---
| Bug? | most likely not
| New Feature? | no
| Framework | Laravel
| Framework version | 5.4.36
| Package version | dev-master
| PHP version | 7.1.8
#### Actual Behaviour
I created an API endpoint that simply proxies to another API endpoint with additional query parameters: i. e. a GET request to `http://example.com/api/admin` proxies to `http://example.com/api/user?is_admin=1`. This is implemented via the `api` helper provided by dingo:
api->get('user?is_admin=1');
}
// ...
}
However, every other GET request to `http://example.com/api/admin` that is done by Firefox (via axios with default configuration) does not return a response body (but always a statuscode of 200). While debugging the script I found out that the call to `$this->api->get('user?is_admin=1');` returns `null` instead of the actual data for every other call.
#### Expected Behaviour
I expect the call to `$this->api->get(...)` to always return the correct data.
#### Steps to reproduce
My app is very simple and mostly uses the default configuration. The proxied controller simply creates a `QueryBuilder` and returns its result. A simplified example without user input filtering etc.:
query;
if(0 < $query_params->count()) {
$qb = User::query();
if($query_params->has('is_admin')) {
$qb->where('is_admin', $query_params->get('is_admin'));
}
$collection = $qb->get();
} else {
$collection = User::all();
}
return $this->response->array($collection->toArray());
}
// ...
}
In the browser you then need to make an HTTP request to the `admin` route, with axios that could be something like
axios.get('/api/admin')
.then(response => {
console.debug(response.data);
});
#### Possible solution
I think it has to do with caching. When I use the HTTP client in PhpStorm (Tools -> Test RESTful Web Service) to execute GET requests to `http://example.com/api/admin` without any cache headers, it always returns a result. Firefox/axios on the other hand always uses cache headers and ETags. I don't know how those headers are handled by Dingo or how they are passed on to the next controller via the `api` helper, so I have no other idea so far than the quick and dirty solution of disabling caching entirely.
Maybe somebody can point me in the right direction on how to get caching right with Dingo?
I could imagine the following scenario to be happening but I don't know how to resolve this:
1. The first ever request (without cache headers) returns a result and somewhere in the dispatch process an ETag is created
2. The second request now contains the cache headers with the ETag. These headers are passed on to the internal request and in the dispatch process of that internal request the server recognizes that nothing has changed, so the internal request returns a statuscode of 304 without a response body. However, because the `api` helper does not return full responses from the internal requests but only the data, the returned value is `null`. In the dispatch process of the request to the admin route a new ETag is generated based on the now empty response body.
3. In the third request, the cache headers are still included but this time the ETag represents the empty body of the previous response. When this ETag is passed on to the internal request, the server recognizes that the given ETag (which was based on an empty body) does not match and therefore returns data again. Based on this data a new ETag is generated.
4. Step 2. starts again
**edit**
Using the `raw()` method, I got the full response object and my assumptions were true. Every other call, the ETag passed on to the proxied controller gets a match so the internal API call returns 304 without content. I guess using internal requests is not the best solution here anyway, I will create a service layer instead.
Contributor guide
Assessment
This issue has not been assessed yet.