diff --git a/Octokit.Reactive/IObservableGitHubClient.cs b/Octokit.Reactive/IObservableGitHubClient.cs
index e6374a0c..1dc1bb3c 100644
--- a/Octokit.Reactive/IObservableGitHubClient.cs
+++ b/Octokit.Reactive/IObservableGitHubClient.cs
@@ -1,6 +1,6 @@
namespace Octokit.Reactive
{
- public interface IObservableGitHubClient
+ public interface IObservableGitHubClient : IApiInfo
{
IConnection Connection { get; }
diff --git a/Octokit.Reactive/ObservableGitHubClient.cs b/Octokit.Reactive/ObservableGitHubClient.cs
index dc5c3d03..0ddd519d 100644
--- a/Octokit.Reactive/ObservableGitHubClient.cs
+++ b/Octokit.Reactive/ObservableGitHubClient.cs
@@ -68,5 +68,11 @@ namespace Octokit.Reactive
public IObservableNotificationsClient Notification { get; private set; }
public IObservableGitDatabaseClient GitDatabase { get; private set; }
public IObservableSearchClient Search { get; private set; }
+
+ ///
+ /// Gets the latest API Info - this will be null if no API calls have been made
+ ///
+ /// representing the information returned as part of an Api call
+ public ApiInfo LastApiInfo { get { return _gitHubClient.Connection.LastApiInfo; } }
}
}
diff --git a/Octokit.Tests.Integration/Clients/GitHubClientTests.cs b/Octokit.Tests.Integration/Clients/GitHubClientTests.cs
new file mode 100644
index 00000000..14ca8894
--- /dev/null
+++ b/Octokit.Tests.Integration/Clients/GitHubClientTests.cs
@@ -0,0 +1,32 @@
+using Octokit.Tests.Integration;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit;
+
+public class GitHubClientTests
+{
+ public class TheLastApiInfoProperty
+ {
+ [IntegrationTest]
+ public async Task CanRetrieveLastApiInfo()
+ {
+ var github = Helper.GetAuthenticatedClient();
+
+ // Doesn't matter which API gets called
+ await github.Miscellaneous.GetRateLimits();
+
+ var result = github.LastApiInfo;
+
+ //Assert.True(result.Links.Count > 0);
+ //Assert.True(result.AcceptedOauthScopes.Count > 0);
+ //Assert.True(result.OauthScopes.Count > 0);
+ //Assert.False(String.IsNullOrEmpty(result.Etag));
+ Assert.True(result.RateLimit.Limit > 0);
+ Assert.True(result.RateLimit.Remaining > -1);
+ Assert.NotNull(result.RateLimit.Reset);
+ }
+ }
+}
diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
index 87dd6b7a..45b1fb1e 100644
--- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
+++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
@@ -75,6 +75,7 @@
+
diff --git a/Octokit.Tests/GitHubClientTests.cs b/Octokit.Tests/GitHubClientTests.cs
index 1b0fc242..b02b4ac7 100644
--- a/Octokit.Tests/GitHubClientTests.cs
+++ b/Octokit.Tests/GitHubClientTests.cs
@@ -5,6 +5,7 @@ using NSubstitute;
using Octokit.Internal;
using Xunit;
using Xunit.Extensions;
+using System.Collections.Generic;
namespace Octokit.Tests
{
@@ -104,5 +105,71 @@ namespace Octokit.Tests
Assert.Equal("bar", client.Credentials.Password);
}
}
+
+ public class TheLastApiInfoProperty
+ {
+ [Fact]
+ public async Task ReturnsNullIfNew()
+ {
+ var connection = Substitute.For();
+ connection.LastApiInfo.Returns((ApiInfo)null);
+ var client = new GitHubClient(connection);
+
+ var result = client.LastApiInfo;
+
+ Assert.Null(result);
+
+ var temp = connection.Received(1).LastApiInfo;
+ }
+
+ [Fact]
+ public async Task ReturnsObjectIfNotNew()
+ {
+ var apiInfo = new ApiInfo(
+ new Dictionary
+ {
+ {
+ "next",
+ new Uri("https://api.github.com/repos/rails/rails/issues?page=4&per_page=5")
+ },
+ {
+ "last",
+ new Uri("https://api.github.com/repos/rails/rails/issues?page=131&per_page=5")
+ },
+ {
+ "first",
+ new Uri("https://api.github.com/repos/rails/rails/issues?page=1&per_page=5")
+ },
+ {
+ "prev",
+ new Uri("https://api.github.com/repos/rails/rails/issues?page=2&per_page=5")
+ }
+ },
+ new List
+ {
+ "user",
+ },
+ new List
+ {
+ "user",
+ "public_repo",
+ "repo",
+ "gist"
+ },
+ "5634b0b187fd2e91e3126a75006cc4fa",
+ new RateLimit(100, 75, 1372700873)
+ );
+ var connection = Substitute.For();
+ connection.LastApiInfo.Returns(apiInfo);
+ var client = new GitHubClient(connection);
+
+ var result = client.LastApiInfo;
+
+ Assert.NotNull(result);
+
+ var temp = connection.Received(1).LastApiInfo;
+ }
+ }
+
}
}
diff --git a/Octokit.Tests/Http/ConnectionTests.cs b/Octokit.Tests/Http/ConnectionTests.cs
index 02f1601e..ad335e44 100644
--- a/Octokit.Tests/Http/ConnectionTests.cs
+++ b/Octokit.Tests/Http/ConnectionTests.cs
@@ -564,5 +564,85 @@ namespace Octokit.Tests.Http
Assert.True(connection.UserAgent.StartsWith("OctokitTests ("));
}
}
+
+ public class TheLastAPiInfoProperty
+ {
+ [Fact]
+ public async Task ReturnsNullIfNew()
+ {
+ var httpClient = Substitute.For();
+ httpClient.LastApiInfo.Returns((ApiInfo)null);
+ var connection = new Connection(new ProductHeaderValue("OctokitTests"),
+ _exampleUri,
+ Substitute.For(),
+ httpClient,
+ Substitute.For());
+
+ var result = connection.LastApiInfo;
+
+ Assert.Null(result);
+
+ var temp = httpClient.Received(1).LastApiInfo;
+ }
+
+ [Fact]
+ public async Task ReturnsObjectIfNotNew()
+ {
+ var apiInfo = new ApiInfo(
+ new Dictionary
+ {
+ {
+ "next",
+ new Uri("https://api.github.com/repos/rails/rails/issues?page=4&per_page=5")
+ },
+ {
+ "last",
+ new Uri("https://api.github.com/repos/rails/rails/issues?page=131&per_page=5")
+ },
+ {
+ "first",
+ new Uri("https://api.github.com/repos/rails/rails/issues?page=1&per_page=5")
+ },
+ {
+ "prev",
+ new Uri("https://api.github.com/repos/rails/rails/issues?page=2&per_page=5")
+ }
+ },
+ new List
+ {
+ "user",
+ },
+ new List
+ {
+ "user",
+ "public_repo",
+ "repo",
+ "gist"
+ },
+ "5634b0b187fd2e91e3126a75006cc4fa",
+ new RateLimit(100, 75, 1372700873)
+ );
+
+ var httpClient = Substitute.For();
+ httpClient.LastApiInfo.Returns(apiInfo);
+ var connection = new Connection(new ProductHeaderValue("OctokitTests"),
+ _exampleUri,
+ Substitute.For(),
+ httpClient,
+ Substitute.For());
+
+ var result = connection.LastApiInfo;
+
+ // No point checking all of the values as they are tested elsewhere
+ // Just provde that the ApiInfo is populated
+ Assert.Equal(4, result.Links.Count);
+ Assert.Equal(1, result.OauthScopes.Count);
+ Assert.Equal(4, result.AcceptedOauthScopes.Count);
+ Assert.Equal("5634b0b187fd2e91e3126a75006cc4fa", result.Etag);
+ Assert.Equal(100, result.RateLimit.Limit);
+
+ var temp = httpClient.Received(1).LastApiInfo;
+ }
+ }
}
}
diff --git a/Octokit/GitHubClient.cs b/Octokit/GitHubClient.cs
index d88a6257..b79640af 100644
--- a/Octokit/GitHubClient.cs
+++ b/Octokit/GitHubClient.cs
@@ -100,6 +100,12 @@ namespace Octokit
Deployment = new DeploymentsClient(apiConnection);
}
+ ///
+ /// Gets the latest API Info - this will be null if no API calls have been made
+ ///
+ /// representing the information returned as part of an Api call
+ public ApiInfo LastApiInfo { get { return Connection.LastApiInfo; } }
+
///
/// Convenience property for getting and setting credentials.
///
diff --git a/Octokit/Http/Connection.cs b/Octokit/Http/Connection.cs
index 846923d3..532c9e71 100644
--- a/Octokit/Http/Connection.cs
+++ b/Octokit/Http/Connection.cs
@@ -136,6 +136,12 @@ namespace Octokit
_jsonPipeline = new JsonHttpPipeline();
}
+ ///
+ /// Gets the latest API Info - this will be null if no API calls have been made
+ ///
+ /// representing the information returned as part of an Api call
+ public ApiInfo LastApiInfo { get { return _httpClient.LastApiInfo; } }
+
public Task> Get(Uri uri, IDictionary parameters, string accepts)
{
Ensure.ArgumentNotNull(uri, "uri");
diff --git a/Octokit/Http/HttpClientAdapter.cs b/Octokit/Http/HttpClientAdapter.cs
index 59dd87c0..bf33df39 100644
--- a/Octokit/Http/HttpClientAdapter.cs
+++ b/Octokit/Http/HttpClientAdapter.cs
@@ -28,6 +28,12 @@ namespace Octokit.Internal
_http = new HttpClient(new RedirectHandler { InnerHandler = getHandler() });
}
+ ///
+ /// Gets the latest API Info - this will be null if no API calls have been made
+ ///
+ /// representing the information returned as part of an Api call
+ public ApiInfo LastApiInfo { get; private set; }
+
///
/// Sends the specified request and returns a response.
///
@@ -45,7 +51,11 @@ namespace Octokit.Internal
// Make the request
var responseMessage = await _http.SendAsync(requestMessage, HttpCompletionOption.ResponseContentRead, cancellationTokenForRequest)
.ConfigureAwait(false);
- return await BuildResponse(responseMessage).ConfigureAwait(false);
+ var response = await BuildResponse(responseMessage).ConfigureAwait(false);
+
+ LastApiInfo = response.ApiInfo;
+
+ return response;
}
}
diff --git a/Octokit/Http/IApiInfo.cs b/Octokit/Http/IApiInfo.cs
new file mode 100644
index 00000000..04a2cf89
--- /dev/null
+++ b/Octokit/Http/IApiInfo.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Octokit
+{
+ ///
+ /// Provides a property for the Last recorded API infomation
+ ///
+ public interface IApiInfo
+ {
+ ///
+ /// Gets the latest API Info - this will be null if no API calls have been made
+ ///
+ /// representing the information returned as part of an Api call
+ ApiInfo LastApiInfo { get; }
+ }
+}
diff --git a/Octokit/Http/IConnection.cs b/Octokit/Http/IConnection.cs
index 7deec1cc..dd756b10 100644
--- a/Octokit/Http/IConnection.cs
+++ b/Octokit/Http/IConnection.cs
@@ -10,7 +10,7 @@ namespace Octokit
///
/// A connection for making HTTP requests against URI endpoints.
///
- public interface IConnection
+ public interface IConnection : IApiInfo
{
///
/// Performs an asynchronous HTTP GET request that expects a containing HTML.
diff --git a/Octokit/Http/IHttpClient.cs b/Octokit/Http/IHttpClient.cs
index f554d750..db9de47a 100644
--- a/Octokit/Http/IHttpClient.cs
+++ b/Octokit/Http/IHttpClient.cs
@@ -10,7 +10,7 @@ namespace Octokit.Internal
///
/// Most folks won't ever need to swap this out. But if you're trying to run this on Windows Phone, you might.
///
- public interface IHttpClient : IDisposable
+ public interface IHttpClient : IDisposable, IApiInfo
{
///
/// Sends the specified request and returns a response.
diff --git a/Octokit/IGitHubClient.cs b/Octokit/IGitHubClient.cs
index a828c83e..1ae593cc 100644
--- a/Octokit/IGitHubClient.cs
+++ b/Octokit/IGitHubClient.cs
@@ -5,7 +5,7 @@ namespace Octokit
///
/// A Client for the GitHub API v3. You can read more about the api here: http://developer.github.com.
///
- public interface IGitHubClient
+ public interface IGitHubClient : IApiInfo
{
///
/// Provides a client connection to make rest requests to HTTP endpoints.
diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj
index 64daa005..4db1ff4c 100644
--- a/Octokit/Octokit-Mono.csproj
+++ b/Octokit/Octokit-Mono.csproj
@@ -399,6 +399,7 @@
+
\ No newline at end of file
diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj
index 9002587a..66103c57 100644
--- a/Octokit/Octokit-MonoAndroid.csproj
+++ b/Octokit/Octokit-MonoAndroid.csproj
@@ -1,4 +1,4 @@
-
+
Debug
@@ -415,6 +415,7 @@
+
\ No newline at end of file
diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj
index 607ec595..bde1203d 100644
--- a/Octokit/Octokit-Monotouch.csproj
+++ b/Octokit/Octokit-Monotouch.csproj
@@ -1,4 +1,4 @@
-
+
Debug
@@ -408,6 +408,7 @@
+
diff --git a/Octokit/Octokit-Portable.csproj b/Octokit/Octokit-Portable.csproj
index 74f211df..4080a485 100644
--- a/Octokit/Octokit-Portable.csproj
+++ b/Octokit/Octokit-Portable.csproj
@@ -398,6 +398,7 @@
+
diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj
index 944bb681..65c2b6f0 100644
--- a/Octokit/Octokit-netcore45.csproj
+++ b/Octokit/Octokit-netcore45.csproj
@@ -402,6 +402,7 @@
+
diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj
index 60a9607f..943d7bca 100644
--- a/Octokit/Octokit.csproj
+++ b/Octokit/Octokit.csproj
@@ -84,6 +84,7 @@
+