Skip to content

Commit

Permalink
Merge pull request #45 from digirati-co-uk/feature/imgrequest_rejects…
Browse files Browse the repository at this point in the history
…_badparams

Allow `ImageRequest.Parse` to optionally reject bad parameters
  • Loading branch information
griffri authored Jul 12, 2024
2 parents a7174e3 + edb2dc0 commit 5c0c9b2
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 4 deletions.
88 changes: 86 additions & 2 deletions src/IIIF/IIIF.Tests/ImageApi/ImageRequestXTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using FluentAssertions;
using System;
using FluentAssertions;
using IIIF.ImageApi;
using Xunit;

namespace IIIF.Tests.ImageApi;

Expand Down Expand Up @@ -221,4 +221,88 @@ public void Parse_CorrectPercentageScaled()
// Assert
result.Should().BeEquivalentTo(expected);
}

[Theory]
[InlineData("my-asset")]
[InlineData("my-asset/")]
public void Parse_IsBase(string path)
{
// Arrange and Act
const string prefix = "iiif-img/27/1/";
var result = ImageRequest.Parse($"{prefix}{path}", prefix);

// Assert
result.IsBase.Should().BeTrue();
}

[Fact]
public void Parse_InfoJson()
{
// Arrange and Act
const string prefix = "iiif-img/27/1/";
var result = ImageRequest.Parse($"{prefix}my-asset/info.json", prefix);

// Assert
result.IsInformationRequest.Should().BeTrue();
}

[Fact]
public void Parse_Fails_WhenInfoHasInvalidExtension()
{
// Arrange and Act
const string prefix = "iiif-img/27/1/";
var action = () => ImageRequest.Parse($"{prefix}my-asset/info.jsonll", prefix);

// Assert
action.Should().ThrowExactly<ArgumentException>();
}

[Theory]
[InlineData("iiif-img/27/1/")]
[InlineData("/iiif-img/27/1/")]
[InlineData("/iiif-img/27/1")]
[InlineData("iiif-img/27/1")]
public void Parse_Validate_HandlesPrefixFormats(string prefix)
{
// Arrange and Act
const string request = $"iiif-img/27/1/my-asset/full/800,/0/default.jpg";
var action = () => ImageRequest.Parse(request, prefix, true);

// Assert
action.Should().NotThrow<ArgumentException>();
}

[Theory]
[InlineData("my-asset//full/800,/0/default.jpg")]
[InlineData("my-asset/full//800,/0/default.jpg")]
[InlineData("my-asset/full/800,//0/default.jpg")]
[InlineData("my-asset/full/800,/0//default.jpg")]
public void Parse_Validate_Fails_WhenGivenExtraSegments(string path)
{
// Arrange and Act
const string prefix = "iiif-img/27/1/";
var action = () => ImageRequest.Parse($"{prefix}{path}", prefix, true);

// Assert
action.Should().ThrowExactly<ArgumentException>()
.WithMessage("Path contains empty or an invalid number of segments");
}

[Theory]
[InlineData("my-asset//800,/0/default.jpg")]
[InlineData("my-asset/full//0/default.jpg")]
[InlineData("my-asset/full/800,//default.jpg")]
[InlineData("my-asset/full/800,/0/")]
[InlineData("my-asset////default.jpg")]
[InlineData("my-asset////")]
public void Parse_Validate_Fails_WhenGivenEmptyParameters(string path)
{
// Arrange and Act
const string prefix = "iiif-img/27/1/";
var action = () => ImageRequest.Parse($"{prefix}{path}", prefix, true);

// Assert
action.Should().ThrowExactly<ArgumentException>()
.WithMessage("Path contains empty or an invalid number of segments");
}
}
22 changes: 20 additions & 2 deletions src/IIIF/IIIF/ImageApi/ImageRequest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Linq;

namespace IIIF.ImageApi;

Expand All @@ -25,7 +26,15 @@ public class ImageRequest
/// </summary>
public string ImageRequestPath => OriginalPath.Replace(Identifier, string.Empty);

public static ImageRequest Parse(string path, string prefix)
/// <summary>
/// Parses an image request path as a IIIF ImageRequest object
/// </summary>
/// <returns>A ImageRequest object</returns>
/// <param name="path">The image request path</param>
/// <param name="prefix">The image request prefix</param>
/// <param name="validateSegments">If true, throws an ArgumentException if the image request contains empty values,
/// or an invalid number of segments</param>
public static ImageRequest Parse(string path, string prefix, bool validateSegments = false)
{
if (path[0] == '/') path = path[1..];

Expand All @@ -35,12 +44,16 @@ public static ImageRequest Parse(string path, string prefix)
if (prefix != path[..prefix.Length])
throw new ArgumentException("Path does not start with prefix", nameof(prefix));
path = path[prefix.Length..];
if (path[0] == '/') path = path[1..];
}

var request = new ImageRequest { Prefix = prefix };

var parts = path.Split('/');

request.Identifier = parts[0];
if (parts.Length == 1 || parts[1] == string.Empty)

if (parts.Length == 1 || (parts.Length == 2 && parts[1] == string.Empty))
{
// likely the server will want to redirect this
request.IsBase = true;
Expand All @@ -52,6 +65,11 @@ public static ImageRequest Parse(string path, string prefix)
request.IsInformationRequest = true;
return request;
}

if (validateSegments && (parts.Length != 5 || parts.Any(string.IsNullOrEmpty)))
{
throw new ArgumentException("Path contains empty or an invalid number of segments");
}

request.OriginalPath = path;
request.Region = RegionParameter.Parse(parts[1]);
Expand Down

0 comments on commit 5c0c9b2

Please sign in to comment.