up
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
AOC Guard CI / aoc-guard (push) Has been cancelled
AOC Guard CI / aoc-verify (push) Has been cancelled
Concelier Attestation Tests / attestation-tests (push) Has been cancelled
Export Center CI / export-ci (push) Has been cancelled
Notify Smoke Test / Notify Unit Tests (push) Has been cancelled
Notify Smoke Test / Notifier Service Tests (push) Has been cancelled
Notify Smoke Test / Notification Smoke Test (push) Has been cancelled
Policy Lint & Smoke / policy-lint (push) Has been cancelled
Scanner Analyzers / Discover Analyzers (push) Has been cancelled
Scanner Analyzers / Build Analyzers (push) Has been cancelled
Scanner Analyzers / Test Language Analyzers (push) Has been cancelled
Scanner Analyzers / Validate Test Fixtures (push) Has been cancelled
Scanner Analyzers / Verify Deterministic Output (push) Has been cancelled
Signals CI & Image / signals-ci (push) Has been cancelled
Signals Reachability Scoring & Events / reachability-smoke (push) Has been cancelled
Signals Reachability Scoring & Events / sign-and-upload (push) Has been cancelled
This commit is contained in:
@@ -1,94 +1,94 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using StellaOps.Concelier.Models;
|
||||
using StellaOps.Concelier.Connector.Ics.Cisa;
|
||||
using StellaOps.Concelier.Connector.Ics.Cisa.Internal;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Concelier.Connector.Ics.Cisa.Tests.IcsCisa;
|
||||
|
||||
public class IcsCisaConnectorMappingTests
|
||||
{
|
||||
private static readonly DateTimeOffset RecordedAt = new(2025, 10, 14, 12, 0, 0, TimeSpan.Zero);
|
||||
|
||||
[Fact]
|
||||
public void BuildReferences_MergesFeedAndDetailAttachments()
|
||||
{
|
||||
var dto = new IcsCisaAdvisoryDto
|
||||
{
|
||||
AdvisoryId = "ICSA-25-123-01",
|
||||
Title = "Sample Advisory",
|
||||
Link = "https://www.cisa.gov/news-events/ics-advisories/icsa-25-123-01",
|
||||
Summary = "Summary",
|
||||
DescriptionHtml = "<p>Summary</p>",
|
||||
Published = RecordedAt,
|
||||
Updated = RecordedAt,
|
||||
IsMedical = false,
|
||||
References = new[]
|
||||
{
|
||||
"https://example.org/advisory",
|
||||
"https://www.cisa.gov/news-events/ics-advisories/icsa-25-123-01"
|
||||
},
|
||||
Attachments = new List<IcsCisaAttachmentDto>
|
||||
{
|
||||
new() { Title = "PDF Attachment", Url = "https://files.cisa.gov/docs/icsa-25-123-01.pdf" },
|
||||
}
|
||||
};
|
||||
|
||||
var references = IcsCisaConnector.BuildReferences(dto, RecordedAt);
|
||||
|
||||
Assert.Equal(3, references.Count);
|
||||
Assert.Contains(references, reference => reference.Kind == "attachment" && reference.Url == "https://files.cisa.gov/docs/icsa-25-123-01.pdf");
|
||||
Assert.Contains(references, reference => reference.Url == "https://example.org/advisory");
|
||||
Assert.Contains(references, reference => reference.Url == "https://www.cisa.gov/news-events/ics-advisories/icsa-25-123-01");
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void BuildMitigationReferences_ProducesReferences()
|
||||
{
|
||||
var dto = new IcsCisaAdvisoryDto
|
||||
{
|
||||
AdvisoryId = "ICSA-25-999-01",
|
||||
Title = "Mitigation Test",
|
||||
Link = "https://www.cisa.gov/news-events/ics-advisories/icsa-25-999-01",
|
||||
Mitigations = new[] { "Apply firmware 9.9.1", "Limit network access" },
|
||||
Published = RecordedAt,
|
||||
Updated = RecordedAt,
|
||||
IsMedical = false,
|
||||
};
|
||||
|
||||
var references = IcsCisaConnector.BuildMitigationReferences(dto, RecordedAt);
|
||||
|
||||
Assert.Equal(2, references.Count);
|
||||
var first = references.First();
|
||||
Assert.Equal("mitigation", first.Kind);
|
||||
Assert.Equal("icscisa-mitigation", first.SourceTag);
|
||||
Assert.EndsWith("#mitigation-1", first.Url, StringComparison.Ordinal);
|
||||
Assert.Contains("Apply firmware", first.Summary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using StellaOps.Concelier.Models;
|
||||
using StellaOps.Concelier.Connector.Ics.Cisa;
|
||||
using StellaOps.Concelier.Connector.Ics.Cisa.Internal;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Concelier.Connector.Ics.Cisa.Tests.IcsCisa;
|
||||
|
||||
public class IcsCisaConnectorMappingTests
|
||||
{
|
||||
private static readonly DateTimeOffset RecordedAt = new(2025, 10, 14, 12, 0, 0, TimeSpan.Zero);
|
||||
|
||||
[Fact]
|
||||
public void BuildReferences_MergesFeedAndDetailAttachments()
|
||||
{
|
||||
var dto = new IcsCisaAdvisoryDto
|
||||
{
|
||||
AdvisoryId = "ICSA-25-123-01",
|
||||
Title = "Sample Advisory",
|
||||
Link = "https://www.cisa.gov/news-events/ics-advisories/icsa-25-123-01",
|
||||
Summary = "Summary",
|
||||
DescriptionHtml = "<p>Summary</p>",
|
||||
Published = RecordedAt,
|
||||
Updated = RecordedAt,
|
||||
IsMedical = false,
|
||||
References = new[]
|
||||
{
|
||||
"https://example.org/advisory",
|
||||
"https://www.cisa.gov/news-events/ics-advisories/icsa-25-123-01"
|
||||
},
|
||||
Attachments = new List<IcsCisaAttachmentDto>
|
||||
{
|
||||
new() { Title = "PDF Attachment", Url = "https://files.cisa.gov/docs/icsa-25-123-01.pdf" },
|
||||
}
|
||||
};
|
||||
|
||||
var references = IcsCisaConnector.BuildReferences(dto, RecordedAt);
|
||||
|
||||
Assert.Equal(3, references.Count);
|
||||
Assert.Contains(references, reference => reference.Kind == "attachment" && reference.Url == "https://files.cisa.gov/docs/icsa-25-123-01.pdf");
|
||||
Assert.Contains(references, reference => reference.Url == "https://example.org/advisory");
|
||||
Assert.Contains(references, reference => reference.Url == "https://www.cisa.gov/news-events/ics-advisories/icsa-25-123-01");
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void BuildMitigationReferences_ProducesReferences()
|
||||
{
|
||||
var dto = new IcsCisaAdvisoryDto
|
||||
{
|
||||
AdvisoryId = "ICSA-25-999-01",
|
||||
Title = "Mitigation Test",
|
||||
Link = "https://www.cisa.gov/news-events/ics-advisories/icsa-25-999-01",
|
||||
Mitigations = new[] { "Apply firmware 9.9.1", "Limit network access" },
|
||||
Published = RecordedAt,
|
||||
Updated = RecordedAt,
|
||||
IsMedical = false,
|
||||
};
|
||||
|
||||
var references = IcsCisaConnector.BuildMitigationReferences(dto, RecordedAt);
|
||||
|
||||
Assert.Equal(2, references.Count);
|
||||
var first = references.First();
|
||||
Assert.Equal("mitigation", first.Kind);
|
||||
Assert.Equal("icscisa-mitigation", first.SourceTag);
|
||||
Assert.EndsWith("#mitigation-1", first.Url, StringComparison.Ordinal);
|
||||
Assert.Contains("Apply firmware", first.Summary);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void BuildAffectedPackages_EmitsProductRangesWithSemVer()
|
||||
{
|
||||
var dto = new IcsCisaAdvisoryDto
|
||||
{
|
||||
AdvisoryId = "ICSA-25-456-02",
|
||||
Title = "Vendor Advisory",
|
||||
Link = "https://www.cisa.gov/news-events/ics-advisories/icsa-25-456-02",
|
||||
DescriptionHtml = "",
|
||||
Summary = null,
|
||||
Published = RecordedAt,
|
||||
Vendors = new[] { "Example Corp" },
|
||||
Products = new[] { "ControlSuite 4.2" }
|
||||
};
|
||||
|
||||
var packages = IcsCisaConnector.BuildAffectedPackages(dto, RecordedAt);
|
||||
|
||||
var productPackage = Assert.Single(packages);
|
||||
Assert.Equal(AffectedPackageTypes.IcsVendor, productPackage.Type);
|
||||
Assert.Equal("ControlSuite", productPackage.Identifier);
|
||||
Title = "Vendor Advisory",
|
||||
Link = "https://www.cisa.gov/news-events/ics-advisories/icsa-25-456-02",
|
||||
DescriptionHtml = "",
|
||||
Summary = null,
|
||||
Published = RecordedAt,
|
||||
Vendors = new[] { "Example Corp" },
|
||||
Products = new[] { "ControlSuite 4.2" }
|
||||
};
|
||||
|
||||
var packages = IcsCisaConnector.BuildAffectedPackages(dto, RecordedAt);
|
||||
|
||||
var productPackage = Assert.Single(packages);
|
||||
Assert.Equal(AffectedPackageTypes.IcsVendor, productPackage.Type);
|
||||
Assert.Equal("ControlSuite", productPackage.Identifier);
|
||||
var range = Assert.Single(productPackage.VersionRanges);
|
||||
Assert.Equal("product", range.RangeKind);
|
||||
Assert.Equal("4.2", range.RangeExpression);
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using StellaOps.Concelier.Connector.Ics.Cisa.Internal;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Concelier.Connector.Ics.Cisa.Tests.IcsCisa;
|
||||
|
||||
public class IcsCisaFeedParserTests
|
||||
{
|
||||
[Fact]
|
||||
public void Parse_ReturnsAdvisories()
|
||||
{
|
||||
var parser = new IcsCisaFeedParser();
|
||||
using var stream = File.OpenRead(Path.Combine("IcsCisa", "Fixtures", "sample-feed.xml"));
|
||||
|
||||
var advisories = parser.Parse(stream, isMedicalTopic: false, topicUri: new Uri("https://content.govdelivery.com/accounts/USDHSCISA/topics.rss"));
|
||||
|
||||
Assert.Equal(2, advisories.Count);
|
||||
|
||||
var first = advisories.First();
|
||||
Console.WriteLine("Description:" + first.DescriptionHtml);
|
||||
Console.WriteLine("Attachments:" + string.Join(",", first.Attachments.Select(a => a.Url)));
|
||||
Console.WriteLine("References:" + string.Join(",", first.References));
|
||||
Assert.Equal("ICSA-25-123-01", first.AdvisoryId);
|
||||
Assert.Contains("CVE-2024-12345", first.CveIds);
|
||||
Assert.Contains("Example Corp", first.Vendors);
|
||||
Assert.Contains("ControlSuite 4.2", first.Products);
|
||||
Assert.Contains(first.Attachments, attachment => attachment.Url == "https://example.com/security/icsa-25-123-01.pdf");
|
||||
Assert.Contains(first.References, reference => reference == "https://www.cisa.gov/news-events/ics-advisories/icsa-25-123-01");
|
||||
|
||||
var second = advisories.Last();
|
||||
Assert.True(second.IsMedical);
|
||||
Assert.Contains("CVE-2025-11111", second.CveIds);
|
||||
Assert.Contains("HealthTech", second.Vendors);
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using StellaOps.Concelier.Connector.Ics.Cisa.Internal;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Concelier.Connector.Ics.Cisa.Tests.IcsCisa;
|
||||
|
||||
public class IcsCisaFeedParserTests
|
||||
{
|
||||
[Fact]
|
||||
public void Parse_ReturnsAdvisories()
|
||||
{
|
||||
var parser = new IcsCisaFeedParser();
|
||||
using var stream = File.OpenRead(Path.Combine("IcsCisa", "Fixtures", "sample-feed.xml"));
|
||||
|
||||
var advisories = parser.Parse(stream, isMedicalTopic: false, topicUri: new Uri("https://content.govdelivery.com/accounts/USDHSCISA/topics.rss"));
|
||||
|
||||
Assert.Equal(2, advisories.Count);
|
||||
|
||||
var first = advisories.First();
|
||||
Console.WriteLine("Description:" + first.DescriptionHtml);
|
||||
Console.WriteLine("Attachments:" + string.Join(",", first.Attachments.Select(a => a.Url)));
|
||||
Console.WriteLine("References:" + string.Join(",", first.References));
|
||||
Assert.Equal("ICSA-25-123-01", first.AdvisoryId);
|
||||
Assert.Contains("CVE-2024-12345", first.CveIds);
|
||||
Assert.Contains("Example Corp", first.Vendors);
|
||||
Assert.Contains("ControlSuite 4.2", first.Products);
|
||||
Assert.Contains(first.Attachments, attachment => attachment.Url == "https://example.com/security/icsa-25-123-01.pdf");
|
||||
Assert.Contains(first.References, reference => reference == "https://www.cisa.gov/news-events/ics-advisories/icsa-25-123-01");
|
||||
|
||||
var second = advisories.Last();
|
||||
Assert.True(second.IsMedical);
|
||||
Assert.Contains("CVE-2025-11111", second.CveIds);
|
||||
Assert.Contains("HealthTech", second.Vendors);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@@ -14,9 +14,9 @@ using StellaOps.Concelier.Storage;
|
||||
using StellaOps.Concelier.Storage.Advisories;
|
||||
using StellaOps.Concelier.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace StellaOps.Concelier.Connector.Ics.Cisa.Tests;
|
||||
|
||||
|
||||
namespace StellaOps.Concelier.Connector.Ics.Cisa.Tests;
|
||||
|
||||
[Collection(ConcelierFixtureCollection.Name)]
|
||||
public sealed class IcsCisaConnectorTests
|
||||
{
|
||||
@@ -26,7 +26,7 @@ public sealed class IcsCisaConnectorTests
|
||||
{
|
||||
_fixture = fixture ?? throw new ArgumentNullException(nameof(fixture));
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public async Task FetchParseMap_EndToEnd_ProducesCanonicalAdvisories()
|
||||
{
|
||||
@@ -42,37 +42,37 @@ public sealed class IcsCisaConnectorTests
|
||||
|
||||
var advisoryStore = harness.ServiceProvider.GetRequiredService<IAdvisoryStore>();
|
||||
var advisories = await advisoryStore.GetRecentAsync(10, CancellationToken.None);
|
||||
|
||||
Assert.Equal(2, advisories.Count);
|
||||
|
||||
|
||||
Assert.Equal(2, advisories.Count);
|
||||
|
||||
var icsa = Assert.Single(advisories, advisory => advisory.AdvisoryKey == "ICSA-25-123-01");
|
||||
Assert.Contains("CVE-2024-12345", icsa.Aliases);
|
||||
Assert.Contains(icsa.References, reference => reference.Url == "https://example.com/security/icsa-25-123-01");
|
||||
Assert.Contains(icsa.References, reference => reference.Url == "https://files.cisa.gov/docs/icsa-25-123-01.pdf" && reference.Kind == "attachment");
|
||||
var icsaMitigations = icsa.References.Where(reference => reference.Kind == "mitigation").ToList();
|
||||
Assert.Equal(2, icsaMitigations.Count);
|
||||
Assert.Contains("Apply ControlSuite firmware version 4.2.1 or later.", icsaMitigations[0].Summary, StringComparison.Ordinal);
|
||||
Assert.EndsWith("#mitigation-1", icsaMitigations[0].Url, StringComparison.Ordinal);
|
||||
Assert.Contains("Restrict network access", icsaMitigations[1].Summary, StringComparison.Ordinal);
|
||||
|
||||
var controlSuitePackage = Assert.Single(icsa.AffectedPackages, package => string.Equals(package.Identifier, "ControlSuite", StringComparison.OrdinalIgnoreCase));
|
||||
var controlSuiteRange = Assert.Single(controlSuitePackage.VersionRanges);
|
||||
Assert.Equal("product", controlSuiteRange.RangeKind);
|
||||
Assert.Equal("4.2", controlSuiteRange.RangeExpression);
|
||||
Assert.NotNull(controlSuiteRange.Primitives);
|
||||
Assert.NotNull(controlSuiteRange.Primitives!.SemVer);
|
||||
Assert.Equal("4.2.0", controlSuiteRange.Primitives.SemVer!.ExactValue);
|
||||
Assert.True(controlSuiteRange.Primitives.VendorExtensions!.TryGetValue("ics.product", out var controlSuiteProduct) && controlSuiteProduct == "ControlSuite");
|
||||
Assert.True(controlSuiteRange.Primitives.VendorExtensions!.TryGetValue("ics.version", out var controlSuiteVersion) && controlSuiteVersion == "4.2");
|
||||
Assert.True(controlSuiteRange.Primitives.VendorExtensions!.TryGetValue("ics.vendors", out var controlSuiteVendors) && controlSuiteVendors == "Example Corp");
|
||||
|
||||
var icsma = Assert.Single(advisories, advisory => advisory.AdvisoryKey == "ICSMA-25-045-01");
|
||||
Assert.Contains("CVE-2025-11111", icsma.Aliases);
|
||||
var icsmaMitigation = Assert.Single(icsma.References.Where(reference => reference.Kind == "mitigation"));
|
||||
Assert.Contains("Contact HealthTech support", icsmaMitigation.Summary, StringComparison.Ordinal);
|
||||
Assert.Contains(icsma.References, reference => reference.Url == "https://www.cisa.gov/sites/default/files/2025-10/ICSMA-25-045-01_Supplement.pdf");
|
||||
var infusionPackage = Assert.Single(icsma.AffectedPackages, package => string.Equals(package.Identifier, "InfusionManager", StringComparison.OrdinalIgnoreCase));
|
||||
var infusionRange = Assert.Single(infusionPackage.VersionRanges);
|
||||
Assert.Contains("CVE-2024-12345", icsa.Aliases);
|
||||
Assert.Contains(icsa.References, reference => reference.Url == "https://example.com/security/icsa-25-123-01");
|
||||
Assert.Contains(icsa.References, reference => reference.Url == "https://files.cisa.gov/docs/icsa-25-123-01.pdf" && reference.Kind == "attachment");
|
||||
var icsaMitigations = icsa.References.Where(reference => reference.Kind == "mitigation").ToList();
|
||||
Assert.Equal(2, icsaMitigations.Count);
|
||||
Assert.Contains("Apply ControlSuite firmware version 4.2.1 or later.", icsaMitigations[0].Summary, StringComparison.Ordinal);
|
||||
Assert.EndsWith("#mitigation-1", icsaMitigations[0].Url, StringComparison.Ordinal);
|
||||
Assert.Contains("Restrict network access", icsaMitigations[1].Summary, StringComparison.Ordinal);
|
||||
|
||||
var controlSuitePackage = Assert.Single(icsa.AffectedPackages, package => string.Equals(package.Identifier, "ControlSuite", StringComparison.OrdinalIgnoreCase));
|
||||
var controlSuiteRange = Assert.Single(controlSuitePackage.VersionRanges);
|
||||
Assert.Equal("product", controlSuiteRange.RangeKind);
|
||||
Assert.Equal("4.2", controlSuiteRange.RangeExpression);
|
||||
Assert.NotNull(controlSuiteRange.Primitives);
|
||||
Assert.NotNull(controlSuiteRange.Primitives!.SemVer);
|
||||
Assert.Equal("4.2.0", controlSuiteRange.Primitives.SemVer!.ExactValue);
|
||||
Assert.True(controlSuiteRange.Primitives.VendorExtensions!.TryGetValue("ics.product", out var controlSuiteProduct) && controlSuiteProduct == "ControlSuite");
|
||||
Assert.True(controlSuiteRange.Primitives.VendorExtensions!.TryGetValue("ics.version", out var controlSuiteVersion) && controlSuiteVersion == "4.2");
|
||||
Assert.True(controlSuiteRange.Primitives.VendorExtensions!.TryGetValue("ics.vendors", out var controlSuiteVendors) && controlSuiteVendors == "Example Corp");
|
||||
|
||||
var icsma = Assert.Single(advisories, advisory => advisory.AdvisoryKey == "ICSMA-25-045-01");
|
||||
Assert.Contains("CVE-2025-11111", icsma.Aliases);
|
||||
var icsmaMitigation = Assert.Single(icsma.References.Where(reference => reference.Kind == "mitigation"));
|
||||
Assert.Contains("Contact HealthTech support", icsmaMitigation.Summary, StringComparison.Ordinal);
|
||||
Assert.Contains(icsma.References, reference => reference.Url == "https://www.cisa.gov/sites/default/files/2025-10/ICSMA-25-045-01_Supplement.pdf");
|
||||
var infusionPackage = Assert.Single(icsma.AffectedPackages, package => string.Equals(package.Identifier, "InfusionManager", StringComparison.OrdinalIgnoreCase));
|
||||
var infusionRange = Assert.Single(infusionPackage.VersionRanges);
|
||||
Assert.Equal("2.1", infusionRange.RangeExpression);
|
||||
}
|
||||
|
||||
@@ -107,11 +107,11 @@ public sealed class IcsCisaConnectorTests
|
||||
var icsmaDetail = new Uri("https://www.cisa.gov/news-events/ics-medical-advisories/icsma-25-045-01", UriKind.Absolute);
|
||||
handler.AddResponse(icsmaDetail, () => CreateTextResponse("IcsCisa/Fixtures/icsma-25-045-01.html", "text/html"));
|
||||
}
|
||||
|
||||
private static HttpResponseMessage CreateTextResponse(string relativePath, string contentType)
|
||||
{
|
||||
var fullPath = Path.Combine(AppContext.BaseDirectory, relativePath);
|
||||
var content = File.ReadAllText(fullPath);
|
||||
|
||||
private static HttpResponseMessage CreateTextResponse(string relativePath, string contentType)
|
||||
{
|
||||
var fullPath = Path.Combine(AppContext.BaseDirectory, relativePath);
|
||||
var content = File.ReadAllText(fullPath);
|
||||
return new HttpResponseMessage(HttpStatusCode.OK)
|
||||
{
|
||||
Content = new StringContent(content, Encoding.UTF8, contentType),
|
||||
|
||||
Reference in New Issue
Block a user