{"componentChunkName":"component---src-templates-post-jsx","path":"/fr/inbound-outbound-processing","result":{"data":{"markdownRemark":{"html":"<h1>Comprendre le Inbound et Outbound Processing dans Drupal : principes et exemples</h1>\n<h2>Introduction</h2>\n<p>Dans un site Drupal, lorsqu’un utilisateur interagit avec le système (par exemple, en accédant à une URL, en soumettant un formulaire, ou en consommant une API), Drupal traite la requête via un cycle d’entrée et de sortie : c’est ce qu’on appelle les processus <strong>Inbound</strong> et <strong>Outbound</strong>.</p>\n<p>Ces deux mécanismes permettent à Drupal :</p>\n<ul>\n<li>d’interpréter les données entrantes (inbound),</li>\n<li>de modifier les données sortantes (outbound),</li>\n<li>et de centraliser la logique de traitement via des services ou des hooks.</li>\n</ul>\n<p>Voyons tout cela en détail avec des exemples concrets.</p>\n<h2>1. Le Inbound Processing : traiter ce qui entre</h2>\n<p>Le <strong>Inbound Processing</strong> s’applique à tout ce que l’utilisateur envoie vers le système :</p>\n<ul>\n<li>L’URL demandée,</li>\n<li>Les paramètres de requête (<code class=\"language-text\">GET</code>, <code class=\"language-text\">POST</code>),</li>\n<li>Les données soumises dans un formulaire ou appel API.</li>\n</ul>\n<h3>Objectif</h3>\n<ul>\n<li>Réécrire des chemins ou paramètres,</li>\n<li>Appliquer une logique de transformation ou de sécurité,</li>\n<li>Décoder des valeurs avant qu’elles ne soient utilisées dans le système.</li>\n</ul>\n<h3>Exemple : Modifier une URL d’entrée</h3>\n<p>Imaginons qu’on souhaite rediriger les chemins <code class=\"language-text\">/produits</code> vers <code class=\"language-text\">/product</code> tout en gardant la logique interne de Drupal.</p>\n<div class=\"gatsby-highlight\" data-language=\"php\"><pre class=\"language-php\"><code class=\"language-php\"><span class=\"token keyword\">use</span> <span class=\"token package\">Symfony<span class=\"token punctuation\">\\</span>Component<span class=\"token punctuation\">\\</span>HttpKernel<span class=\"token punctuation\">\\</span>Event<span class=\"token punctuation\">\\</span>RequestEvent</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">use</span> <span class=\"token package\">Symfony<span class=\"token punctuation\">\\</span>Component<span class=\"token punctuation\">\\</span>EventDispatcher<span class=\"token punctuation\">\\</span>EventSubscriberInterface</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">InboundPathSubscriber</span> <span class=\"token keyword\">implements</span> <span class=\"token class-name\">EventSubscriberInterface</span> <span class=\"token punctuation\">{</span>\n\n  <span class=\"token keyword\">public</span> <span class=\"token keyword\">static</span> <span class=\"token keyword\">function</span> <span class=\"token function\">getSubscribedEvents</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">return</span> <span class=\"token punctuation\">[</span><span class=\"token single-quoted-string string\">'kernel.request'</span> <span class=\"token operator\">=</span><span class=\"token operator\">></span> <span class=\"token punctuation\">[</span><span class=\"token single-quoted-string string\">'onKernelRequest'</span><span class=\"token punctuation\">,</span> <span class=\"token number\">30</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  <span class=\"token keyword\">public</span> <span class=\"token keyword\">function</span> <span class=\"token function\">onKernelRequest</span><span class=\"token punctuation\">(</span>RequestEvent <span class=\"token variable\">$event</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token variable\">$request</span> <span class=\"token operator\">=</span> <span class=\"token variable\">$event</span><span class=\"token operator\">-</span><span class=\"token operator\">></span><span class=\"token function\">getRequest</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token variable\">$path</span> <span class=\"token operator\">=</span> <span class=\"token variable\">$request</span><span class=\"token operator\">-</span><span class=\"token operator\">></span><span class=\"token function\">getPathInfo</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token variable\">$path</span> <span class=\"token operator\">===</span> <span class=\"token single-quoted-string string\">'/produits'</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token variable\">$request</span><span class=\"token operator\">-</span><span class=\"token operator\">></span><span class=\"token property\">server</span><span class=\"token operator\">-</span><span class=\"token operator\">></span><span class=\"token function\">set</span><span class=\"token punctuation\">(</span><span class=\"token single-quoted-string string\">'REQUEST_URI'</span><span class=\"token punctuation\">,</span> <span class=\"token single-quoted-string string\">'/product'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Ici, nous utilisons l’événement <code class=\"language-text\">kernel.request</code> pour intercepter l’URL avant que Drupal ne résolve le routeur.</p>\n<h2>2. Le Outbound Processing : manipuler ce qui sort</h2>\n<p>Le <strong>Outbound Processing</strong> intervient lorsque Drupal génère une réponse (HTML, JSON, etc.). Il est souvent utilisé pour :</p>\n<ul>\n<li>Modifier les liens générés (<code class=\"language-text\">Url::fromRoute()</code>),</li>\n<li>Réécrire dynamiquement les URL sortantes,</li>\n<li>Ajouter des entêtes HTTP, ou modifier la structure JSON.</li>\n</ul>\n<h3>Exemple : Réécriture dynamique des liens</h3>\n<p>Supposons que vous souhaitiez transformer tous les liens <code class=\"language-text\">/user/ID</code> en <code class=\"language-text\">/profil/ID</code> lors du rendu HTML :</p>\n<div class=\"gatsby-highlight\" data-language=\"php\"><pre class=\"language-php\"><code class=\"language-php\"><span class=\"token keyword\">use</span> <span class=\"token package\">Drupal<span class=\"token punctuation\">\\</span>Core<span class=\"token punctuation\">\\</span>PathProcessor<span class=\"token punctuation\">\\</span>OutboundPathProcessorInterface</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">use</span> <span class=\"token package\">Symfony<span class=\"token punctuation\">\\</span>Component<span class=\"token punctuation\">\\</span>HttpFoundation<span class=\"token punctuation\">\\</span>Request</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">use</span> <span class=\"token package\">Drupal<span class=\"token punctuation\">\\</span>Core<span class=\"token punctuation\">\\</span>Render<span class=\"token punctuation\">\\</span>BubbleableMetadata</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">OutboundPathProcessor</span> <span class=\"token keyword\">implements</span> <span class=\"token class-name\">OutboundPathProcessorInterface</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token keyword\">public</span> <span class=\"token keyword\">function</span> <span class=\"token function\">processOutbound</span><span class=\"token punctuation\">(</span><span class=\"token variable\">$path</span><span class=\"token punctuation\">,</span> <span class=\"token operator\">&amp;</span><span class=\"token variable\">$options</span> <span class=\"token operator\">=</span> <span class=\"token punctuation\">[</span><span class=\"token punctuation\">]</span><span class=\"token punctuation\">,</span> Request <span class=\"token variable\">$request</span> <span class=\"token operator\">=</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">,</span> BubbleableMetadata <span class=\"token variable\">$bubbleable_metadata</span> <span class=\"token operator\">=</span> <span class=\"token constant\">NULL</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    <span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span><span class=\"token function\">strpos</span><span class=\"token punctuation\">(</span><span class=\"token variable\">$path</span><span class=\"token punctuation\">,</span> <span class=\"token single-quoted-string string\">'/user/'</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">===</span> <span class=\"token number\">0</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n      <span class=\"token keyword\">return</span> <span class=\"token function\">str_replace</span><span class=\"token punctuation\">(</span><span class=\"token single-quoted-string string\">'/user/'</span><span class=\"token punctuation\">,</span> <span class=\"token single-quoted-string string\">'/profil/'</span><span class=\"token punctuation\">,</span> <span class=\"token variable\">$path</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    <span class=\"token punctuation\">}</span>\n    <span class=\"token keyword\">return</span> <span class=\"token variable\">$path</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>Déclaration dans <code class=\"language-text\">services.yml</code> :</p>\n<div class=\"gatsby-highlight\" data-language=\"yaml\"><pre class=\"language-yaml\"><code class=\"language-yaml\"><span class=\"token key atrule\">services</span><span class=\"token punctuation\">:</span>\n  <span class=\"token key atrule\">my_module.path_processor.outbound</span><span class=\"token punctuation\">:</span>\n    <span class=\"token key atrule\">class</span><span class=\"token punctuation\">:</span> Drupal\\my_module\\OutboundPathProcessor\n    <span class=\"token key atrule\">tags</span><span class=\"token punctuation\">:</span>\n      <span class=\"token punctuation\">-</span> <span class=\"token punctuation\">{</span> <span class=\"token key atrule\">name</span><span class=\"token punctuation\">:</span> path_processor_outbound<span class=\"token punctuation\">,</span> <span class=\"token key atrule\">priority</span><span class=\"token punctuation\">:</span> <span class=\"token number\">100 </span><span class=\"token punctuation\">}</span></code></pre></div>\n<h2>Quand utiliser Inbound vs Outbound ?</h2>\n<table>\n<thead>\n<tr>\n<th>Situation</th>\n<th>Inbound</th>\n<th>Outbound</th>\n</tr>\n</thead>\n<tbody>\n<tr>\n<td>Modifier le chemin avant qu’il ne soit résolu</td>\n<td>Oui</td>\n<td>Non</td>\n</tr>\n<tr>\n<td>Modifier un lien avant de l'afficher</td>\n<td>Non</td>\n<td>Oui</td>\n</tr>\n<tr>\n<td>Réécrire les paramètres d’une URL</td>\n<td>Oui</td>\n<td>Oui</td>\n</tr>\n<tr>\n<td>Ajouter des entêtes HTTP</td>\n<td>Non</td>\n<td>Oui</td>\n</tr>\n<tr>\n<td>Gérer la redirection conditionnelle</td>\n<td>Oui</td>\n<td>Non</td>\n</tr>\n</tbody>\n</table>\n<h2>Utilisation combinée : cas typique d’un site multilingue</h2>\n<ul>\n<li>Inbound : intercepter l’URL <code class=\"language-text\">/fr/produits</code> pour router vers <code class=\"language-text\">/en/product</code>.</li>\n<li>Outbound : générer les bons liens traduits dans les menus (<code class=\"language-text\">/fr/produits</code>, <code class=\"language-text\">/en/product</code>...).</li>\n</ul>\n<p>C’est <code class=\"language-text\">PathProcessorManager</code> qui orchestre ces opérations dans Drupal Core.</p>\n<h2>Debug &#x26; Bonnes pratiques</h2>\n<ul>\n<li>Utilisez <code class=\"language-text\">\\Drupal::logger()</code> pour tracer les chemins traités.</li>\n<li>Priorisez vos abonnements aux événements Symfony (ordre d’exécution critique).</li>\n<li>Activez le cache de routes en production, mais désactivez-le lors du développement.</li>\n</ul>\n<h2>Conclusion</h2>\n<p>Les systèmes <strong>Inbound</strong> et <strong>Outbound</strong> dans Drupal sont des outils puissants pour contrôler le flux des données HTTP. Que vous créiez un site multilingue, headless, ou que vous souhaitiez personnaliser les chemins de votre site, ces hooks vous donnent un contrôle fin sur l’entrée et la sortie des données — sans modifier le cœur de Drupal.</p>","excerpt":"Comprendre le Inbound et Outbound Processing dans Drupal : principes et exemples Introduction Dans un site Drupal, lorsqu’un utilisateur interagit avec le…","frontmatter":{"date":"2025-05-12","metaDate":"2025-05-12","title":"Inbound & Outbound Processing","tags":["Drupal","Core feature","HTTP requests","Module development"],"path":"/inbound-outbound-processing","cover":{"childImageSharp":{"fluid":{"base64":"data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAgABQDASIAAhEBAxEB/8QAFwAAAwEAAAAAAAAAAAAAAAAAAAIDAf/EABgBAQADAQAAAAAAAAAAAAAAAAEAAgME/9oADAMBAAIQAxAAAAGFUXry00TZ3QspQJ//xAAaEAACAwEBAAAAAAAAAAAAAAAAAQIREhBB/9oACAEBAAEFAkaHJElzNjKtynz3KP/EABURAQEAAAAAAAAAAAAAAAAAABEg/9oACAEDAQE/ASP/xAAUEQEAAAAAAAAAAAAAAAAAAAAg/9oACAECAQE/AR//xAAcEAABAwUAAAAAAAAAAAAAAAAQAAERISIxUaH/2gAIAQEABj8CMMtPCkXcVBkf/8QAHhAAAgMAAgMBAAAAAAAAAAAAAREAITFBYVGRodH/2gAIAQEAAT8hZ1G5HqMYYAI+u4QAQArFeYCEJsem3oXE0h+okjAUT5gFqV1Oz5P/2gAMAwEAAgADAAAAEG/1AP/EABcRAQEBAQAAAAAAAAAAAAAAAAEAESH/2gAIAQMBAT8QOLsOFpf/xAAWEQEBAQAAAAAAAAAAAAAAAAABACH/2gAIAQIBAT8QUsmRv//EAB0QAQEBAAICAwAAAAAAAAAAAAERACExQVFxgZH/2gAIAQEAAT8Q7n40muBl+L9zGsUp+B1hiI64eHDhoAAxxgAFphZEYThEesxg+Bc8cBL3zdxtVcdtQKKHpv/Z","aspectRatio":0.625081788440567,"src":"/static/1d4893aa934642fb4398940d90f06b8a/88110/inbound-outbound.jpg","srcSet":"/static/1d4893aa934642fb4398940d90f06b8a/0b320/inbound-outbound.jpg 480w,\n/static/1d4893aa934642fb4398940d90f06b8a/60b32/inbound-outbound.jpg 960w,\n/static/1d4893aa934642fb4398940d90f06b8a/88110/inbound-outbound.jpg 1920w,\n/static/1d4893aa934642fb4398940d90f06b8a/522de/inbound-outbound.jpg 2866w","srcWebp":"/static/1d4893aa934642fb4398940d90f06b8a/d1a9d/inbound-outbound.webp","srcSetWebp":"/static/1d4893aa934642fb4398940d90f06b8a/bc3bf/inbound-outbound.webp 480w,\n/static/1d4893aa934642fb4398940d90f06b8a/39337/inbound-outbound.webp 960w,\n/static/1d4893aa934642fb4398940d90f06b8a/d1a9d/inbound-outbound.webp 1920w,\n/static/1d4893aa934642fb4398940d90f06b8a/f0a30/inbound-outbound.webp 2866w","sizes":"(max-width: 1920px) 100vw, 1920px"},"resize":{"src":"/static/1d4893aa934642fb4398940d90f06b8a/c4f3a/inbound-outbound.jpg"}}}}}},"pageContext":{"isCreatedByStatefulCreatePages":false,"pathSlug":"/inbound-outbound-processing","locale":"fr","prev":{"fields":{"locale":"fr"},"frontmatter":{"path":"/drupal-architectures","title":"Drupal Monolithique, Découplé et Progressivement Découplé : Quelle Architecture Choisir ?","tags":["Drupal 10","Drupal 11","Architecture","Conception","Strategy"]}},"next":{"fields":{"locale":"fr"},"frontmatter":{"path":"/drupal-cms","title":"Drupal CMS 1.0 (Starshot) : Une nouvelle ère pour la création de sites web","tags":["Drupal 11","News","Drupal CMS","UX"]}}}}}