Skip to content

Commit

Permalink
new GeoServer .Net Client example
Browse files Browse the repository at this point in the history
  • Loading branch information
totpero committed Dec 2, 2023
1 parent 411293a commit 487dc21
Show file tree
Hide file tree
Showing 20 changed files with 425 additions and 0 deletions.
45 changes: 45 additions & 0 deletions GeoServer.Net.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34322.80
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GeoServer.Net", "src\GeoServer.Net\GeoServer.Net.csproj", "{FFFBE134-B411-439C-9B06-0580A261CFD4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EDE9678A-A3B8-489A-9559-3E1CCFB5E1E5}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{F6F66F4D-A0D3-4D09-9590-027DEBB7321A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GeoServer.Net.Tests", "test\GeoServer.Net.Tests\GeoServer.Net.Tests.csproj", "{3964813D-42DD-4DD1-BF8F-02B153460E22}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{74CC736A-110C-46D4-AC52-90A9CC701B6F}"
ProjectSection(SolutionItems) = preProject
LICENSE = LICENSE
README.md = README.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FFFBE134-B411-439C-9B06-0580A261CFD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FFFBE134-B411-439C-9B06-0580A261CFD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FFFBE134-B411-439C-9B06-0580A261CFD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FFFBE134-B411-439C-9B06-0580A261CFD4}.Release|Any CPU.Build.0 = Release|Any CPU
{3964813D-42DD-4DD1-BF8F-02B153460E22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3964813D-42DD-4DD1-BF8F-02B153460E22}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3964813D-42DD-4DD1-BF8F-02B153460E22}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3964813D-42DD-4DD1-BF8F-02B153460E22}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{FFFBE134-B411-439C-9B06-0580A261CFD4} = {EDE9678A-A3B8-489A-9559-3E1CCFB5E1E5}
{3964813D-42DD-4DD1-BF8F-02B153460E22} = {F6F66F4D-A0D3-4D09-9590-027DEBB7321A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {79ADD1A3-B69D-4589-A7B5-4FD1AC02A17A}
EndGlobalSection
EndGlobal
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
# GeoServer.Net
.Net Client for geoserver https://github.com/geoserver/geoserver

# GeoServer API documentation:
https://docs.geoserver.org/stable/en/user/rest/index.html
34 changes: 34 additions & 0 deletions src/GeoServer.Net/Constants/ApiConsts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
namespace GeoServer.Net.Constants;

public static class ApiConsts
{
public const string Version = "2.24.1";
public const string OutputFormat = ".json";

public static class Endpoints
{
//public const string BaseApiUrl = "http://localhost:8080/geoserver";
//public const string BaseApiPath = BaseApiUrl + "/rest";
public const string BaseApiPath = "/rest";

/// <summary>
/// The REST API allows you to set and retrieve information about the server itself.
/// </summary>
public static class About
{
public const string BaseAboutApiPath = BaseApiPath + "/about";

public const string VersionApiPath = BaseAboutApiPath + "/version" + OutputFormat;
public const string ManifestApiPath = BaseAboutApiPath + "/manifest" + OutputFormat;
public const string SystemStatusApiPath = BaseAboutApiPath + "/system-status" + OutputFormat;
}

public static class Layers
{
public const string BaseLayersApiPath = BaseApiPath + "/layers";
public const string GetLayersApiPath = BaseLayersApiPath + OutputFormat;

}
}

}
26 changes: 26 additions & 0 deletions src/GeoServer.Net/Contracts/IGeoServerAboutClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using GeoServer.Net.Responses.About;

namespace GeoServer.Net.Contracts;

public interface IGeoServerAboutClient
{
/// <summary>
/// Retrieve the versions of the main components: GeoServer, GeoTools, and GeoWebCache
/// http://localhost:8080/geoserver/rest/about/version.json
/// </summary>
/// <returns></returns>
Task<GeoServerAboutVersionResponse> GetVersionAsync();
/// <summary>
/// Retrieve the full manifest and subsets of the manifest as known to the ClassLoader
/// http://localhost:8080/geoserver/rest/about/manifest.json
/// </summary>
/// <returns></returns>
Task<GeoServerAboutManifestResponse> GetManifestAsync();
/// <summary>
/// It is possible to request the available system information (monitoring data) through the GeoServer REST API.
/// The supported formats are XML, JSON and HTML.
/// https://docs.geoserver.org/stable/en/user/rest/about.html#system-status
/// </summary>
/// <returns></returns>
Task<GeoServerAboutSystemStatusResponse> GetSystemStatusAsync();
}
3 changes: 3 additions & 0 deletions src/GeoServer.Net/Contracts/IGeoServerClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace GeoServer.Net.Contracts;

public interface IGeoServerClient: IGeoServerAboutClient, IGeoServerLayersClient;
16 changes: 16 additions & 0 deletions src/GeoServer.Net/Contracts/IGeoServerLayersClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using GeoServer.Net.Responses.Layers;

namespace GeoServer.Net.Contracts;

/// <summary>
/// https://docs.geoserver.org/latest/en/api/#1.0.0/layers.yaml
/// </summary>
public interface IGeoServerLayersClient
{
/// <summary>
/// Displays a list of all layers on the server. You must use the “Accept:” header to specify format or append an extension to the endpoint (example “/layers.xml” for XML)
/// http://localhost:8080/geoserver/rest/layers.json
/// </summary>
/// <returns></returns>
Task<GeoServerLayersListResponse> GetLayersListAsync();
}
3 changes: 3 additions & 0 deletions src/GeoServer.Net/Exceptions/GeoServerHttpRequestException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace GeoServer.Net.Exceptions;

public class GeoServerHttpRequestException(string message) : HttpRequestException(message);
12 changes: 12 additions & 0 deletions src/GeoServer.Net/GeoServer.Net.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<Folder Include="Requests\" />
</ItemGroup>

</Project>
74 changes: 74 additions & 0 deletions src/GeoServer.Net/GeoServerClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Text;
using GeoServer.Net.Constants;
using GeoServer.Net.Contracts;
using GeoServer.Net.Exceptions;
using GeoServer.Net.Responses.About;
using GeoServer.Net.Responses.Layers;

namespace GeoServer.Net;

/// <summary>
/// https://docs.geoserver.org/stable/en/user/rest/about.html
/// </summary>
public class GeoServerClient: HttpClient, IGeoServerClient
{
private readonly string _url;

public GeoServerClient(string url, string username, string password)
{
_url = url;
var baseUri = new Uri(_url);
BaseAddress = baseUri;
DefaultRequestHeaders.Clear();
DefaultRequestHeaders.ConnectionClose = true;

var authenticationString = $"{username}:{password}";
var base64EncodedAuthenticationString = Convert.ToBase64String(Encoding.UTF8.GetBytes(authenticationString));

DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64EncodedAuthenticationString);

}

/// <summary>
/// Retrieve the versions of the main components: GeoServer, GeoTools, and GeoWebCache
/// https://docs.geoserver.org/stable/en/user/rest/about.html
/// </summary>
/// <returns></returns>
public async Task<GeoServerAboutVersionResponse> GetVersionAsync()
{
var response = await GetAsync(_url + ApiConsts.Endpoints.About.VersionApiPath);
if(!response.IsSuccessStatusCode) throw new GeoServerHttpRequestException(response.StatusCode.ToString());
//var result = await response.Content.ReadAsStringAsync();
var result = await response.Content.ReadFromJsonAsync<GeoServerAboutVersionResponse>();
return result;
}

public async Task<GeoServerAboutManifestResponse> GetManifestAsync()
{
var response = await GetAsync(_url + ApiConsts.Endpoints.About.ManifestApiPath);
if (!response.IsSuccessStatusCode) throw new GeoServerHttpRequestException(response.StatusCode.ToString());
//var result = await response.Content.ReadAsStringAsync();
var result = await response.Content.ReadFromJsonAsync<GeoServerAboutManifestResponse>();
return result;
}

public async Task<GeoServerAboutSystemStatusResponse> GetSystemStatusAsync()
{
var response = await GetAsync(_url + ApiConsts.Endpoints.About.SystemStatusApiPath);
if (!response.IsSuccessStatusCode) throw new GeoServerHttpRequestException(response.StatusCode.ToString());
//var result = await response.Content.ReadAsStringAsync();
var result = await response.Content.ReadFromJsonAsync<GeoServerAboutSystemStatusResponse>();
return result;
}

public async Task<GeoServerLayersListResponse> GetLayersListAsync()
{
var response = await GetAsync(_url + ApiConsts.Endpoints.Layers.GetLayersApiPath);
if (!response.IsSuccessStatusCode) throw new GeoServerHttpRequestException(response.StatusCode.ToString());
//var result = await response.Content.ReadAsStringAsync();
var result = await response.Content.ReadFromJsonAsync<GeoServerLayersListResponse>();
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Text.Json.Serialization;

namespace GeoServer.Net.Responses.About.Base;

public abstract class GeoServerAboutBaseResponse<TModel>
{
[JsonPropertyName("about")]
public GeoServerAboutResponse<TModel> About { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Text.Json.Serialization;

namespace GeoServer.Net.Responses.About.Base;

public class GeoServerAboutResponse<TResource>
{
[JsonPropertyName("resource")]
public TResource[] Resources { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
using GeoServer.Net.Responses.About.Base;
using System.Text.Json.Serialization;

namespace GeoServer.Net.Responses.About;

public class GeoServerAboutManifestResponse:GeoServerAboutBaseResponse<Manifest>
{

}

public class Manifest
{
[JsonPropertyName("@name")]
public string Name { get; set; }
[JsonPropertyName("Archiver-Version")]
public string ArchiverVersion { get; set; }
[JsonPropertyName("Bundle-License")]
public string BundleLicense { get; set; }
[JsonPropertyName("Specification-Version")]
public object SpecificationVersion { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Text.Json.Serialization;

namespace GeoServer.Net.Responses.About;

public class GeoServerAboutSystemStatusResponse
{
[JsonPropertyName("metrics")]
public Metrics Metrics { get; set; }
}

public class Metrics
{
[JsonPropertyName("metric")]
public Metric[] Metric { get; set; }
}

public class Metric
{
[JsonPropertyName("available")]
public bool Available { get; set; }
[JsonPropertyName("description")]
public string Description { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("unit")]
public string Unit { get; set; }
[JsonPropertyName("category")]
public string Category { get; set; }
[JsonPropertyName("identifier")]
public string Identifier { get; set; }
[JsonPropertyName("priority")]
public int Priority { get; set; }
[JsonPropertyName("value")]
public string Value { get; set; }
}
22 changes: 22 additions & 0 deletions src/GeoServer.Net/Responses/About/GeoServerAboutVersionResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System.Text.Json.Serialization;
using GeoServer.Net.Responses.About.Base;

namespace GeoServer.Net.Responses.About;

public class GeoServerAboutVersionResponse: GeoServerAboutBaseResponse<Resource>
{
}



public class Resource
{
[JsonPropertyName("@name")]
public string Name { get; set; }
[JsonPropertyName("Build-Timestamp")]
public string BuildTimestamp { get; set; }
[JsonPropertyName("Version")]
public object Version { get; set; }
[JsonPropertyName("Git-Revision")]
public string GitRevision { get; set; }
}
24 changes: 24 additions & 0 deletions src/GeoServer.Net/Responses/Layers/GeoServerLayersListResponse.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System.Text.Json.Serialization;

namespace GeoServer.Net.Responses.Layers;

public class GeoServerLayersListResponse
{
[JsonPropertyName("layers")]
public Layers Layers { get; set; }
}


public class Layers
{
[JsonPropertyName("layer")]
public Layer[] Layer { get; set; }
}

public class Layer
{
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("href")]
public string Href { get; set; }
}
33 changes: 33 additions & 0 deletions test/GeoServer.Net.Tests/AboutEndpointsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using FluentAssertions;
using GeoServer.Net.Contracts;

namespace GeoServer.Net.Tests;

public class AboutEndpointsTests
{
private readonly IGeoServerAboutClient _geoServerClient = new GeoServerClient(GeneralConfigurations.GeoServerUrl, GeneralConfigurations.UserName, GeneralConfigurations.Password);

[Fact]
public async Task GetVersionTest()
{
var response = await _geoServerClient.GetVersionAsync();
response.Should().NotBeNull();
response.About.Resources.Length.Should().BeGreaterThan(0);
}

[Fact]
public async Task GetManifestTest()
{
var response = await _geoServerClient.GetManifestAsync();
response.Should().NotBeNull();
response.About.Resources.Length.Should().BeGreaterThan(0);
}

[Fact]
public async Task GetSystemStatusTest()
{
var response = await _geoServerClient.GetSystemStatusAsync();
response.Should().NotBeNull();
response.Metrics.Metric.Length.Should().BeGreaterThan(0);
}
}
Loading

0 comments on commit 487dc21

Please sign in to comment.