Skip to content

Fix issues found during the connection-reuse review - #38

Merged
jonathan-kosgei merged 7 commits into
masterfrom
fix-noticed-issues
Nov 3, 2026
Merged

jonathan-kosgei merged 7 commits into
masterfrom
fix-noticed-issues

Conversation

@jonathan-kosgei

@jonathan-kosgei jonathan-kosgei commented Nov 3, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #37: fixes the items that pull request listed under "Noticed, not changed". No public symbol is renamed or removed and the version stays 3.1.0; the public-API additions are one setter, two model properties with a new ThreatScores class, and two request headers. The Release build is now warning-free.

Changes

  • IPLookupResult.Languages is populated again. System.Text.Json does not set a collection property that has a non-public setter, so Languages always deserialised as an empty list. The setter is now public (as Blocklists already is), with tests from the fixtures.
  • Threat.IsVpn and Threat.Scores. is_vpn maps to IsVpn (bool?) and scores to a new ThreatScores class (VpnScore, ProxyScore, ThreatScore, TrustScore, all int?); null means the response did not include the value. Documented in the README and the sample. Tests cover the VPN, satellite, anycast and bulk fixtures, a partial scores object, a GET /{ip}/threat body and a serialize/deserialize round trip.
  • User-Agent and Accept headers. Every request now carries User-Agent: ipdata-dotnet/<version> and Accept: application/json on both target frameworks. The version is the package version read from the assembly's informational version at run time (build metadata stripped, assembly version as fallback), so no dependency was added. Tests assert both headers through the mocked IHttpClient and through a real HttpClient.
  • SYSLIB0051. The (SerializationInfo, StreamingContext) constructors of ApiException and its subclasses stay on every target; on net8.0 they are marked [Obsolete(DiagnosticId = "SYSLIB0051")], so the library builds without the warning and code that still calls them gets the runtime's own diagnostic. The netstandard2.0 build is unchanged. A test checks that each constructor is still present, protected and marked.
  • Package icon. PackageIconUrl (deprecated, NU5048, an externally hosted image) is replaced by PackageIcon with icon.png embedded in the package, a PNG export of the 64x64 frame of the former .ico. ApplicationIcon and the empty Win32Resource, which only apply to executables, are removed together with the .ico; the assemblies no longer carry a 34 KB Win32 icon resource.
  • Stale IPData.nuspec removed. dotnet pack never used it (SDK-style project generates its own manifest) and its authors and dependency groups had drifted from the project file. The generated manifest is unchanged apart from the icon element.
  • Solution items. IPData.sln no longer lists .github/CODE_OF_CONDUCT.md and .github/PULL_REQUEST_TEMPLATE.md, which do not exist.
  • Test dependencies. xunit 2.9.3, xunit.runner.visualstudio 4.0.1, Microsoft.NET.Test.Sdk 18.11.0, FluentAssertions 7.2.2 (the last line under the Apache-2.0 license), FluentAssertions.Analyzers 0.33.0 (the newest release built against a Roslyn version that every .NET 8 SDK ships; 0.34 needs Roslyn 4.11), coverlet.msbuild 10.1.0, AutoFixture 4.18.1 and an explicit Moq 4.20.72 reference (previously Moq 4.7.0 via AutoFixture.AutoMoq). The xunit analyzers flag ConfigureAwait(false) in test methods (xUnit1030, it can bypass the runner's parallelization limits), so those calls were removed from the tests; nothing else in the tests changed and all of them pass on the new stack.

Not changed

  • Line endings. .editorconfig asks for CRLF in *.cs, but 23 of the 38 .cs files are LF. Normalising in either direction rewrites every line of one set of files, so this PR keeps each file's existing endings and leaves the normalisation to a dedicated commit (ideally with a .gitattributes).
  • System.Text.Json 4.7.2 (netstandard2.0 asset only). Not flagged by NuGet audit; bumping it would change the dependency surface for .NET Standard consumers, which is a separate decision.
  • System.ComponentModel.TypeConverter 4.3.0 in the test project is already the latest release of that package.

Verification

All commands run from the repository root with .NET SDK 8.0.133 on Linux, before the push:

$ dotnet build IPData.sln -c Release
Build succeeded.  0 Warning(s)  0 Error(s)        (master: NU5048 and SYSLIB0051)
  Successfully created package 'src/IPData/bin/Release/IPData.3.1.0.nupkg'
$ dotnet test IPData.sln -c Release --no-build
Passed! - Failed: 0, Passed: 137, Skipped: 0, Total: 137   (master: 121)
$ dotnet pack src/IPData/IPData.csproj -c Release --no-build
exit 0
$ unzip -l src/IPData/bin/Release/IPData.3.1.0.nupkg
lib/net8.0/IPData.dll  lib/netstandard2.0/IPData.dll  (+ .pdb)  icon.png
  nuspec: <icon>icon.png</icon>; dependency groups unchanged (net8.0: none; .NETStandard2.0: System.Text.Json 4.7.2)
$ dotnet test test/Unit/IPData.Tests/IPData.Tests.csproj -c Release /p:CollectCoverage=true
coverlet.msbuild 10.1.0 instruments under SDK 8: IPData line 94.9 %, branch 72.2 %, method 99.4 %

A console app referencing the project and sending through a real HttpClient with a recording handler shows the request as GET https://api.ipdata.co/8.8.8.8?api-key=<key> HTTP/2.0 (RequestVersionOrLower) with User-Agent: ipdata-dotnet/3.1.0 and Accept: application/json, and deserialises languages, is_vpn and scores from the recorded body. The same call against the live endpoint with a placeholder key returns UnauthorizedException (HTTP 401), so the server accepts the headers.

Not verified: the netstandard2.0 asset compiles and packs but has no runnable test target, so its header and constructor code paths are build-verified only.

CI: the CI workflow, run #18 on 02a852e (pull_request, job build-and-test): success. Restore, Build, Test and Pack all passed.

🤖 Generated with Claude Code

System.Text.Json never sets a collection property that has a non-public
setter, so Languages has deserialised as an empty list since the move to
System.Text.Json. Give it a public setter, as Blocklists already has, and
cover it with the existing fixtures.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The threat object of a response carries is_vpn and a scores object
(vpn_score, proxy_score, threat_score and trust_score), which the model
dropped. Add IsVpn (bool?) and Scores (a new ThreatScores class with int?
members) so both are read; null means the response did not include the
value. Document the fields in the README and the sample.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Requests carried no User-Agent, so the API could not tell which client
library made them, and no Accept header. CreateRequest now adds
"User-Agent: ipdata-dotnet/<version>" and "Accept: application/json" on
both target frameworks. The version is the package version read from the
assembly's informational version at run time (without the "+commit" build
metadata), so no new dependency is needed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Formatter-based serialization is obsolete on .NET 8 and later, and the
protected (SerializationInfo, StreamingContext) constructors of
ApiException and its subclasses produced SYSLIB0051 warnings in the net8.0
build. The constructors stay on every target so the public shape of the
types does not change; on net8.0 they are marked obsolete with the same
SYSLIB0051 diagnostic id, which silences the warning in the library and
passes it on to any code that still calls them. The netstandard2.0 build
is unchanged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
PackageIconUrl is deprecated (NU5048) and pointed at an externally hosted
image. The package now embeds icon.png, a PNG export of the 64x64 frame of
the project's icon, through PackageIcon. ApplicationIcon and the empty
Win32Resource only apply to executables, so they are removed from the
class library together with the .ico file they used. IPData.nuspec was
never used by dotnet pack (the SDK-style project generates its own
manifest) and had drifted from the project file, so it is removed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
IPData.sln listed .github/CODE_OF_CONDUCT.md and
.github/PULL_REQUEST_TEMPLATE.md as solution items, but neither file
exists in the repository.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Move the test project to current releases: xunit 2.9.3 with
xunit.runner.visualstudio 4.0.1 and Microsoft.NET.Test.Sdk 18.11.0,
FluentAssertions 7.2.2 (the last line under the Apache-2.0 license) with
FluentAssertions.Analyzers 0.33.0 (the newest release built against a
Roslyn version that every .NET 8 SDK ships; 0.34 needs Roslyn 4.11),
coverlet.msbuild 10.1.0, AutoFixture 4.18.1 and an explicit Moq 4.20.72
reference, which replaces the Moq 4.7.0 that AutoFixture.AutoMoq pulled
in. The xunit analyzers flag ConfigureAwait(false) in test methods
(xUnit1030) because it can bypass the runner's parallelization limits, so
those calls are removed from the tests. All 137 tests pass on the new
stack.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@jonathan-kosgei
jonathan-kosgei merged commit 75a8c73 into master Nov 3, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants