Phase 2 : service de lookup ISBN en cascade BnF puis OpenLibrary

Recuperation des metadonnees d'un livre a partir de son ISBN, cote serveur
uniquement (aucune interface, aucune persistance).

Cascade : BnF en ISBN-13, puis BnF en ISBN-10 converti, puis OpenLibrary.
La conversion 13 -> 10 est indispensable et non optionnelle : la BnF indexe
l'ISBN tel qu'imprime, les ouvrages d'avant 2007 ne portent qu'un ISBN-10 et
sont introuvables par l'EAN-13 que lit le scanner.

Toutes les notices trouvees sont remontees (jusqu'a 5) : un meme ISBN peut
correspondre a plusieurs reeditions, le choix revient a l'utilisateur.

Le double appel /isbn puis /authors d'OpenLibrary est bien fait, avec repli
sur l'oeuvre quand l'edition ne porte aucun auteur : c'est le bug de BookLogr
(titre rempli, auteur vide) qu'il ne faut pas reproduire.

La couverture vient toujours d'OpenLibrary, avec ?default=false pour obtenir
un 404 plutot qu'une image placeholder.

87 tests xUnit, sur fixtures enregistrees : aucune dependance au reseau.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mathieu
2026-08-17 22:22:47 +02:00
co-authored by Claude Opus 5
parent 4990e41f3e
commit f8f30dbcf7
37 changed files with 1661 additions and 0 deletions
+37
View File
@@ -0,0 +1,37 @@
using MaBibli.Api.Services.Isbn;
using MaBibli.Shared.Dtos;
namespace MaBibli.Api.Endpoints;
public static class IsbnEndpoints
{
/// <summary>
/// Expose le lookup ISBN. Aucune écriture en base : cet endpoint pré-remplit un formulaire,
/// il n'enregistre rien.
/// </summary>
public static IEndpointRouteBuilder MapIsbnEndpoints(this IEndpointRouteBuilder routes)
{
var groupe = routes.MapGroup("/api/isbn").WithTags("ISBN");
groupe.MapGet("/{isbn}", async (
string isbn,
IIsbnLookupService service,
CancellationToken ct) =>
{
var resultat = await service.RechercherAsync(isbn, ct);
return resultat is null
? Results.BadRequest(new { erreur = $"« {isbn} » n'est pas un ISBN valide." })
: Results.Ok(resultat);
})
.WithName("RechercherIsbn")
.WithSummary("Cherche les notices correspondant à un ISBN (cascade BnF → OpenLibrary).")
.WithDescription(
"Renvoie TOUS les candidats trouvés (jusqu'à 5) : un même ISBN peut correspondre à "
+ "plusieurs rééditions. Le choix revient à l'utilisateur.")
.Produces<ResultatLookupIsbn>()
.Produces(StatusCodes.Status400BadRequest);
return routes;
}
}