Next: , Previous: , Up: API   [Contents][Index]


3.2 Making REST Requests

Function: ghub-request method resource &optional params &key query payload headers unpaginate noerror reader username auth host callback errorback url value error extra method*

This function makes a request for RESOURCE using METHOD. PARAMS, QUERY, PAYLOAD and/or HEADERS are alists holding additional request data. The response body is returned and the response headers are stored in the variable ghub-response-headers.

  • METHOD is the HTTP method, given as a string.
  • RESOURCE is the resource to access, given as a string beginning with a slash.
  • PARAMS, QUERY, PAYLOAD and HEADERS are alists and are used to specify request data. All these arguments are alists that resemble the JSON expected and returned by the Github API. The keys are symbols and the values stored in the cdr (not the cadr) can be strings, integers, or lists of strings and integers.

    The Github API documentation is vague on how data has to be transmitted and for a particular resource usually just talks about "parameters". Generally speaking when the METHOD is "HEAD" or "GET", then they have to be transmitted as a query, otherwise as a payload.

    • Use PARAMS to automatically transmit like QUERY or PAYLOAD would depending on METHOD.
    • Use QUERY to explicitly transmit data as a query.
    • Use PAYLOAD to explicitly transmit data as a payload. Instead of an alist, PAYLOAD may also be a string, in which case it gets encoded as UTF-8 but is otherwise transmitted as-is.
    • Use HEADERS for those rare resources that require that the data is transmitted as headers instead of as a query or payload. When that is the case, then the Github API documentation usually mentions it explicitly.
  • If SILENT is non-nil, then progress reports and the like are not messaged.
  • If UNPAGINATE is t, then this function makes as many requests as necessary to get all values. If UNPAGINATE is a natural number, then it gets at most that many pages. For any other non-nil value it raises an error.
  • If NOERROR is non-nil, then no error is raised if the request fails and nil is returned instead. If NOERROR is return, then the error payload is returned instead of nil.
  • If READER is non-nil, then it is used to read and return from the response buffer. The default is ghub--read-json-payload. For the very few resources that do not return JSON, you might want to use ghub--decode-payload.
  • If USERNAME is non-nil, then the request is made on behalf of that user. It is better to specify the user using the Git variable github.user for "api.github.com", or github.HOST.user if connecting to a Github Enterprise instance.
  • Each package that uses Ghub should use its own token. If AUTH is nil or unspecified, then the generic ghub token is used instead. This is only acceptable for personal utilities. A package that is distributed to other users should always use this argument to identify itself, using a symbol matching its name.

    Package authors who find this inconvenient should write a wrapper around this function and possibly for the method-specific functions as well.

    Beside nil, some other symbols have a special meaning too. none means to make an unauthorized request. basic means to make a password based request. If the value is a string, then it is assumed to be a valid token. basic and an explicit token string are only intended for internal and debugging uses.

    If AUTH is a package symbol, then the scopes are specified using the variable AUTH-github-token-scopes. It is an error if that is not specified. See ghub-github-token-scopes for an example.

  • If HOST is non-nil, then connect to that Github instance. This defaults to "api.github.com". When a repository is connected to a Github Enterprise instance, then it is better to specify that using the Git variable github.host instead of using this argument.
  • If FORGE is gitlab, then connect to Gitlab.com or, depending on HOST, to another Gitlab instance. This is only intended for internal use. Instead of using this argument you should use function glab-request and other glab-* functions.
  • If CALLBACK and/or ERRORBACK is non-nil, then this function makes one or more asynchronous requests and calls CALLBACK or ERRORBACK when finished. If no error occurred, then it calls CALLBACK, unless that is nil.

    If an error occurred, then it calls ERRORBACK, or if that is nil, then CALLBACK. ERRORBACK can also be t, in which case it signals instead. NOERROR is ignored for all asynchronous requests.

    Both callbacks are called with four arguments.

    1. For CALLBACK, the combined value of the retrieved pages. For ERRORBACK, the error that occurred when retrieving the last page.
    2. The headers of the last page as an alist.
    3. Status information provided by url-retrieve. Its :error property holds the same information as the first argument to ERRORBACK.
    4. A ghub--req struct, which can be passed to ghub-continue (which see) to retrieve the next page, if any.
Function: ghub-continue args

If there is a next page, then this function retrieves that.

This function is only intended to be called from callbacks. If there is a next page, then that is retrieved and the buffer that the result will be loaded into is returned, or t if the process has already completed. If there is no next page, then return nil.

Callbacks are called with four arguments (see ghub-request). The forth argument is a ghub--req struct, intended to be passed to this function. A callback may use the struct’s extra slot to pass additional information to the callback that will be called after the next request. Use the function ghub-req-extra to get and set the value of that slot.

As an example, using ghub-continue in a callback like so:

(ghub-get "/users/tarsius/repos" nil
          :callback (lambda (value _headers _status req)
                      (unless (ghub-continue req)
                        (setq my-value value))))

is equivalent to:

(ghub-get "/users/tarsius/repos" nil
          :unpaginate t
          :callback (lambda (value _headers _status _req)
                      (setq my-value value)))

To demonstrate how to pass information from one callback to the next, here we record when we start fetching each page:

(ghub-get "/users/tarsius/repos" nil
          :extra (list (current-time))
          :callback (lambda (value _headers _status req)
                      (push (current-time) (ghub-req-extra req))
                      (unless (ghub-continue req)
                        (setq my-times (ghub-req-extra req))
                        (setq my-value value))))
Variable: ghub-response-headers

A select few Github API resources respond by transmitting data in the response header instead of in the response body. Because there are so few of these inconsistencies, ghub-request always returns the response body.

To access the response headers use this variable after ghub-request has returned.

This function returns an alist of the link relations in HEADERS, or if optional HEADERS is nil, then those in ghub-response-headers.

When accessing a Bitbucket instance then the link relations are in PAYLOAD instead of HEADERS, making their API merely RESTish and forcing this function to append those relations to the value of ghub-response-headers, for later use when this function is called with nil for PAYLOAD.


Next: Making GraphQL Requests, Previous: Their APIs, Up: API   [Contents][Index]