1
0
Fork 0
mirror of https://gitlab.com/news-flash/article_scraper.git synced 2025-07-07 16:15:32 +02:00

thumbnail: check for attribute with name property as well (fixes #4)

This commit is contained in:
Jan Lukas Gernert 2024-11-02 11:30:29 +01:00
parent b3ce28632d
commit 11ee29feda
3 changed files with 839 additions and 1 deletions

View file

@ -0,0 +1,808 @@
<!doctype html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link href="/assets/css/dist-style.css" rel="stylesheet" />
<link href="/assets/css/fonts.css" rel="stylesheet" />
<script src="https://unpkg.com/typeit@8.8.4/dist/index.umd.js"></script>
<!-- Begin Jekyll SEO tag v2.8.0 -->
<title>PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only. | a-chacon</title>
<meta name="generator" content="Jekyll v4.3.4" />
<meta property="og:title" content="PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only." />
<meta name="author" content="Andrés" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="Haciendo funcionar el generador de autenticación de Rails 8 (Beta) en una aplicación creada en modo API-Only." />
<meta property="og:description" content="Haciendo funcionar el generador de autenticación de Rails 8 (Beta) en una aplicación creada en modo API-Only." />
<link rel="canonical" href="https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html" />
<meta property="og:url" content="https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html" />
<meta property="og:site_name" content="a-chacon" />
<meta property="og:image" content="https://a-chacon.com/assets/images/rails8-poc-api-auth.webp" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2024-10-16T00:00:00+00:00" />
<meta name="twitter:card" content="summary_large_image" />
<meta property="twitter:image" content="https://a-chacon.com/assets/images/rails8-poc-api-auth.webp" />
<meta property="twitter:title" content="PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only." />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Andrés"},"dateModified":"2024-10-16T00:00:00+00:00","datePublished":"2024-10-16T00:00:00+00:00","description":"Haciendo funcionar el generador de autenticación de Rails 8 (Beta) en una aplicación creada en modo API-Only.","headline":"PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only.","image":"https://a-chacon.com/assets/images/rails8-poc-api-auth.webp","mainEntityOfPage":{"@type":"WebPage","@id":"https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html"},"publisher":{"@type":"Organization","logo":{"@type":"ImageObject","url":"https://a-chacon.com/assets/images/keyboard-key-a.png"},"name":"Andrés"},"url":"https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html"}</script>
<!-- End Jekyll SEO tag -->
<link type="application/atom+xml" rel="alternate" href="https://a-chacon.com/feed.xml" title="a-chacon" />
<script data-host="https://app.microanalytics.io" data-dnt="false" src="https://app.microanalytics.io/js/script.js"
id="ZwSg9rf6GA" async defer></script>
<style>
.mini-banner {
background-color: #6eea8e;
/* Light red background color */
color: #1c2a18;
/* Dark red text color */
padding: 10px 20px;
/* Padding around the text */
text-align: center;
/* Center the text */
position: fixed;
/* Fix the banner to the top of the page */
bottom: 0;
/* Position at the very top */
left: 0;
/* Full width */
right: 0;
/* Full width */
z-index: 1000;
/* Ensure it's above other elements */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
/* Slight shadow for depth */
}
.mini-banner p {
margin: 0;
/* Remove default paragraph margin */
font-size: 16px;
/* Font size */
font-weight: bold;
/* Bold text */
}
body {
margin-top: 60px;
/* Adjust based on the banner height */
}
</style>
<div class="mini-banner">
<p>Building an API with Rails? Discover
<a href="https://github.com/a-chacon/oas_rails" style="color: #826cf6; text-decoration: underline;">
OasRails</a>, a Rails engine for generate automatic interactive documentation.
</p>
</div>
</head>
<body class="bg-white text-gray-900 dark:bg-gray-700 dark:text-slate-100">
<script>
document.addEventListener("DOMContentLoaded", function () {
new TypeIt("h1", {}).go();
});
</script>
<nav class="absolute top-0 left-0 right-0 flex w-full flex-wrap items-center justify-between py-4">
<div class="flex w-full flex-wrap items-center justify-between px-5">
<a class="flex" href="/" aria-label="Andres Chacon - Developer">
<img src="/assets/images/keyboard-key-a.png" alt="webpage logo" class="block h-8 w-auto">
<p class="pl-4 hidden md:block text-lg font-bold">a-chacon <span
class="text-mulish text-sm font-normal">~/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html</span>
</p>
</a>
<div class="flex divide-x">
<div><a class="px-4 hover:text-sky-400 "
href="/blog.html">Blog</a></div>
<div><a class="px-4 hover:text-sky-400 "
href="/projects">Proyectos</a></div>
<div class="language-switcher relative">
<button class="current-language px-4 hover:text-sky-400">
ES
</button>
<div class="dropdown-content absolute hidden mt-2 py-2 bg-white rounded shadow-lg z-20">
<a class="p-4 hover:text-sky-400" href="/en/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html">EN</a>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
const currentLangButton = document.querySelector('.current-language');
const dropdownContent = document.querySelector('.dropdown-content');
if (currentLangButton && dropdownContent) {
currentLangButton.addEventListener('click', function () {
dropdownContent.classList.toggle('hidden');
});
document.addEventListener('click', function (event) {
if (!currentLangButton.contains(event.target) && !dropdownContent.contains(event.target)) {
dropdownContent.classList.add('hidden');
}
});
}
});
</script>
</nav>
<link rel="stylesheet" href="/assets/css/monokai.css">
<div class="container mx-auto">
<div id="post" class="prose max-w-[75ch] prose-neutral mx-auto pb-10 pt-20 lg:pt-[90px] lg:pb-20">
<div class="pb-4">
<a href="https://a-chacon.com/category/on-rails"
class="no-underline font-mulish text-sm hover:text-sky-400 text-gray-500">
ON RAILS
</a>
</div>
<h1 class="text-left text-2xl font-bold md:text-5xl text-black">PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only.</h1>
<div class="flex flex-col md:flex-row text-sm font-mulish justify-between items-center">
<div class="flex">
<p>Andrés</p>
<p class="px-2"></p>
<p>16 October 2024</p>
<p class="px-2"></p>
<p>
6 mins </p>
</div>
<div>
<div class="sharing-buttons flex flex-wrap gap-1 justify-center ">
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
target="_blank" rel="noopener"
href="https://facebook.com/sharer/sharer.php?u=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html"
aria-label="Share on Facebook">
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
class="w-5 h-5">
<title>Facebook</title>
<path
d="M379 22v75h-44c-36 0-42 17-42 41v54h84l-12 85h-72v217h-88V277h-72v-85h72v-62c0-72 45-112 109-112 31 0 58 3 65 4z">
</path>
</svg>
</a>
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
target="_blank" rel="noopener"
href="https://twitter.com/intent/tweet?url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html&text=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only."
aria-label="Share on Twitter">
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
class="w-5 h-5">
<title>Twitter</title>
<path
d="m459 152 1 13c0 139-106 299-299 299-59 0-115-17-161-47a217 217 0 0 0 156-44c-47-1-85-31-98-72l19 1c10 0 19-1 28-3-48-10-84-52-84-103v-2c14 8 30 13 47 14A105 105 0 0 1 36 67c51 64 129 106 216 110-2-8-2-16-2-24a105 105 0 0 1 181-72c24-4 47-13 67-25-8 24-25 45-46 58 21-3 41-8 60-17-14 21-32 40-53 55z">
</path>
</svg>
</a>
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
target="_blank" rel="noopener"
href="https://www.linkedin.com/shareArticle?mini=true&url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html&title=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only.&summary=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only.&source=https://a-chacon.com"
aria-label="Share on Linkedin">
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
class="w-5 h-5">
<title>Linkedin</title>
<path
d="M136 183v283H42V183h94zm6-88c1 27-20 49-53 49-32 0-52-22-52-49 0-28 21-49 53-49s52 21 52 49zm333 208v163h-94V314c0-38-13-64-47-64-26 0-42 18-49 35-2 6-3 14-3 23v158h-94V183h94v41c12-20 34-48 85-48 62 0 108 41 108 127z">
</path>
</svg>
</a>
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
target="_blank" rel="noopener"
href="https://pinterest.com/pin/create/button/?url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html&media=https://a-chacon.com&description=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only."
aria-label="Share on Pinterest" draggable="false">
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
class="w-5 h-5">
<title>Pinterest</title>
<path
d="M268 6C165 6 64 75 64 186c0 70 40 110 64 110 9 0 15-28 15-35 0-10-24-30-24-68 0-81 62-138 141-138 68 0 118 39 118 110 0 53-21 153-90 153-25 0-46-18-46-44 0-38 26-74 26-113 0-67-94-55-94 25 0 17 2 36 10 51-14 60-42 148-42 209 0 19 3 38 4 57 4 3 2 3 7 1 51-69 49-82 72-173 12 24 44 36 69 36 106 0 154-103 154-196C448 71 362 6 268 6z">
</path>
</svg>
</a>
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
target="_blank" rel="noopener"
href="https://reddit.com/submit/?url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html&resubmit=true&title=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only."
aria-label="Share on Reddit" draggable="false">
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
class="w-5 h-5">
<title>Reddit</title>
<path
d="M440 204c-15 0-28 6-38 15-35-24-83-40-137-42l28-125 88 20c0 22 18 39 39 39 22 0 40-18 40-39s-17-40-40-40c-15 0-28 9-35 22l-97-22c-5-1-10 3-11 7l-31 138c-53 2-100 18-136 43a53 53 0 0 0-38-16c-56 0-74 74-23 100l-3 24c0 84 95 152 210 152 117 0 211-68 211-152 0-8-1-17-3-25 50-25 32-99-24-99zM129 309a40 40 0 1 1 80 0 40 40 0 0 1-80 0zm215 93c-37 37-139 37-176 0-4-3-4-9 0-13s10-4 13 0c28 28 120 29 149 0 4-4 10-4 14 0s4 10 0 13zm-1-54c-22 0-39-17-39-39a39 39 0 1 1 39 39z">
</path>
</svg>
</a>
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
target="_blank" rel="noopener"
href="https://wa.me/?text=PoC:%20Usando%20el%20Generador%20de%20Autenticaci%C3%B3n%20de%20Rails%208%20(Beta)%20En%20Modo%20API-Only.%20https://a-chacon.com"
aria-label="Share on Whatsapp" draggable="false">
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
class="w-5 h-5">
<title>Whatsapp</title>
<path
d="M413 97A222 222 0 0 0 64 365L31 480l118-31a224 224 0 0 0 330-195c0-59-25-115-67-157zM256 439c-33 0-66-9-94-26l-7-4-70 18 19-68-4-7a185 185 0 0 1 287-229c34 36 56 82 55 131 1 102-84 185-186 185zm101-138c-5-3-33-17-38-18-5-2-9-3-12 2l-18 22c-3 4-6 4-12 2-32-17-54-30-75-66-6-10 5-10 16-31 2-4 1-7-1-10l-17-41c-4-10-9-9-12-9h-11c-4 0-9 1-15 7-5 5-19 19-19 46s20 54 23 57c2 4 39 60 94 84 36 15 49 17 67 14 11-2 33-14 37-27s5-24 4-26c-2-2-5-4-11-6z">
</path>
</svg>
</a>
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
target="_blank" rel="noopener"
href="https://telegram.me/share/url?text=PoC:%20Usando%20el%20Generador%20de%20Autenticaci%C3%B3n%20de%20Rails%208%20(Beta)%20En%20Modo%20API-Only.&url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html"
aria-label="Share on Telegram" draggable="false">
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
class="w-5 h-5">
<title>Telegram</title>
<path
d="M256 8a248 248 0 1 0 0 496 248 248 0 0 0 0-496zm115 169c-4 39-20 134-28 178-4 19-10 25-17 25-14 2-25-9-39-18l-56-37c-24-17-8-25 6-40 3-4 67-61 68-67l-1-4-5-1q-4 1-105 70-15 10-27 9c-9 0-26-5-38-9-16-5-28-7-27-16q1-7 18-14l145-62c69-29 83-34 92-34 2 0 7 1 10 3l4 7a43 43 0 0 1 0 10z">
</path>
</svg>
</a>
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700" target="_blank" rel="noopener" href="/cdn-cgi/l/email-protection#68571b1d0a020d0b1c5538072b524d5a583d1b09060c074d5a580d044d5a582f0d060d1a090c071a4d5a580c0d4d5a58291d1c0d061c010b090b014d2b5b4d2a5b064d5a580c0d4d5a583a0901041b4d5a58504d5a58402a0d1c09414d5a582d064d5a5825070c074d5a582938214527060411464e0a070c1155001c1c181b52474709450b00090b0706460b07054707064d5a581a0901041b475a585a5c47595847595e4718070b451d1b01060f451a0901041b455045091d1c00451b111b1c0d0545010645091801450706041146001c0504" aria-label="Share by Email" draggable="false">
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
class="w-5 h-5">
<title>Email</title>
<path
d="M464 64a48 48 0 0 1 29 86L275 314c-11 8-27 8-38 0L19 150a48 48 0 0 1 29-86h416zM218 339c22 17 54 17 76 0l218-163v208c0 35-29 64-64 64H64c-35 0-64-29-64-64V176l218 163z">
</path>
</svg>
</a>
</div>
</div>
</div>
<img class="w-full" src="/assets/images/rails8-poc-api-auth.webp" alt="PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only.">
<div class="my-6">
<p>Como ya saben, una de las funcionalidades nuevas de Rails 8 es el <strong>nuevo generador básico de autenticación</strong> que viene a demostrar que no es tan complejo desarrollar todo lo que respecta a autenticación en una aplicación con Rails y que muchas veces no es necesario depender de terceros (gemas). La discusión comenzó <a href="https://github.com/rails/rails/issues/50446">aquí</a>.</p>
<p>Dicho esto, veamos que pasa usando el generador en una aplicación API-Only:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> rails <span class="nt">-v</span>
Rails 8.0.0.beta1
</code></pre></div></div>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> rails new app <span class="nt">--api</span> &amp; <span class="nb">cd </span>app
</code></pre></div></div>
<p>Y ejecutamos el nuevo comando:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code> rails g authentication
create app/models/session.rb
create app/models/user.rb
create app/models/current.rb
create app/controllers/sessions_controller.rb
create app/controllers/concerns/authentication.rb
create app/controllers/passwords_controller.rb
create app/mailers/passwords_mailer.rb
create app/views/passwords_mailer/reset.html.erb
create app/views/passwords_mailer/reset.text.erb
create <span class="nb">test</span>/mailers/previews/passwords_mailer_preview.rb
gsub app/controllers/application_controller.rb
route resources :passwords, param: :token
route resource :session
gsub Gemfile
bundle <span class="nb">install</span> <span class="nt">--quiet</span>
generate migration CreateUsers email_address:string!:uniq password_digest:string! <span class="nt">--force</span>
rails generate migration CreateUsers email_address:string!:uniq password_digest:string! <span class="nt">--force</span>
invoke active_record
create db/migrate/20241016002139_create_users.rb
generate migration CreateSessions user:references ip_address:string user_agent:string <span class="nt">--force</span>
rails generate migration CreateSessions user:references ip_address:string user_agent:string <span class="nt">--force</span>
invoke active_record
create db/migrate/20241016002140_create_sessions.rb
</code></pre></div></div>
<p>Ok, ahora por ejemplo, si revisamos <code class="language-plaintext highlighter-rouge">SessionsController</code> veremos que el método de <code class="language-plaintext highlighter-rouge">Login</code> se ve de la siguiente forma:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">def</span> <span class="nf">create</span>
<span class="k">if</span> <span class="n">user</span> <span class="o">=</span> <span class="no">User</span><span class="p">.</span><span class="nf">authenticate_by</span><span class="p">(</span><span class="n">params</span><span class="p">.</span><span class="nf">permit</span><span class="p">(</span><span class="ss">:email_address</span><span class="p">,</span> <span class="ss">:password</span><span class="p">))</span>
<span class="n">start_new_session_for</span> <span class="n">user</span>
<span class="n">redirect_to</span> <span class="n">after_authentication_url</span>
<span class="k">else</span>
<span class="n">redirect_to</span> <span class="n">new_session_url</span><span class="p">,</span> <span class="ss">alert: </span><span class="s2">"Try another email address or password."</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>
<p>O sea, redirecciona a rutas y/o vistas que en nuestra API no existen ni hacen sentido, y además si inspeccionamos el metodo <code class="language-plaintext highlighter-rouge">start_new_session_for</code> nos daremos cuenta de que el sistema está basado 100% en <strong>autenticación mediante cookies</strong>. Entonces, ¿qué hacemos?</p>
<p>Mi propuesta es la siguiente: el generador crea las bases para la autenticación y creo que funciona bastante bien, por lo que con unas pequeñas modificaciones podemos dejar funcionando una <strong>autenticación Bearer</strong> (Token Authentication) rápidamente en nuestra API con Rails 8 más los archivos ya generados.</p>
<p>El primer paso será agregar <strong>persistencia para nuestro token</strong>, para esto modificaremos la migración que crea las sessiones y agregaremos un nuevo campo llamado <code class="language-plaintext highlighter-rouge">token</code>:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">create_table</span> <span class="ss">:sessions</span> <span class="k">do</span> <span class="o">|</span><span class="n">t</span><span class="o">|</span>
<span class="n">t</span><span class="p">.</span><span class="nf">references</span> <span class="ss">:user</span><span class="p">,</span> <span class="ss">null: </span><span class="kp">false</span><span class="p">,</span> <span class="ss">foreign_key: </span><span class="kp">true</span>
<span class="n">t</span><span class="p">.</span><span class="nf">string</span> <span class="ss">:ip_address</span>
<span class="n">t</span><span class="p">.</span><span class="nf">string</span> <span class="ss">:user_agent</span>
<span class="n">t</span><span class="p">.</span><span class="nf">string</span> <span class="ss">:token</span> <span class="c1"># HERE</span>
<span class="n">t</span><span class="p">.</span><span class="nf">timestamps</span>
<span class="k">end</span>
</code></pre></div></div>
<p>Ahora simplemente ejecuta <code class="language-plaintext highlighter-rouge">rails db:migrate</code> y create un usuario de prueba por consola, yo lo haré con esta línea <code class="language-plaintext highlighter-rouge">User.create(email_address: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="a6d3d5c3d4e6d2c3d5d288c5c9cb">[email&#160;protected]</a>", password: "123456789")</code> (Lo utilizaremos más tarde). Luego debemos crear un nuevo token para cada sesión nueva de un usuario, para esto lo más simple es usar un callback en el modelo <code class="language-plaintext highlighter-rouge">Session</code>:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/models/sessions.rb</span>
<span class="k">class</span> <span class="nc">Session</span> <span class="o">&lt;</span> <span class="no">ApplicationRecord</span>
<span class="n">belongs_to</span> <span class="ss">:user</span>
<span class="n">before_create</span> <span class="ss">:generate_token</span> <span class="c1"># Here call</span>
<span class="kp">private</span>
<span class="k">def</span> <span class="nf">generate_token</span> <span class="c1"># Here implement, generate the token as you wish.</span>
<span class="nb">self</span><span class="p">.</span><span class="nf">token</span> <span class="o">=</span> <span class="no">Digest</span><span class="o">::</span><span class="no">SHA1</span><span class="p">.</span><span class="nf">hexdigest</span><span class="p">([</span> <span class="no">Time</span><span class="p">.</span><span class="nf">now</span><span class="p">,</span> <span class="nb">rand</span> <span class="p">].</span><span class="nf">join</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>
<p>Ahora volviendo al metodo <code class="language-plaintext highlighter-rouge">start_new_session_for</code> en el concern <code class="language-plaintext highlighter-rouge">Authentication</code>, no es necesario que creemos una cookie, asi que debemos remover esa linea y dejar el metodo de la siguiente forma:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/controllers/concerns/authentication.rb</span>
<span class="k">def</span> <span class="nf">start_new_session_for</span><span class="p">(</span><span class="n">user</span><span class="p">)</span>
<span class="n">user</span><span class="p">.</span><span class="nf">sessions</span><span class="p">.</span><span class="nf">create!</span><span class="p">(</span><span class="ss">user_agent: </span><span class="n">request</span><span class="p">.</span><span class="nf">user_agent</span><span class="p">,</span> <span class="ss">ip_address: </span><span class="n">request</span><span class="p">.</span><span class="nf">remote_ip</span><span class="p">).</span><span class="nf">tap</span> <span class="k">do</span> <span class="o">|</span><span class="n">session</span><span class="o">|</span>
<span class="no">Current</span><span class="p">.</span><span class="nf">session</span> <span class="o">=</span> <span class="n">session</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>
<p>Y modificaremos el <code class="language-plaintext highlighter-rouge">create</code> de <code class="language-plaintext highlighter-rouge">SessionsController</code> para que las respuestas sean en formato json y no redirecciones:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/controllers/sessions_controller.rb</span>
<span class="k">def</span> <span class="nf">create</span>
<span class="k">if</span> <span class="n">user</span> <span class="o">=</span> <span class="no">User</span><span class="p">.</span><span class="nf">authenticate_by</span><span class="p">(</span><span class="n">params</span><span class="p">.</span><span class="nf">permit</span><span class="p">(</span><span class="ss">:email_address</span><span class="p">,</span> <span class="ss">:password</span><span class="p">))</span>
<span class="n">start_new_session_for</span> <span class="n">user</span>
<span class="n">render</span> <span class="ss">json: </span><span class="p">{</span> <span class="ss">data: </span><span class="p">{</span> <span class="ss">token: </span><span class="no">Current</span><span class="p">.</span><span class="nf">session</span><span class="p">.</span><span class="nf">token</span> <span class="p">}</span> <span class="p">}</span>
<span class="k">else</span>
<span class="n">render</span> <span class="ss">json: </span><span class="p">{},</span> <span class="ss">status: :unauthorized</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre></div></div>
<p><strong>Para hacer que todo esto funcione debemos hacer dos cosas:</strong></p>
<ol>
<li>
<p>Incluir el modulo <code class="language-plaintext highlighter-rouge">Authentication</code> en <code class="language-plaintext highlighter-rouge">ApplicationController</code>:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/controllers/application_controller.rb</span>
<span class="k">class</span> <span class="nc">ApplicationController</span> <span class="o">&lt;</span> <span class="no">ActionController</span><span class="o">::</span><span class="no">API</span>
<span class="kp">include</span> <span class="no">Authentication</span>
<span class="k">end</span>
</code></pre></div> </div>
</li>
<li>
<p>Eliminar la linea numero 6 de este mismo concern:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># app/controllers/concerns/authentication.rb</span>
<span class="n">included</span> <span class="k">do</span>
<span class="n">before_action</span> <span class="ss">:require_authentication</span>
<span class="n">helper_method</span> <span class="ss">:authenticated?</span> <span class="c1"># This, we don't use helpers in APIs</span>
<span class="k">end</span>
</code></pre></div> </div>
</li>
</ol>
<p>Hasta este punto ya deberíamos tener el <strong>login funcionando</strong>. Para probar esto voy a agregar <a href="https://github.com/a-chacon/oas_rails">OasRails</a>, que a propósito <strong>ya está funcionando con Rails 8</strong> y voy a enviar un par de peticiones a ver como se comporta, no explicaré como implementar OasRails, para eso puedes ver el repositorio o leer más en <a href="/on rails/2024/07/25/documenting-rails-apis">este post</a>.</p>
<p>Inicio de sesión exitoso:</p>
<p><img src="/assets/images/rails8_success_login.png" alt="" /></p>
<p>Inicio de sesión fallido:</p>
<p><img src="/assets/images/rails8_fail_login.png" alt="" /></p>
<hr />
<p>Ya podemos generar tokens, ahora modificaremos el código para <strong>autenticarnos con ese mismo token</strong>. Para eso, cambiaremos la lógica de buscar la sesión actual del usuario con base en la cookie a buscarla basándonos en la cabecera <code class="language-plaintext highlighter-rouge">Authorization</code>:</p>
<div class="language-ruby highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="c1"># app/controllers/concerns/authentication.rb</span>
<span class="k">def</span> <span class="nf">resume_session</span>
<span class="no">Current</span><span class="p">.</span><span class="nf">session</span> <span class="o">=</span> <span class="n">find_session_by_token</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">find_session_by_cookie</span>
<span class="no">Session</span><span class="p">.</span><span class="nf">find_by</span><span class="p">(</span><span class="ss">token: </span><span class="n">request</span><span class="p">.</span><span class="nf">headers</span><span class="p">[</span><span class="ss">:authorization</span><span class="p">]</span><span class="o">&amp;</span><span class="p">.</span><span class="nf">split</span><span class="p">(</span><span class="s2">" "</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span>
<span class="k">end</span>
</code></pre></div></div>
<p>Para probar esto creo que tendremos que hacer rápidamente un modelo que dependa de <code class="language-plaintext highlighter-rouge">User</code> y que requiera autenticación para utilizar. Intentemos con <code class="language-plaintext highlighter-rouge">rails g scaffold project title:string description:text user:references</code> y le agregamos al principio del controlador la línea de código <code class="language-plaintext highlighter-rouge">before_action :require_authentication</code>.</p>
<p>Aquí les dejo una pequeña prueba del index de Projects autenticado con el token que obtuve en las pruebas anteriores:</p>
<p><img src="/assets/images/rails8_projects.png" alt="" /></p>
<hr />
<p>Con esto ya tienes gran parte de la lógica de autenticación funcionando en la aplicación API-Only. Te queda continuar con las modificaciones en el resto de los endpoints para que las respuestas sean en formato json y no supuestas vistas que no existen en la aplicación.</p>
<p>Probablemente de aquí a que se lance la versión final de Rails 8 aparezca un <strong>PR solucionando esto y el generador funcione correctamente en modo API-Only</strong>. Hasta entonces, con estas pequeñas modificaciones ya puedes seguir construyendo tu API.</p>
</div>
<div class="mx-auto py-8">
<p class="text-center font-extrabold italic">
¿Te gustó? ¡Compártelo!
</p>
<div class="sharing-buttons flex flex-wrap gap-1 justify-center ">
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
target="_blank" rel="noopener"
href="https://facebook.com/sharer/sharer.php?u=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html"
aria-label="Share on Facebook">
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
class="w-5 h-5">
<title>Facebook</title>
<path
d="M379 22v75h-44c-36 0-42 17-42 41v54h84l-12 85h-72v217h-88V277h-72v-85h72v-62c0-72 45-112 109-112 31 0 58 3 65 4z">
</path>
</svg>
</a>
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
target="_blank" rel="noopener"
href="https://twitter.com/intent/tweet?url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html&text=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only."
aria-label="Share on Twitter">
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
class="w-5 h-5">
<title>Twitter</title>
<path
d="m459 152 1 13c0 139-106 299-299 299-59 0-115-17-161-47a217 217 0 0 0 156-44c-47-1-85-31-98-72l19 1c10 0 19-1 28-3-48-10-84-52-84-103v-2c14 8 30 13 47 14A105 105 0 0 1 36 67c51 64 129 106 216 110-2-8-2-16-2-24a105 105 0 0 1 181-72c24-4 47-13 67-25-8 24-25 45-46 58 21-3 41-8 60-17-14 21-32 40-53 55z">
</path>
</svg>
</a>
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
target="_blank" rel="noopener"
href="https://www.linkedin.com/shareArticle?mini=true&url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html&title=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only.&summary=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only.&source=https://a-chacon.com"
aria-label="Share on Linkedin">
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
class="w-5 h-5">
<title>Linkedin</title>
<path
d="M136 183v283H42V183h94zm6-88c1 27-20 49-53 49-32 0-52-22-52-49 0-28 21-49 53-49s52 21 52 49zm333 208v163h-94V314c0-38-13-64-47-64-26 0-42 18-49 35-2 6-3 14-3 23v158h-94V183h94v41c12-20 34-48 85-48 62 0 108 41 108 127z">
</path>
</svg>
</a>
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
target="_blank" rel="noopener"
href="https://pinterest.com/pin/create/button/?url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html&media=https://a-chacon.com&description=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only."
aria-label="Share on Pinterest" draggable="false">
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
class="w-5 h-5">
<title>Pinterest</title>
<path
d="M268 6C165 6 64 75 64 186c0 70 40 110 64 110 9 0 15-28 15-35 0-10-24-30-24-68 0-81 62-138 141-138 68 0 118 39 118 110 0 53-21 153-90 153-25 0-46-18-46-44 0-38 26-74 26-113 0-67-94-55-94 25 0 17 2 36 10 51-14 60-42 148-42 209 0 19 3 38 4 57 4 3 2 3 7 1 51-69 49-82 72-173 12 24 44 36 69 36 106 0 154-103 154-196C448 71 362 6 268 6z">
</path>
</svg>
</a>
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
target="_blank" rel="noopener"
href="https://reddit.com/submit/?url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html&resubmit=true&title=PoC: Usando el Generador de Autenticación de Rails 8 (Beta) En Modo API-Only."
aria-label="Share on Reddit" draggable="false">
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
class="w-5 h-5">
<title>Reddit</title>
<path
d="M440 204c-15 0-28 6-38 15-35-24-83-40-137-42l28-125 88 20c0 22 18 39 39 39 22 0 40-18 40-39s-17-40-40-40c-15 0-28 9-35 22l-97-22c-5-1-10 3-11 7l-31 138c-53 2-100 18-136 43a53 53 0 0 0-38-16c-56 0-74 74-23 100l-3 24c0 84 95 152 210 152 117 0 211-68 211-152 0-8-1-17-3-25 50-25 32-99-24-99zM129 309a40 40 0 1 1 80 0 40 40 0 0 1-80 0zm215 93c-37 37-139 37-176 0-4-3-4-9 0-13s10-4 13 0c28 28 120 29 149 0 4-4 10-4 14 0s4 10 0 13zm-1-54c-22 0-39-17-39-39a39 39 0 1 1 39 39z">
</path>
</svg>
</a>
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
target="_blank" rel="noopener"
href="https://wa.me/?text=PoC:%20Usando%20el%20Generador%20de%20Autenticaci%C3%B3n%20de%20Rails%208%20(Beta)%20En%20Modo%20API-Only.%20https://a-chacon.com"
aria-label="Share on Whatsapp" draggable="false">
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
class="w-5 h-5">
<title>Whatsapp</title>
<path
d="M413 97A222 222 0 0 0 64 365L31 480l118-31a224 224 0 0 0 330-195c0-59-25-115-67-157zM256 439c-33 0-66-9-94-26l-7-4-70 18 19-68-4-7a185 185 0 0 1 287-229c34 36 56 82 55 131 1 102-84 185-186 185zm101-138c-5-3-33-17-38-18-5-2-9-3-12 2l-18 22c-3 4-6 4-12 2-32-17-54-30-75-66-6-10 5-10 16-31 2-4 1-7-1-10l-17-41c-4-10-9-9-12-9h-11c-4 0-9 1-15 7-5 5-19 19-19 46s20 54 23 57c2 4 39 60 94 84 36 15 49 17 67 14 11-2 33-14 37-27s5-24 4-26c-2-2-5-4-11-6z">
</path>
</svg>
</a>
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700"
target="_blank" rel="noopener"
href="https://telegram.me/share/url?text=PoC:%20Usando%20el%20Generador%20de%20Autenticaci%C3%B3n%20de%20Rails%208%20(Beta)%20En%20Modo%20API-Only.&url=https://a-chacon.com/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html"
aria-label="Share on Telegram" draggable="false">
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
class="w-5 h-5">
<title>Telegram</title>
<path
d="M256 8a248 248 0 1 0 0 496 248 248 0 0 0 0-496zm115 169c-4 39-20 134-28 178-4 19-10 25-17 25-14 2-25-9-39-18l-56-37c-24-17-8-25 6-40 3-4 67-61 68-67l-1-4-5-1q-4 1-105 70-15 10-27 9c-9 0-26-5-38-9-16-5-28-7-27-16q1-7 18-14l145-62c69-29 83-34 92-34 2 0 7 1 10 3l4 7a43 43 0 0 1 0 10z">
</path>
</svg>
</a>
<a class="border-2 duration-200 ease inline-flex items-center mb-1 mr-1 transition p-2 rounded-full text-white border-slate-600 bg-slate-600 hover:bg-slate-700 hover:border-slate-700" target="_blank" rel="noopener" href="/cdn-cgi/l/email-protection#79460a0c1b131c1a0d4429163a435c4b492c0a18171d165c4b491c155c4b493e1c171c0b181d160b5c4b491d1c5c4b49380c0d1c170d101a181a105c3a4a5c3b4a175c4b491d1c5c4b492b1810150a5c4b49415c4b49513b1c0d18505c4b493c175c4b4934161d165c4b493829305436171500575f1b161d0044110d0d090a43565618541a11181a1617571a16145616175c4b490b1810150a564b494b4d56484956484f5609161a540c0a10171e540b1810150a544154180c0d11540a000a0d1c1454101754180910541617150057110d1415" aria-label="Share by Email" draggable="false">
<svg aria-hidden="true" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"
class="w-5 h-5">
<title>Email</title>
<path
d="M464 64a48 48 0 0 1 29 86L275 314c-11 8-27 8-38 0L19 150a48 48 0 0 1 29-86h416zM218 339c22 17 54 17 76 0l218-163v208c0 35-29 64-64 64H64c-35 0-64-29-64-64V176l218 163z">
</path>
</svg>
</a>
</div>
</div>
<div class="font-mulish flex justify-center mb-10">
<a class="pr-2" href="/docker/2024/09/16/run-llm-locally.html">&laquo; LLM en local: Corriendo Ollama y Open WebUI con Docker Compose.</a>
</div>
<!-- <div class="mx-auto py-8"> -->
<!-- <script type="text/javascript" src="https://cdnjs.buymeacoffee.com/1.0.0/button.prod.min.js" data-name="bmc-button" -->
<!-- data-slug="achacon" data-color="#FFDD00" data-emoji="" data-font="Lato" data-text="Buy me a coffee" -->
<!-- data-outline-color="#000000" data-font-color="#000000" data-coffee-color="#ffffff"></script> -->
<!-- </div> -->
<!---->
<!-- <div class="my-6"> -->
<!-- ¡Hola a todos! 👋 ¿Disfrutaron leyendo el artículo? ¡Me encantaría conocer sus opiniones! 💬 No duden en dejar un -->
<!-- comentario abajo, ya sea para compartir sus comentarios, preguntas o simplemente saludar. ¡No es necesario -->
<!-- registrarse, solo compartan algo valioso! 😊 -->
<!-- </div> -->
<!-- <div class="my-6"> -->
<!-- Hey there! 👋 Enjoyed reading the post? I'd love to hear your thoughts! 💬 Feel free to drop a comment -->
<!-- below—whether it's feedback, questions, or just saying hi. No need to sign up, just share something valuable! 😊 -->
<!-- </div> -->
<!---->
<!-- <div id="embedContainer" style="height: fit-content;" data-identifier="/on%20rails/2024/10/16/poc-using-rails-8-auth-system-in-api-only.html" -->
<!-- data-site-key="80dce74b8e1af5839a6f"></div> -->
<!-- <script src="https://opina.fly.dev/embed.js"></script> -->
</div>
</div>
<footer class="w-full bottom-0">
<hr class="my-8 border-zinc-200" />
<div class="container mx-auto">
<div class="flex flex-wrap text-left">
<div class="w-full md:w-6/12 md:px-4">
<p class="text-3xl font-semibold">
Mantengamosnos en contacto!
</p>
<p class="font-mulish text-lg dark:text-zinc-300 mt-2 mb-2">
Encuéntrame en cualquiera de estas plataformas:
</p>
<div class="flex justify-center md:justify-start pt-2 gap-6">
<a class="transition hover:scale-110 duration-300" href="/cdn-cgi/l/email-protection#b7d6d9d3c5d2c499d4dff7c7c5d8c3d8d9dad6dedb99d4d8da">
<img
class="h-6 w-6"
src="/assets/images/contact_channels/email.svg"
alt="Email Icon"
/>
</a>
<a
class="transition hover:scale-110 duration-300"
href="https://github.com/a-chacon"
target="_blank"
>
<img
class="h-6 w-6"
src="/assets/images/contact_channels/github-mark.svg"
alt="Github Icon"
/>
</a>
<a
class="transition hover:scale-110 duration-300"
href="https://t.me/a_chacon"
target="_blank"
>
<img
class="h-6 w-6"
src="/assets/images/contact_channels/telegram.svg"
alt="Telegram Icon"
/>
</a>
<a
class="transition hover:scale-110 duration-300"
href="https://stackoverflow.com/users/16847024/andr%c3%a9s"
target="_blank"
>
<img
class="h-6 w-6"
src="/assets/images/contact_channels/stack-overflow.svg"
alt="StackOverflow Icon"
/>
</a>
<a
class="transition hover:scale-110 duration-300"
href="https://discord.com/users/673943171369140252"
target="_blank"
>
<img
class="h-6 w-6"
src="/assets/images/contact_channels/discord.svg"
alt="Discord Icon"
/>
</a>
<a
class="transition hover:scale-110 duration-300"
rel="me"
href="https://lile.cl/@achacon"
target="_blank"
>
<img
class="h-6 w-6"
src="/assets/images/contact_channels/mastodon.svg"
alt="Mastodon Icon"
/>
</a>
</div>
</div>
<div class="w-full md:w-6/12 md:text-right py-4 md:py-0">
<div class="flex flex-wrap items-top mb-6">
<div class="w-full lg:w-4/12 md:px-4 ml-auto">
<span class="text-lg block text-gray-800 mb-2">
Páginas
</span>
<ul>
<li>
<a class="font-mulish text-slate-600 hover:text-sky-400 dark:text-slate-300 dark:hover:text-slate-200"
href="/blog.html">Blog</a>
</li>
<li>
<a class="font-mulish text-slate-600 hover:text-sky-400 dark:text-slate-300 dark:hover:text-slate-200"
href="/">Casa</a>
</li>
<li>
<a class="font-mulish text-slate-600 hover:text-sky-400 dark:text-slate-300 dark:hover:text-slate-200"
href="/projects">Proyectos</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="font-mulish flex flex-wrap items-center md:justify-between justify-center my-8">
<div class="w-full md:w-4/12 px-4 mx-auto text-center">
<a href="/feed.xml" class="p-2">
<svg fill="#000000" viewBox="-3 0 19 19" xmlns="http://www.w3.org/2000/svg" class="w-10 mx-auto">
<g id="SVGRepo_bgCarrier" stroke-width="0"></g>
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
<g id="SVGRepo_iconCarrier">
<path
d="M.926 12.818a1.403 1.403 0 1 1 0 1.984 1.402 1.402 0 0 1 0-1.984zm10.531 2.357a1.03 1.03 0 0 1-1.029-1.03 8.775 8.775 0 0 0-.694-3.438A8.826 8.826 0 0 0 1.591 5.31a1.03 1.03 0 1 1 0-2.059 10.817 10.817 0 0 1 4.24.857 10.893 10.893 0 0 1 3.463 2.334 10.867 10.867 0 0 1 3.19 7.703 1.027 1.027 0 0 1-1.027 1.029zm-4.538 0a1.03 1.03 0 0 1-1.029-1.03 4.297 4.297 0 0 0-4.299-4.298 1.03 1.03 0 0 1 0-2.059 6.362 6.362 0 0 1 5.857 3.883 6.298 6.298 0 0 1 .5 2.475 1.03 1.03 0 0 1-1.029 1.029z">
</path>
</g>
</svg>
</a>
<div class="text-sm text-blueGray-500 font-semibold py-1">
© <span id="get-current-year">2024</span>
<a href="https://www.creative-tim.com/product/notus-js" class="text-blueGray-500 hover:text-gray-800"
target="_blank" aria-label="Creative C">a-chacon.</a>
All rights reserved.
<p class="text-xs pt-4">
Built with ❤️ using the
<a class="hover:text-sky-400" href="https://github.com/a-chacon/awesome-jekyll-theme">Awesome Jekyll
Theme</a>.
</p>
</div>
</div>
</div>
</div>
</footer>
<script data-cfasync="false" src="/cdn-cgi/scripts/5c5dd728/cloudflare-static/email-decode.min.js"></script><script>
document.querySelectorAll("a").forEach(function (link) {
link.addEventListener("click", function (event) {
event.preventDefault(); // Prevent the default link action temporarily
link.classList.add("gentle-clicked");
setTimeout(function () {
link.classList.remove("gentle-clicked");
window.location.href = link.href; // Navigate to the link after the animation
}, 300); // Duration of the gentle bounce animation
});
});
</script>
<script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'8dc35b4edefb4223',t:'MTczMDU0MjQ1Ni4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
</html>

View file

@ -275,7 +275,7 @@ impl FullTextParser {
/// See:
/// - <https://github.com/KWARC/rust-libxml/issues/111>
/// - <https://github.com/Orange-OpenSource/hurl/issues/1535>
/// These two functions should be removed when the issue is fixed in libxml crate.
/// These two functions should be removed when the issue is fixed in libxml crate.
fn try_usize_to_i32(value: usize) -> Result<i32, libxml::parser::XmlParseError> {
if cfg!(target_pointer_width = "16") || (value < i32::MAX as usize) {
// Cannot safely use our value comparison, but the conversion if always safe.
@ -514,6 +514,22 @@ impl FullTextParser {
return Some(thumb);
}
if let Ok(thumb) = Util::get_attribute(
context,
"//meta[contains(@property, 'twitter:image')]",
"content",
) {
return Some(thumb);
}
if let Ok(thumb) = Util::get_attribute(
context,
"//meta[contains(@property, 'og:image')]",
"content",
) {
return Some(thumb);
}
if let Ok(thumb) =
Util::get_attribute(context, "//link[contains(@rel, 'image_src')]", "href")
{

View file

@ -278,3 +278,17 @@ Foto: IMAGO/Vaclav Salek / IMAGO/CTK Photo
"https://cdn.prod.www.spiegel.de/images/a4573666-f15e-4290-8c73-a0c6cd4ad3b2_w948_r1.778_fpx29.99_fpy44.98.jpg"
)
}
#[test]
fn extract_thumbnail_a_chacon() {
let html = std::fs::read_to_string(format!("./resources/tests/thumbnails/a-chacon.html"))
.expect("Failed to read source HTML");
let doc = FullTextParser::parse_html_string_patched(&html).unwrap();
let ctx = Context::new(&doc).unwrap();
let thumb = FullTextParser::check_for_thumbnail(&ctx).unwrap();
assert_eq!(
thumb,
"https://a-chacon.com/assets/images/rails8-poc-api-auth.webp"
)
}