Vos documents restent les vôtres
Vos pages sont créées et vous reviennent aussitôt. Cette page dit ce que le service garde, et pour combien de temps.
Résumé
Imaginez la boutique du coin qui fait les doubles de clés. Vous tendez la vôtre, la machine en fait la copie en une minute, et vous repartez avec les deux dans la poche. Nous demander un document, c'est pareil. Vous tendez la description de la page que vous voulez, la machine la crée, et la page vous revient.
Pendant la création de la page, ce que vous avez envoyé séjourne dans la mémoire de la machine, comme un numéro de téléphone séjourne dans votre tête le temps de le composer. La page finie repart vers vous, et cette mémoire passe aussitôt au document suivant qui attend.
Cinq choses sont notées, et c'est toute la liste. Une ligne pour la facture, qui dit le nom de votre compte, le moment, combien de pages sont sorties, et un numéro qui représente ce document-là. Une ligne dans notre propre journal pour chaque document qui sort, qui dit le nom court sous lequel votre compte passe, combien de pages sont sorties et combien de temps ça a pris. Vos propres polices, si vous en envoyez et que votre compte est réglé pour cela : les formes des lettres sont mises dans un dossier qui vous appartient, pour que vous n'ayez jamais à les envoyer une seconde fois. Un court avertissement quand votre description mentionne quelque chose que le travail laisse ensuite de côté, comme une image que personne n'a placée ou une couleur avec laquelle rien n'a été peint. Et une ligne quand nous écartons une demande, ou quand notre propre machine casse, pour que quelqu'un puisse être réveillé.
Quand nous ne pouvons pas utiliser ce que vous nous avez envoyé, la réponse le dit et vous montre le morceau exact qui l'a arrêtée — le mot fautif, la ligne où il était, le nom que vous aviez donné à une image — pour que vous puissiez le corriger sans deviner. Cette réponse vous revient à vous, dans la réponse à votre propre demande, et elle s'arrête là : pas un de ces morceaux n'est écrit quelque part, et aucun n'est transmis à personne. La ligne que nous écrivons dit seulement qu'une demande a été écartée, et sous laquelle d'une poignée figée de rubriques.
Ce qui est écrit sur vos pages reste entre vous et elles. Les mots, les chiffres, les noms de vos clients, la photo que vous avez envoyée : ils arrivent, ils sont créés, et ils repartent avec le fichier. La facture sait combien il y avait de pages, et c'est tout ce qu'elle sait.
Le fichier fini contient ce que vous avez demandé, et cela seulement. Donnez-lui un titre, il a ce titre ; donnez-lui une date, il a cette date. Tout le reste de ce qu'il contient vient de vous, et c'est pour cela que demander deux fois le même document vous donne le même fichier jusqu'à la dernière lettre. C'est quelque chose que vous pouvez vérifier vous-même en une minute, et nous préférons que vous le fassiez.
Deux choses que vous pouvez demander changent cela, et ces deux-là seulement : un champ qui demande le moment où le document est créé, et un verrou que vous posez sans en donner la clé, qui est alors tirée au hasard.
Ce site et la machine qui crée sont deux choses distinctes. Ici, vous avez un compte, une adresse pour votre facture et votre clé d'API. Là-bas, vous êtes un nom court et un nombre de pages. Et si vous préférez que le tout se trouve chez vous, cette machine est vendue pour y être installée, auquel cas vos pages restent entre vos propres murs du début à la fin.
Les deux tiennent sur des machines en France : ce site et la machine qui crée. Un service que nous faisons tourner pour un de nos clients tourne sur des machines qui s'y trouvent aussi.
Techniquement
Le chemin qu'une requête suit de bout en bout, les frontières de processus qu'elle franchit, et tout ce qui écrit sur le système de fichiers à cette occasion.
Le chemin d'une requête, de bout en bout
Un seul POST envoie un corps multipart. La partie nommée json_data contient la description du document ; chaque autre partie est un binaire que la description désigne par ce nom — un modèle PDF, une image, un profil ICC, un paquet XMP, le XML d'une facture. Le corps est borné par un plafond configuré, 512 mébioctets tel que le service est livré.
Chaque partie est lue en mémoire et la description est désérialisée dans l'arbre de requête que le service parcourt ; le texte brut est abandonné dès que l'analyse rend la main. L'écriture elle-même tourne sur un exécutant bloquant, si bien que la boucle asynchrone continue de servir pendant qu'un long document se compose.
Le moteur rend un vecteur d'octets, qui devient le corps de la réponse tel quel : pas de fichier temporaire, pas de zone de transit, pas de seconde copie. L'arbre de requête, les parties nommées et les octets finis appartiennent à cette tâche et sont libérés quand elle rend la main — en Rust, la libération est structurelle et non planifiée.
Le service tourne avec un dossier temporaire privé, que la machine jette quand le service s'arrête.
Les deux chemins qui écrivent sur le disque
Deux chemins de code dans tout le service créent un fichier, et chacun mérite sa place.
- Le magasin de polices par client. Un client autorisé à dessiner avec ses propres polices voit les polices que ses rendus ont vraiment employées écrites dans un répertoire à son nom, et rechargées en mémoire au démarrage. C'est un état du serveur plutôt qu'un cache : les octets arrivent une fois et chaque requête ultérieure ne fait que les nommer.
- La file des alertes. Une ligne s'écrit quand le service casse de son côté, et elle est retirée dès que le site l'a prise. Les lots partent toutes les cinq secondes ou à cent alertes, au premier des deux, et la file est relue au démarrage, si bien qu'un redémarrage n'en perd aucune. Elle ne contient aucun chemin, aucun nom de fichier et rien de ce que votre demande a choisi — un identifiant, la sorte de panne, le nom du client, un numéro d'incident et un moment.
Ce que contient le journal
Quatre instructions se trouvent sur le chemin de rendu. Un document qui est sorti écrit le nom du client que ce site a envoyé avec l'appel, le numéro que ce site a donné à l'appel, le nombre de pages et les deux durées. Un avertissement du moteur écrit le nom du client et la sorte d'avertissement ; le rendu réussit dans les deux cas — un avertissement est une observation, jamais un refus. Une panne propre au service écrit un numéro d'incident, le nom du client et ce qui a lâché. Un refus écrit le nom du client, le statut et la sorte.
Un avertissement nomme une ressource que la requête a fournie et que la page n'a jamais peinte, par l'étiquette que le moteur lui a donnée en écrivant le fichier : un nom de série pour une police, un autre pour une image, un autre pour un espace de couleur. Vos propres chaînes restent dans votre document.
Les instructions restantes relèvent du cycle de vie et des alertes : la prise que le service ouvre au démarrage, l'arrêt qu'on lui a demandé, l'état du magasin de certificats que vérifie le flux d'alertes, et ce que ce site a répondu à un lot d'alertes. La sortie va sur la sortie standard, au niveau que le journal de la machine recueille.
Ce qu'un refus rapporte
Chaque erreur que le service lève est écrite dans le corps de la réponse à l'appel qui l'a levée, et bon nombre d'entre elles citent la requête. C'est voulu : un client doit pouvoir voir quel morceau de ce qu'il a envoyé a été refusé.
Les familles qui citent ce que vous avez envoyé : le texte entier d'un code qu'on n'a pas pu dessiner, pour chacune des cinq sortes de code-barres et de code carré ; la valeur à laquelle la description n'a pas pu être lue, avec sa ligne et sa colonne dans le corps que vous avez envoyé ; le caractère fautif, le texte d'un nombre et un nom de variable dans une expression de coordonnée ; les noms que vous avez donnés à une police, une image, une pièce jointe, un modèle de page, un calque, un espace de couleur, un dégradé, un dessin, un champ, et un identifiant d'article. À travers le moteur en dessous : un caractère du texte à dessiner, le titre d'un article, et un nom de champ avec sa réponse.
Tout cela part au client qui l'a envoyé, dans la réponse à cet appel, et s'arrête là. Rien n'en est journalisé, rien n'en atteint le disque, et rien n'en repart ailleurs : les vingt endroits qui écrivent quoi que ce soit ont été lus un par un, et pas un ne contient de message d'erreur.
Une seule chose à vous voyage plus loin : le nom de client que ce site envoie avec votre appel s'écrit dans le journal du service à chaque appel, et dans la file des alertes — puis de là vers ce site — quand le service échoue de son propre côté. Rien d'autre à vous ne voyage : cette panne vous répond par une phrase qui ne contient aucun chemin de système de fichiers, et le chemin reste dans le journal de l'exploitant.
L'authentification, et ce qu'on dit au service
L'authentification appartient à ce site. Votre appel arrive ici, la clé d'API est confrontée aux comptes que ce site détient, et l'appel est transmis au service avec un seul en-tête contenant le nom du client. Le service n'a aucune authentification propre : il répond sur la boucle locale de cette machine et rien d'extérieur ne peut l'atteindre, cet en-tête est tout ce qu'on lui dit du client, et il résout les droits — polices propres, plafond de pages — depuis un fichier TOML lu une fois au démarrage.
Révoquer une clé d'API revient donc à réécrire cette liste, avec effet à la requête suivante. La clé elle-même n'atteint jamais le service.
Le journal d'accès de ce site, une autre question
Le serveur frontal placé devant ces pages tient un journal d'accès, comme tout serveur frontal : adresse source, le nom du compte quand la requête en portait un, horodatage, ligne de requête, code de statut et taille du corps, référent, agent utilisateur, et les deux noms de l'hôte demandé. Il tourne chaque jour et quatorze jours compressés sont gardés.
Il est lu dans un seul but, l'acquisition : quels robots passent et à quelle cadence, si un agent qui se dit robot en est vraiment un, quelles adresses publiées n'ont jamais été prises, et quels visiteurs sont venus d'une recherche. Les fichiers statiques sont servis directement et ne figurent pas dans ses lignes.
Une adresse qui a demandé à répétition des URL que ce site n'a jamais servies est inscrite dans une courte liste de refus que le serveur frontal lit, et ses requêtes suivantes reçoivent leur réponse à la porte. Cette liste contient des adresses et rien d'autre, et elle s'édite à la main.
Sur votre propre infrastructure
Le compte rendu des alertes s'active en nommant un point d'arrivée à qui rendre compte. Sans lui, aucune tâche de compte rendu ne démarre et aucun fichier de file d'attente n'existe, ce qui laisse le magasin de polices seul à écrire sur le disque — et seulement pour un client autorisé à ses propres polices.
Le mécanisme à la ligne près
Les garanties, avec leurs chiffres. Chaque ligne a été relevée sur les sources du service, et vaut pour la version en production.
La demande, étape par étape
- Un seul point d'entrée crée un PDF, sur un corps multipart. La partie nommée json_data contient la description en texte ; toute autre partie est gardée sous son propre nom et est le binaire que la description désigne par ce nom.
- Chaque partie est lue entière en mémoire, jamais écrite dans un fichier de travail. La description est désérialisée dans l'arbre de requête, et le texte brut est libéré dès que cela rend la main.
- L'arbre de requête et les parties nommées sont déplacés dans un fil bloquant, et tous deux sont libérés quand il rend la main. Rien ne survit à la tâche : pas de cache indexé par requête, pas de mise en page mémorisée, pas de tampon partagé qui garderait le dernier document.
- Le plafond du corps est un réglage du service, 512 mébioctets à la livraison. Un plafond de pages peut être posé par serveur et par client, et le plus serré des deux s'applique.
Les deux fichiers que le service écrit
Deux chemins de code dans tout le service créent un fichier. Voici chacun d'eux, champ par champ.
- Le magasin de polices par client : pour un client autorisé à dessiner avec ses propres polices, les polices avec lesquelles un rendu réussi a vraiment composé du texte sont écrites dans un répertoire au nom de ce client et relues au démarrage. Il grossit exactement de cela : les polices qu'un document sorti a vraiment employées. Chaque fichier est écrit sous un nom temporaire dans le même répertoire puis renommé à sa place, si bien qu'une lecture simultanée n'observe jamais une police incomplète ; le nom est tenu aux lettres ASCII, aux chiffres, au point, au tiret et au tiret bas, 64 caractères au plus.
- La file des alertes : un objet JSON par ligne, cinq champs et pas un de plus — un identifiant sur lequel le site dédoublonne, la sorte de panne, le nom du client quand un rendu précis est en cause, le numéro d'incident rendu au client, et un moment au format RFC 3339. Elle ne s'écrit que lorsque le service échoue de son propre côté, jamais sur un appel qu'il a refusé comme fautif. Un lot part toutes les cinq secondes ou à cent alertes, au premier des deux, et il est retiré du fichier dès que ce site l'a pris ; la file est relue au démarrage, et ce site dédoublonne sur l'identifiant, si bien qu'un envoi dont l'accusé s'est perdu n'est signalé qu'une fois. Le numéro d'incident est le seul pont vers le journal du service : l'alerte dit qu'il y a quelque chose à regarder, et la ligne de journal sous ce numéro dit quoi.
Les quatre énoncés du chemin de rendu
Quatre énoncés de journal se tiennent sur le chemin de rendu, et les voici tous les quatre. Un document qui sort écrit le nom de votre programme, le numéro que ce site a donné à l'appel, le nombre de pages produites et le temps que ça a pris. Un avertissement du moteur écrit le nom de votre programme et la sorte d'avertissement. Une panne de notre côté écrit un numéro d'incident, le nom de votre programme, et ce qui a lâché ici. Un refus écrit le nom de votre programme, le statut, la sorte de refus, et — sur les trois sortes que vous ne pouvez pas lever en corrigeant votre demande — le même numéro qui vous a été rendu.
Ce numéro est sur votre réponse pour une seule raison : pour qu'un appel téléphonique au sujet d'un refus tombe sur la ligne de journal où il a été écrit plutôt que sur une ligne qui lui ressemble. Il accompagne une licence manquante, un document au-delà de son plafond de pages et une défaillance de notre côté, et rien d'autre — une description que nous n'avons pas su lire nomme déjà la clé JSON à corriger, et un numéro là serait une invitation à nous appeler au sujet de votre propre frappe. Le numéro ne compte rien et ne nomme aucune de nos machines.
Ni un avertissement ni un refus n'est désigné par sa phrase : chacun est désigné par un mot pris dans une liste figée dans le code, si bien que rien de ce que votre demande a choisi ne peut atteindre le journal par là. Un mot de cette liste se lit comme une ressource restée non dessinée, une police dont la licence interdit de la joindre au fichier, une description que nous n'avons pas su lire — la sorte de chose, jamais la chose.
Tout le reste est hors du chemin de rendu : la prise ouverte au démarrage, l'arrêt qu'on a demandé au service, l'état du magasin de certificats que vérifie le flux d'alertes, et la réponse de ce site à un lot d'alertes. Le service écrit sur sa sortie standard, au niveau que le journal de la machine recueille.
Ce qui revient dans une réponse
Un rendu réussi répond 200, le PDF pour corps : le nombre de pages qu'il a, le nombre de choses que le moteur a remarquées en le créant et le nombre de constats qui le séparent des normes demandées par la requête, chaque remarque et chaque constat à côté de son décompte, et le numéro sous lequel l'appel a été passé quand il en a été donné un. Le temps qu'il a pris part au journal du service et ne revient dans rien.
Une requête que le service n'a pas pu employer répond par un code de statut et une phrase en texte simple nommant ce qui l'a arrêtée : 400 pour une description qu'il n'a pas pu employer, 402 pour ce qu'une licence d'évaluation laisse à une clé de licence, 413 pour un corps ou un nombre de pages au-delà de son plafond, 500 pour une défaillance du côté du service.
Cette phrase cite le morceau exact de votre requête qui l'a arrêtée, pour que vous puissiez le corriger sans deviner. Chaque erreur que le service lève repart ainsi, sans exception, dans le corps de la réponse à l'appel qui l'a levée — et voici ce qu'un morceau cité peut être.
- Le texte entier d'un code qu'on n'a pas pu dessiner, pour chacune des cinq sortes de code-barres et de code carré. La réponse dit laquelle des cinq la requête visait.
- La valeur à laquelle la description n'a pas pu être lue, avec la ligne et la colonne où elle se trouve dans le corps que vous avez envoyé.
- Dans une expression écrite là où une coordonnée était attendue, le caractère qui a arrêté la lecture, le texte du nombre, et le nom de la variable.
- Le nom que vous avez donné à une police, une image, une pièce jointe, un modèle de page, un calque, un espace de couleur, un dégradé, un dessin ou un champ, et l'identifiant d'un article.
- À travers le moteur en dessous : un caractère du texte à dessiner là où aucune police ne savait le tracer, le titre d'un article, et le nom d'un champ avec la réponse qui s'y trouve.
Où un refus s'arrête
Un refus est la réponse à votre propre appel, et toute sa vie s'arrête là. Une ligne est écrite quand un appel est écarté, et elle contient trois choses : votre nom de client, le statut, et un mot pris dans une liste figée qui dit de quelle sorte de refus il s'agissait. La phrase qui vous a été rendue n'y est pas, et rien de ce que votre demande a choisi non plus : les vingt endroits du service qui écrivent quoi que ce soit ont été lus un par un, et pas un n'y met de message d'erreur. Rien n'en repart ailleurs non plus — la ligne sur laquelle ce site facture porte un nom de client, un instant, un identifiant et un nombre de pages, et rien d'autre.
Une seule chose à vous voyage plus loin, et elle voyage deux fois ; c'est là tout. Votre nom de client est sur chaque ligne que le service écrit au sujet de votre appel. Il voyage une seconde fois quand le service échoue de son propre côté — un rendu qui a échoué chez lui, ou un magasin de polices d'un client qu'il n'a pu ni lire ni écrire : l'alerte qu'il lève nomme le client pour lequel le travail était fait, pour que celui qu'on réveille sache de quel document il s'agissait, et elle ne contient aucun chemin, aucun nom de fichier et rien de ce que votre demande a choisi. Rien d'autre à vous ne voyage : une panne vous répond par une phrase qui ne donne aucun chemin de notre système de fichiers, et ce chemin reste dans le journal de l'exploitant, où il a sa place.
Ce que contient le PDF fini
- Le dictionnaire d'informations du document et le paquet XMP sont construits d'après ce que votre requête déclare : titre, auteur, sujet, producteur. Une clé JSON que votre requête omet est une clé que le fichier ne contient pas.
- Une date de création apparaît quand votre requête en donne une : toute date à l'intérieur d'un document fini vient de la requête qui l'a demandé. Là où une requête demande expressément que l'instant du rendu soit posé sur la page, l'horloge de la machine et le fuseau nommé répondent, et la date écrite est celle qu'ils indiquent.
- Tout PDF contient un identifiant de fichier. Celui-ci est une empreinte des octets qui viennent d'être écrits, si bien que la même description donne deux fois le même fichier — ce qui vous permet de comparer deux rendus et de constater vous-même qu'ils sont identiques à l'octet.
- Sous une clé de licence, les pages sortent nettes. Une copie tournant sous licence d'évaluation pose un filigrane sur chaque page qu'elle crée et le déclare sur la page ; elle trace aussi les mots en formes plutôt que de les écrire en texte, n'embarque aucune police dans le fichier, n'écrit ni formulaire ni structure, et refuse net une poignée d'appels. La page sur ce qu'une licence donne les liste un par un.
Votre clé d'API, et le nom qui la remplace
La clé d'API vit sur ce site, et ce site est le seul endroit qui la détient. Elle est lue ici, une fois par appel, et changée en un nom de client qui poursuit vers le service dans un en-tête à lui, si bien que le service ne voit jamais la clé ; il travaille sur le nom.
Sur ce site, une ligne en ajout seul est gardée par rendu : le compte, le nom de client sous lequel le rendu a été fait, l'identifiant de ce rendu, le moment, et le nombre de pages. Un mois de ces lignes est ce dont une facture est la somme, et la ligne nomme le client plutôt que la clé d'API, si bien qu'en révoquer une laisse la trace intacte.
Le journal d'accès du site, en entier
Le serveur frontal placé devant ces pages écrit une ligne par requête : l'adresse source, le nom du compte quand la requête en indiquait un, l'horodatage, la ligne de requête, le code de statut et les octets envoyés, le référent, l'agent utilisateur, et les deux noms de l'hôte demandé.
Les lignes tournent chaque jour et quatorze jours compressés sont gardés, ce qui met la plus ancienne visite à quinze jours en arrière. Ses lignes sont les pages qu'un visiteur a demandées ; les fichiers statiques du site et les appels refusés à la porte sont servis directement.
Un rapport écrit dans le code du site lui-même analyse ces lignes pour répondre à cinq questions sur l'acquisition : quels robots sont passés et à quelle cadence, si un agent qui se dit robot en est vraiment un, quelles adresses publiées aucun robot n'a prises, quels visiteurs sont venus d'une recherche et où ils ont atterri, et quelles requêtes cherchaient quelque chose que ce site n'a jamais servi.
Une adresse qui a demandé, plusieurs fois de suite, des URL que ce site n'a jamais servies est inscrite dans une courte liste de refus que le serveur frontal lit, et ses requêtes suivantes reçoivent leur réponse à la porte. Cette liste est courte, elle contient des adresses et rien d'autre, et elle s'édite à la main.
Faire tourner le service chez vous
Démarré sans point d'arrivée à qui rendre compte, le service garde ses propres pannes dans son journal et les deux écritures se réduisent au seul magasin de polices. Démarré sans répertoire de polices pour un client, les polices de ce client vivent dans l'espace mémoire du rendu qui les a employées, et pour exactement le temps qu'il faut.
Où aller ensuite
Comment un programme demande ses pages Les conditions auxquelles c'est vendu Posez-nous la question que cette page a laissée de côté