Kavita/API/Extensions/HttpExtensions.cs
Joseph Milazzo 0e19ba4a10
Manga Reader Shakeout (#1142)
* Fixed a unit test in ArchiveService

* Image scaling fixes

* removing test

* Added new layout mode (enum only) and cleaned up manga reader and wrote extra documentation

* Aligned code with cleanup

* Adding reverse classes for manga reading

* Disable options for layout modes that doesn't make sense.

* Cleaned up manga reader menu items to link to preferences options directly

* Work in progress, but rendering the correct page numbers for double. Need to rework caching logic so we can use existing image objects

* Pagination logic is now properly increasing page number an extra when double layout mode

* I can't figure out cachedImages to work properly with double pages, but doing it in a way where it handles downloading the image (and etag cache) + rendering the url, seems to work really well

* Double original fix, also flex squish fix

* Implemented last page on double which will load next chapter.

Fixed a bug where if GetImage from ReaderController threw an error, the chapter directory would be emptied, but the folder itself wasn't deleted.

* Fixed a bad if for double manga

* double class fix

* Cleanup up some console.logs

* Adjusted the caching for images in a reading session so they cache for 2 mins

* fixing webtoon image issue

* Tweaked the caching of images to 10 mins for reading. Fixed a bug where after webtoon, single image layout would be selected. Tweaked logic for handling prev/next pages on chapter boundaries.

* Fixed an issue where 2nd page would be skipped

* Fixed an issue where 2nd page would be skipped

* Fixed a skip page issue

* Misc css fixes

Co-authored-by: Robbie Davis <robbie@therobbiedavis.com>
2022-03-08 17:58:47 -08:00

60 lines
2.4 KiB
C#

using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using API.Helpers;
using Microsoft.AspNetCore.Http;
namespace API.Extensions
{
public static class HttpExtensions
{
public static void AddPaginationHeader(this HttpResponse response, int currentPage,
int itemsPerPage, int totalItems, int totalPages)
{
var paginationHeader = new PaginationHeader(currentPage, itemsPerPage, totalItems, totalPages);
var options = new JsonSerializerOptions()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};
response.Headers.Add("Pagination", JsonSerializer.Serialize(paginationHeader, options));
response.Headers.Add("Access-Control-Expose-Headers", "Pagination");
}
/// <summary>
/// Calculates SHA256 hash for a byte[] and sets as ETag. Ensures Cache-Control: private header is added.
/// </summary>
/// <param name="response"></param>
/// <param name="content">If byte[] is null or empty, will only add cache-control</param>
public static void AddCacheHeader(this HttpResponse response, byte[] content)
{
if (content == null || content.Length <= 0) return;
using var sha1 = SHA256.Create();
response.Headers.Add("ETag", string.Concat(sha1.ComputeHash(content).Select(x => x.ToString("X2"))));
}
/// <summary>
/// Calculates SHA256 hash for a cover image filename and sets as ETag. Ensures Cache-Control: private header is added.
/// </summary>
/// <param name="response"></param>
/// <param name="filename"></param>
/// <param name="maxAge">Maximum amount of seconds to set for Cache-Control</param>
public static void AddCacheHeader(this HttpResponse response, string filename, int maxAge = 10)
{
if (filename is not {Length: > 0}) return;
var hashContent = filename + File.GetLastWriteTimeUtc(filename);
using var sha1 = SHA256.Create();
response.Headers.Add("ETag", string.Concat(sha1.ComputeHash(Encoding.UTF8.GetBytes(hashContent)).Select(x => x.ToString("X2"))));
if (maxAge != 10)
{
response.Headers.CacheControl = $"max-age={maxAge}";
}
}
}
}