calcinai / xero-php

A php library for the Xero API, with a cleaner OAuth interface and ORM-like abstraction.
MIT License
359 stars 261 forks source link

Get headers from response object #806

Open jasonlewis opened 3 years ago

jasonlewis commented 3 years ago

I think I might be missing something here but there doesn't seem to be a way to get headers off of the response. I want to be able to preemptively check the rate limiting headers. Perhaps there's another way?

calcinai commented 3 years ago

@jasonlewis does Xero return something before you hit the limit? There’s going to be a RateLimitExceeded exception thrown when you actually hit it.

jasonlewis commented 3 years ago

Yeah Xero returns remaining limits in response headers so you can see what your limits currently are.

Taken the following snippet from here: https://developer.xero.com/documentation/oauth2/limits

Each API response you receive will include the X-DayLimit-Remaining, X-MinLimit-Remaining and X-AppMinLimit-Remaining headers telling you the number of remaining against each limit.

calcinai commented 3 years ago

Now you mention it, I do recall reading this somewhere. If you create the request/response manually, you can get the raw response object, but that's not much help for normal usage.

If you use $xero->save($model), this should return a response object that holds the headers... I think.

victormacko commented 3 years ago

I've also come across this need, where can't pre-emptively view & slow down the API calls due to having no visibility of the returned headers for rate-limits.

The # remaining per min is usually the one I find being hit the most. Is there anything I can help with in terms of progressing this further?

Josh-G commented 3 years ago

Are you able to accomplish the desired behaviour using a Guzzle middleware/handler? You can then pass this in using setTransport. We use this for retrying transitive errors with the API, and for handling rate limits.

victormacko commented 3 years ago

Maybe by registering some event-listeners, and potentially adding some delays (to minimise the 'wait-and-retry' exception from being thrown) in the 'before' listener for guzzle too, although I think it'd be better to handle this within the Xero package rather than having to code it separately for each separate app.

calcinai commented 3 years ago

@victormacko Happy for you to propose a way to handle this one

defmost commented 2 years ago

Has someone already found a reliable solution for this?

mogilvie commented 1 year ago

Looking at it now, considering the following...

The XeroPHP\Remote\Query execute function gets the full response back from Guzzle, which contains the following: image

The Query object also contains the Application, so we could pass the limits back to the Application for use outside the bundle. Which kind of makes sense, Application keeps the record of transaction limits remaining during the life cycle of the action.

@calcinai Shall I work along these lines?

calcinai commented 1 year ago

@mogilvie I think that's probably the cleanest way to do it. The only immediate issue I see is those numbers going stale–would you suggest making those numbers of the time and 'expire'?

mogilvie commented 1 year ago

From my reading of the Xero API, each response gives the stats as of the time of the request. So they'd get written over with each new request & response. We could keep the timestamp of the last request in the Application as well. So if there were any long life processes then the bundle user could estimate based on timestamp.

Although if you really needed an up to date count, then request the org details and get the latest usage stats back.

I'll work on the above.

lionslair commented 1 year ago

Subscribing