using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Net; using System.Threading; using System.Threading.Tasks; using Octokit.Internal; namespace Octokit { /// /// A connection for making API requests against URI endpoints. /// Provides type-friendly convenience methods that wrap methods. /// public class ApiConnection : IApiConnection { readonly IApiPagination _pagination; /// /// Initializes a new instance of the class. /// /// A connection for making HTTP requests public ApiConnection(IConnection connection) : this(connection, new ApiPagination()) { } /// /// Initializes a new instance of the class. /// /// A connection for making HTTP requests /// A paginator for paging API responses protected ApiConnection(IConnection connection, IApiPagination pagination) { Ensure.ArgumentNotNull(connection, "connection"); Ensure.ArgumentNotNull(pagination, "pagination"); Connection = connection; _pagination = pagination; } /// /// The underlying connection. /// public IConnection Connection { get; private set; } /// /// Gets the API resource at the specified URI. /// /// Type of the API resource to get. /// URI of the API resource to get /// The API resource. /// Thrown when an API error occurs. public Task Get(Uri uri) { Ensure.ArgumentNotNull(uri, "uri"); return Get(uri, null); } /// /// Gets the API resource at the specified URI. /// /// Type of the API resource to get. /// URI of the API resource to get /// Parameters to add to the API request /// The API resource. /// Thrown when an API error occurs. public async Task Get(Uri uri, IDictionary parameters) { Ensure.ArgumentNotNull(uri, "uri"); var response = await Connection.Get(uri, parameters, null).ConfigureAwait(false); return response.Body; } /// /// Gets the API resource at the specified URI. /// /// Type of the API resource to get. /// URI of the API resource to get /// Parameters to add to the API request /// Accept header to use for the API request /// The API resource. /// Thrown when an API error occurs. public async Task Get(Uri uri, IDictionary parameters, string accepts) { Ensure.ArgumentNotNull(uri, "uri"); Ensure.ArgumentNotNull(accepts, "accepts"); var response = await Connection.Get(uri, parameters, accepts).ConfigureAwait(false); return response.Body; } /// /// Gets the HTML content of the API resource at the specified URI. /// /// URI of the API resource to get /// Parameters to add to the API request /// The API resource's HTML content. /// Thrown when an API error occurs. public async Task GetHtml(Uri uri, IDictionary parameters) { Ensure.ArgumentNotNull(uri, "uri"); var response = await Connection.GetHtml(uri, parameters).ConfigureAwait(false); return response.Body; } /// /// Gets all API resources in the list at the specified URI. /// /// Type of the API resource in the list. /// URI of the API resource to get /// of the The API resources in the list. /// Thrown when an API error occurs. public Task> GetAll(Uri uri) { return GetAll(uri, ApiOptions.None); } /// /// Gets all API resources in the list at the specified URI. /// /// Type of the API resource in the list. /// URI of the API resource to get /// Options for changing the API response /// of the The API resources in the list. /// Thrown when an API error occurs. public Task> GetAll(Uri uri, ApiOptions options) { return GetAll(uri, null, null, options); } /// /// Gets all API resources in the list at the specified URI. /// /// Type of the API resource in the list. /// URI of the API resource to get /// Parameters to add to the API request /// of the The API resources in the list. /// Thrown when an API error occurs. public Task> GetAll(Uri uri, IDictionary parameters) { return GetAll(uri, parameters, null, ApiOptions.None); } /// /// Gets all API resources in the list at the specified URI. /// /// Type of the API resource in the list. /// URI of the API resource to get /// Accept header to use for the API request /// of the The API resources in the list. /// Thrown when an API error occurs. public Task> GetAll(Uri uri, string accepts) { return GetAll(uri, null, accepts, ApiOptions.None); } /// /// Gets all API resources in the list at the specified URI. /// /// Type of the API resource in the list. /// URI of the API resource to get /// Parameters to add to the API request /// Options for changing the API response /// of the The API resources in the list. /// Thrown when an API error occurs. public Task> GetAll(Uri uri, IDictionary parameters, ApiOptions options) { return GetAll(uri, parameters, null, options); } /// /// Gets all API resources in the list at the specified URI. /// /// Type of the API resource in the list. /// URI of the API resource to get /// Parameters to add to the API request /// Accept header to use for the API request /// of the The API resources in the list. /// Thrown when an API error occurs. public Task> GetAll(Uri uri, IDictionary parameters, string accepts) { Ensure.ArgumentNotNull(uri, "uri"); return _pagination.GetAllPages(async () => await GetPage(uri, parameters, accepts).ConfigureAwait(false), uri); } public Task> GetAll(Uri uri, IDictionary parameters, string accepts, ApiOptions options) { Ensure.ArgumentNotNull(uri, "uri"); Ensure.ArgumentNotNull(options, "options"); parameters = Pagination.Setup(parameters, options); return _pagination.GetAllPages(async () => await GetPage(uri, parameters, accepts, options).ConfigureAwait(false), uri); } /// /// Creates a new API resource in the list at the specified URI. /// /// URI endpoint to send request to /// Representing the received HTTP response /// Thrown when an API error occurs. public Task Post(Uri uri) { Ensure.ArgumentNotNull(uri, "uri"); return Connection.Post(uri); } /// /// Creates a new API resource in the list at the specified URI. /// /// The API resource's type. /// URI of the API resource to get /// The created API resource. /// Thrown when an API error occurs. public async Task Post(Uri uri) { Ensure.ArgumentNotNull(uri, "uri"); var response = await Connection.Post(uri).ConfigureAwait(false); return response.Body; } /// /// Creates a new API resource in the list at the specified URI. /// /// The API resource's type. /// URI of the API resource to get /// Object that describes the new API resource; this will be serialized and used as the request's body /// The created API resource. /// Thrown when an API error occurs. public Task Post(Uri uri, object data) { Ensure.ArgumentNotNull(uri, "uri"); Ensure.ArgumentNotNull(data, "data"); return Post(uri, data, null, null); } /// /// Creates a new API resource in the list at the specified URI. /// /// The API resource's type. /// URI of the API resource to get /// Object that describes the new API resource; this will be serialized and used as the request's body /// Accept header to use for the API request /// The created API resource. /// Thrown when an API error occurs. public Task Post(Uri uri, object data, string accepts) { return Post(uri, data, accepts, null); } /// /// Creates a new API resource in the list at the specified URI. /// /// The API resource's type. /// URI of the API resource to get /// Object that describes the new API resource; this will be serialized and used as the request's body /// Accept header to use for the API request /// Content type of the API request /// The created API resource. /// Thrown when an API error occurs. public async Task Post(Uri uri, object data, string accepts, string contentType) { Ensure.ArgumentNotNull(uri, "uri"); Ensure.ArgumentNotNull(data, "data"); var response = await Connection.Post(uri, data, accepts, contentType).ConfigureAwait(false); return response.Body; } /// /// Creates a new API resource in the list at the specified URI. /// /// The API resource's type. /// URI of the API resource to get /// Object that describes the new API resource; this will be serialized and used as the request's body /// Accept header to use for the API request /// Content type of the API request /// Two Factor Authentication Code /// The created API resource. /// Thrown when an API error occurs. public async Task Post(Uri uri, object data, string accepts, string contentType, string twoFactorAuthenticationCode) { Ensure.ArgumentNotNull(uri, "uri"); Ensure.ArgumentNotNull(data, "data"); Ensure.ArgumentNotNull(twoFactorAuthenticationCode, "twoFactorAuthenticationCode"); var response = await Connection.Post(uri, data, accepts, contentType, twoFactorAuthenticationCode).ConfigureAwait(false); return response.Body; } public async Task Post(Uri uri, object data, string accepts, string contentType, TimeSpan timeout) { Ensure.ArgumentNotNull(uri, "uri"); Ensure.ArgumentNotNull(data, "data"); var response = await Connection.Post(uri, data, accepts, contentType, timeout).ConfigureAwait(false); return response.Body; } /// /// Creates or replaces the API resource at the specified URI /// /// URI of the API resource to put /// A for the request's execution. public Task Put(Uri uri) { Ensure.ArgumentNotNull(uri, "uri"); return Connection.Put(uri); } /// /// Creates or replaces the API resource at the specified URI. /// /// The API resource's type. /// URI of the API resource to create or replace /// Object that describes the API resource; this will be serialized and used as the request's body /// The created API resource. /// Thrown when an API error occurs. public async Task Put(Uri uri, object data) { Ensure.ArgumentNotNull(uri, "uri"); Ensure.ArgumentNotNull(data, "data"); var response = await Connection.Put(uri, data).ConfigureAwait(false); return response.Body; } /// /// Creates or replaces the API resource at the specified URI. /// /// The API resource's type. /// URI of the API resource to create or replace /// Object that describes the API resource; this will be serialized and used as the request's body /// The two-factor authentication code in response to the current user's previous challenge /// The created API resource. /// Thrown when an API error occurs. public async Task Put(Uri uri, object data, string twoFactorAuthenticationCode) { Ensure.ArgumentNotNull(uri, "uri"); Ensure.ArgumentNotNull(data, "data"); Ensure.ArgumentNotNullOrEmptyString(twoFactorAuthenticationCode, "twoFactorAuthenticationCode"); var response = await Connection.Put(uri, data, twoFactorAuthenticationCode).ConfigureAwait(false); return response.Body; } /// /// Creates or replaces the API resource at the specified URI. /// /// The API resource's type. /// URI of the API resource to create or replace /// Object that describes the API resource; this will be serialized and used as the request's body /// The two-factor authentication code in response to the current user's previous challenge /// Accept header to use for the API request /// The created API resource. /// Thrown when an API error occurs. public async Task Put(Uri uri, object data, string twoFactorAuthenticationCode, string accepts) { Ensure.ArgumentNotNull(uri, "uri"); Ensure.ArgumentNotNull(data, "data"); var response = await Connection.Put(uri, data, twoFactorAuthenticationCode, accepts).ConfigureAwait(false); return response.Body; } /// /// Updates the API resource at the specified URI. /// /// URI of the API resource to patch /// A for the request's execution. public Task Patch(Uri uri) { Ensure.ArgumentNotNull(uri, "uri"); return Connection.Patch(uri); } /// /// Updates the API resource at the specified URI. /// /// The API resource's type. /// URI of the API resource to update /// Object that describes the API resource; this will be serialized and used as the request's body /// The updated API resource. /// Thrown when an API error occurs. public async Task Patch(Uri uri, object data) { Ensure.ArgumentNotNull(uri, "uri"); Ensure.ArgumentNotNull(data, "data"); var response = await Connection.Patch(uri, data).ConfigureAwait(false); return response.Body; } /// /// Updates the API resource at the specified URI. /// /// The API resource's type. /// URI of the API resource to update /// Object that describes the API resource; this will be serialized and used as the request's body /// Accept header to use for the API request /// The updated API resource. /// Thrown when an API error occurs. public async Task Patch(Uri uri, object data, string accepts) { Ensure.ArgumentNotNull(uri, "uri"); Ensure.ArgumentNotNull(data, "data"); Ensure.ArgumentNotNull(accepts, "accepts"); var response = await Connection.Patch(uri, data, accepts).ConfigureAwait(false); return response.Body; } /// /// Deletes the API object at the specified URI. /// /// URI of the API resource to delete /// A for the request's execution. public Task Delete(Uri uri) { Ensure.ArgumentNotNull(uri, "uri"); return Connection.Delete(uri); } /// /// Deletes the API object at the specified URI. /// /// URI of the API resource to delete /// Two Factor Code /// A for the request's execution. public Task Delete(Uri uri, string twoFactorAuthenticationCode) { Ensure.ArgumentNotNull(uri, "uri"); return Connection.Delete(uri, twoFactorAuthenticationCode); } /// /// Deletes the API object at the specified URI. /// /// URI of the API resource to delete /// Object that describes the API resource; this will be serialized and used as the request's body /// A for the request's execution. public Task Delete(Uri uri, object data) { Ensure.ArgumentNotNull(uri, "uri"); Ensure.ArgumentNotNull(data, "data"); return Connection.Delete(uri, data); } /// /// Performs an asynchronous HTTP DELETE request that expects an empty response. /// /// URI endpoint to send request to /// The object to serialize as the body of the request /// Specifies accept response media type /// The returned public Task Delete(Uri uri, object data, string accepts) { Ensure.ArgumentNotNull(uri, "uri"); Ensure.ArgumentNotNull(data, "data"); Ensure.ArgumentNotNull(accepts, "accepts"); return Connection.Delete(uri, data, accepts); } /// /// Executes a GET to the API object at the specified URI. This operation is appropriate for /// API calls which wants to return the redirect URL. /// It expects the API to respond with a 302 Found. /// /// URI of the API resource to get /// The URL returned by the API in the Location header /// Thrown when an API error occurs, or the API does not respond with a 302 Found [Obsolete("Octokit's HTTP library now follows redirects by default - this API will be removed in a future release")] public async Task GetRedirect(Uri uri) { Ensure.ArgumentNotNull(uri, "uri"); var response = await Connection.GetRedirect(uri).ConfigureAwait(false); if (response.HttpResponse.StatusCode == HttpStatusCode.Redirect) { return response.HttpResponse.Headers["Location"]; } throw new ApiException("Redirect Operation expect status code of Redirect.", response.HttpResponse.StatusCode); } /// /// Executes a GET to the API object at the specified URI. This operation is appropriate for API calls which /// queue long running calculations and return a collection of a resource. /// It expects the API to respond with an initial 202 Accepted, and queries again until a 200 OK is received. /// It returns an empty collection if it receives a 204 No Content response. /// /// The API resource's type. /// URI of the API resource to update /// A token used to cancel this potentially long running request /// The updated API resource. /// Thrown when an API error occurs. public async Task> GetQueuedOperation(Uri uri, CancellationToken cancellationToken) { while (true) { Ensure.ArgumentNotNull(uri, "uri"); var response = await Connection.GetResponse>(uri, cancellationToken).ConfigureAwait(false); switch (response.HttpResponse.StatusCode) { case HttpStatusCode.Accepted: continue; case HttpStatusCode.NoContent: return new ReadOnlyCollection(new T[] { }); case HttpStatusCode.OK: return response.Body; } throw new ApiException("Queued Operations expect status codes of Accepted, No Content, or OK.", response.HttpResponse.StatusCode); } } async Task> GetPage( Uri uri, IDictionary parameters, string accepts) { Ensure.ArgumentNotNull(uri, "uri"); var response = await Connection.Get>(uri, parameters, accepts).ConfigureAwait(false); return new ReadOnlyPagedCollection( response, nextPageUri => Connection.Get>(nextPageUri, parameters, accepts)); } async Task> GetPage( Uri uri, IDictionary parameters, string accepts, ApiOptions options) { Ensure.ArgumentNotNull(uri, "uri"); var connection = Connection; var response = await connection.Get>(uri, parameters, accepts).ConfigureAwait(false); return new ReadOnlyPagedCollection( response, nextPageUri => { var shouldContinue = Pagination.ShouldContinue( nextPageUri, options); return shouldContinue ? connection.Get>(nextPageUri, parameters, accepts) : null; }); } } }