Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- [Currency](#currency)
- [Threat](#threat)
- [EU Endpoint](#eu-endpoint)
- [Dependency Injection](#dependency-injection)
- [Migrating from v2 to v3](#migrating-from-v2-to-v3)
- [Contributing](#contributing)
- [Versioning](#versioning)
Expand Down Expand Up @@ -143,6 +144,41 @@ var client = new IPDataClient("API_KEY", new Uri("https://eu-api.ipdata.co"));
var ipInfo = await client.Lookup("8.8.8.8");
```

## Dependency Injection

If you're using ASP.NET Core, you can register `IPDataClient` with `IHttpClientFactory` to benefit from managed connection pooling and handler lifetimes:

```csharp
// In Program.cs or Startup.cs
services.AddHttpClient("ipdata");
services.AddSingleton<IIPDataClient>(sp =>
{
var factory = sp.GetRequiredService<IHttpClientFactory>();
var httpClient = factory.CreateClient("ipdata");
return new IPDataClient("API_KEY", httpClient);
});
```

Then inject `IIPDataClient` wherever you need it:

```csharp
public class MyService
{
private readonly IIPDataClient _ipDataClient;

public MyService(IIPDataClient ipDataClient)
{
_ipDataClient = ipDataClient;
}

public async Task<string> GetCountry(string ip)
{
var result = await _ipDataClient.Lookup(ip);
return result.CountryName;
}
}
```

## Migrating from v2 to v3

v3.0.0 renames all public types to follow [.NET naming conventions](https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/capitalization-conventions) for two-letter acronyms. It also adds EU endpoint support and a `Company` lookup.
Expand Down
5 changes: 5 additions & 0 deletions test/Unit/IPData.Tests/DataSources/TestData/Carrier.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"name": "T-Mobile",
"mcc": "310",
"mnc": "160"
}
6 changes: 6 additions & 0 deletions test/Unit/IPData.Tests/DataSources/TestData/Company.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "Google LLC",
"domain": "google.com",
"network": "8.8.8.0/24",
"type": "business"
}
71 changes: 71 additions & 0 deletions test/Unit/IPData.Tests/DataSources/TestData/IPLookupResult.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"ip": "91.225.201.108",
"is_eu": false,
"city": "Lviv",
"region": "L'vivs'ka Oblast'",
"region_code": "46",
"region_type": "oblast",
"country_name": "Ukraine",
"country_code": "UA",
"continent_name": "Europe",
"continent_code": "EU",
"latitude": 49.8486,
"longitude": 24.0323,
"postal": "79000",
"calling_code": "380",
"flag": "https://ipdata.co/flags/ua.png",
"emoji_flag": "\uD83C\uDDFA\uD83C\uDDE6",
"emoji_unicode": "U+1F1FA U+1F1E6",
"asn": {
"asn": "AS49824",
"name": "PC \"Astra-net\"",
"domain": "astra.in.ua",
"route": "91.225.200.0/22",
"type": "isp"
},
"company": {
"name": "Astra-net",
"domain": "astra.in.ua",
"network": "91.225.200.0/22",
"type": "isp"
},
"carrier": {
"name": "Kyivstar",
"mcc": "255",
"mnc": "03"
},
"languages": [
{
"name": "Ukrainian",
"native": "\u0423\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430",
"code": "uk"
}
],
"currency": {
"name": "Ukrainian Hryvnia",
"code": "UAH",
"symbol": "\u20B4",
"native": "\u20B4",
"plural": "Ukrainian hryvnias"
},
"time_zone": {
"name": "Europe/Kiev",
"abbr": "EET",
"offset": "+0200",
"is_dst": false,
"current_time": "2020-01-30T23:16:19.129316+02:00"
},
"threat": {
"is_tor": false,
"is_icloud_relay": false,
"is_proxy": false,
"is_datacenter": false,
"is_anonymous": false,
"is_known_attacker": false,
"is_known_abuser": false,
"is_threat": false,
"is_bogon": false,
"blocklists": []
},
"status": 200
}
20 changes: 17 additions & 3 deletions test/Unit/IPData.Tests/DataSources/TestDataSource.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Collections.Generic;
using System.IO;
using System.Reflection;

namespace IPData.Tests.DataSources
{
Expand All @@ -13,17 +15,29 @@ public static IEnumerable<object[]> EmptyOrWhitespaceString()

public static IEnumerable<object[]> IPLookupResultData()
{
yield return new object[] { "{\"ip\":\"91.225.201.108\",\"is_eu\":false,\"city\":\"Lviv\",\"region\":\"L'vivs'ka Oblast'\",\"region_code\":\"46\",\"region_type\":\"oblast\",\"country_name\":\"Ukraine\",\"country_code\":\"UA\",\"continent_name\":\"Europe\",\"continent_code\":\"EU\",\"latitude\":49.8486,\"longitude\":24.0323,\"postal\":\"79000\",\"calling_code\":\"380\",\"flag\":\"https:\\/\\/ipdata.co\\/flags\\/ua.png\",\"emoji_flag\":\"\uD83C\uDDFA\uD83C\uDDE6\",\"emoji_unicode\":\"U+1F1FA U+1F1E6\",\"asn\":{\"asn\":\"AS49824\",\"name\":\"PC \\\"Astra-net\\\"\",\"domain\":\"astra.in.ua\",\"route\":\"91.225.200.0\\/22\",\"type\":\"isp\"},\"company\":{\"name\":\"Astra-net\",\"domain\":\"astra.in.ua\",\"network\":\"91.225.200.0\\/22\",\"type\":\"isp\"},\"carrier\":{\"name\":\"Kyivstar\",\"mcc\":\"255\",\"mnc\":\"03\"},\"languages\":[{\"name\":\"Ukrainian\",\"native\":\"\u0423\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430\",\"code\":\"uk\"}],\"currency\":{\"name\":\"Ukrainian Hryvnia\",\"code\":\"UAH\",\"symbol\":\"\u20B4\",\"native\":\"\u20B4\",\"plural\":\"Ukrainian hryvnias\"},\"time_zone\":{\"name\":\"Europe\\/Kiev\",\"abbr\":\"EET\",\"offset\":\"+0200\",\"is_dst\":false,\"current_time\":\"2020-01-30T23:16:19.129316+02:00\"},\"threat\":{\"is_tor\":false,\"is_icloud_relay\":false,\"is_proxy\":false,\"is_datacenter\":false,\"is_anonymous\":false,\"is_known_attacker\":false,\"is_known_abuser\":false,\"is_threat\":false,\"is_bogon\":false,\"blocklists\":[]},\"status\":200}" };
yield return new object[] { ReadJsonFile("IPLookupResult.json") };
}

public static IEnumerable<object[]> CarrierData()
{
yield return new object[] { "{\"name\":\"T-Mobile\",\"mcc\":\"310\",\"mnc\":\"160\"\r\n}" };
yield return new object[] { ReadJsonFile("Carrier.json") };
}

public static IEnumerable<object[]> CompanyData()
{
yield return new object[] { "{\"name\":\"Google LLC\",\"domain\":\"google.com\",\"network\":\"8.8.8.0\\/24\",\"type\":\"business\"}" };
yield return new object[] { ReadJsonFile("Company.json") };
}

private static string ReadJsonFile(string fileName)
{
var assembly = Assembly.GetExecutingAssembly();
var resourceName = $"IPData.Tests.DataSources.TestData.{fileName}";

using (var stream = assembly.GetManifestResourceStream(resourceName))
using (var reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
}
}
50 changes: 0 additions & 50 deletions test/Unit/IPData.Tests/Exceptions/BadRequestExceptionTests.cs

This file was deleted.

65 changes: 65 additions & 0 deletions test/Unit/IPData.Tests/Exceptions/DerivedExceptionTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using System.Collections.Generic;
using System.Net;
using FluentAssertions;
using IPData.Exceptions;
using Xunit;

namespace IPData.Tests.Exceptions
{
public class DerivedExceptionTests
{
public static IEnumerable<object[]> ExceptionStatusCodeData()
{
yield return new object[] { new BadRequestException(), HttpStatusCode.BadRequest };
yield return new object[] { new ForbiddenException(), HttpStatusCode.Forbidden };
yield return new object[] { new UnauthorizedException(), HttpStatusCode.Unauthorized };
}

public static IEnumerable<object[]> ExceptionData()
{
yield return new object[] { new BadRequestException() };
yield return new object[] { new ForbiddenException() };
yield return new object[] { new UnauthorizedException() };
}

[Theory]
[MemberData(nameof(ExceptionStatusCodeData))]
public void Exception_WhenCreate_ShouldReturnCorrectStatusCode(
ApiException sut, HttpStatusCode expectedStatusCode)
{
sut.StatusCode.Should().Be(expectedStatusCode);
}

[Theory]
[MemberData(nameof(ExceptionData))]
public void Exception_WhenCreateWithoutParams_ShouldReturnApiError(
ApiException sut)
{
sut.ApiError.Should().NotBeNull();
}

public static IEnumerable<object[]> ExceptionWithContentData()
{
var content = "test error message";
yield return new object[] { new BadRequestException(content), content };
yield return new object[] { new ForbiddenException(content), content };
yield return new object[] { new UnauthorizedException(content), content };
}

[Theory]
[MemberData(nameof(ExceptionWithContentData))]
public void Exception_WhenCreateWithContent_ShouldReturnApiErrorWithMessage(
ApiException sut, string expectedMessage)
{
sut.ApiError.Message.Should().Be(expectedMessage);
}

[Theory]
[MemberData(nameof(ExceptionWithContentData))]
public void Exception_WhenCreateWithContent_ShouldBeMessage(
ApiException sut, string expectedMessage)
{
sut.Message.Should().Be(expectedMessage);
}
}
}
50 changes: 0 additions & 50 deletions test/Unit/IPData.Tests/Exceptions/ForbiddenExceptionTests.cs

This file was deleted.

50 changes: 0 additions & 50 deletions test/Unit/IPData.Tests/Exceptions/UnauthorizedExceptionTests.cs

This file was deleted.

Loading
Loading