{"id":517,"date":"2023-09-24T16:16:49","date_gmt":"2023-09-24T21:16:49","guid":{"rendered":"https:\/\/80bits.blog\/?p=517"},"modified":"2023-09-24T16:42:04","modified_gmt":"2023-09-24T21:42:04","slug":"fake-api-generar-servicios-http-rest-en-nodejs-para-simular-micro-servicios","status":"publish","type":"post","link":"https:\/\/80bits.blog\/index.php\/2023\/09\/24\/fake-api-generar-servicios-http-rest-en-nodejs-para-simular-micro-servicios\/","title":{"rendered":"Fake Api &#8211; Generar servicios HTTP Rest en NodeJS para simular micro servicios"},"content":{"rendered":"\n<p>Esta semana, tuve que poner en marcha varios micro servicios, algunos de ellos estaban en im\u00e1genes <a href=\"https:\/\/www.docker.com\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Docker<\/a> y en la mayor\u00eda de los casos, s\u00f3lo necesitaba hacer una o dos consultas, ya que estaba buscando datos espec\u00edficos, como realizar un login o validar cierta informaci\u00f3n.<\/p>\n\n\n\n<p>Lo que hice fue desarrollar un c\u00f3digo sencillo en NodeJS que puede generar uno o varios micro servicios a partir de un archivo JSON y retornar los datos que necesite. Eleg\u00ed NodeJS porque me permite crear un servicio HTTP desde cero, sin dependencias ni abstracciones. Aunque hay otros lenguajes que tambi\u00e9n lo permiten, <a href=\"https:\/\/80bits.blog\/index.php\/2022\/01\/27\/net-6-minimal-api-rest\/\" target=\"_blank\" rel=\"noopener\" title=\"\">algunos tienen m\u00e1s abstracciones que otros<\/a>.<\/p>\n\n\n\n<p>El archivo JSON solo es un Array donde se especifica el nombre, puerto y rutas para generar los servicios.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">C\u00f3digo<\/h2>\n\n\n\n<p>Es muy simple y esta escrito en un solo archivo debido a que no es demasiado extenso, y no tiene dependencias mas que <a href=\"https:\/\/www.npmjs.com\/package\/prettier\" target=\"_blank\" rel=\"noopener\" title=\"\">prettier<\/a> que me sirve para formatear el c\u00f3digo, pero es dependencia de desarrollo por lo que se puede prescindir de ella.<\/p>\n\n\n\n<p>Todos los servicios que se generan tiene una validaci\u00f3n de tipo <em>OPTIONS<\/em>, en caso de haber problemas de tipo <a href=\"https:\/\/developer.mozilla.org\/es\/docs\/Web\/HTTP\/CORS\" target=\"_blank\" rel=\"noopener\" title=\"\">CORS<\/a> y lo dem\u00e1s son solo b\u00fasquedas de las rutas y m\u00e9todos que hay en el archivo JSON.<\/p>\n\n\n\n<p>El archivo de configuraci\u00f3n JSON debe llamarse <em><strong>servers.json<\/strong><\/em>, y as\u00ed debe ser nombrado ya que esta ligado al c\u00f3digo, pero cambiarlo es trivial y la misma referencia al nombre esta en el archivo <strong><em>.gitignore<\/em><\/strong> para que este no se suba al repositorio y el c\u00f3digo sea mas limpio.<\/p>\n\n\n\n<p>Las peticiones se resuelven con rutas exactas no permite comodines ni par\u00e1metros, y tampoco valida el contenido de una petici\u00f3n, esto por que no quise complicar el c\u00f3digo con eventos y\/o promesas para leer el body, ademas de que lo \u00fanico que me interesaba es el contenido de la respuesta.<\/p>\n\n\n\n<p>Si se necesita enviar <em>query params<\/em> entonces hay que agregarlo tal cual se van a enviar esto por la validaci\u00f3n exacta de rutas.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Ejecutar el c\u00f3digo<\/h2>\n\n\n\n<p>Recomiendo hacer uso de <a href=\"https:\/\/nodemon.io\/\" target=\"_blank\" rel=\"noopener\" title=\"\">nodemon<\/a>, ya que asi pueden cambiar el archivo JSON y autom\u00e1ticamente se reflejan los cambios en los servicios.<\/p>\n\n\n\n<p>npm i -g nodemon<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>node index.js\nnodemon index.js<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" width=\"432\" height=\"187\" src=\"https:\/\/80bits.blog\/wp-content\/uploads\/2023\/09\/screenshot_fakeapi_console1.png\" alt=\"\" class=\"wp-image-540\"\/><\/figure>\n\n\n\n<p>Salida ejecutando nodemon y el archivo JSON de ejemplo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Ejemplo JSON<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;\n    {\n        \"name\": \"server 1\",\n        \"notFound\": {\n            \"status\": 404,\n            \"body\": {\n                \"error\": \"not_found\"\n            }\n        },\n        \"port\": 3000,\n        \"paths\": &#91;\n            {\n                \"path\": \"\/profile\",\n                \"methods\": &#91;\n                    {\n                        \"method\": \"get\",\n                        \"response\": {\n                            \"status\": 200,\n                            \"body\": {\n                                \"id\": \"123456789\",\n                                \"name\": \"John Doe\"\n                            },\n                            \"headers\": {\n                                \"Content-Type\": \"application\/json\"\n                            }\n                        }\n                    }\n                ]\n            }\n        ]\n    },\n    {\n        \"name\": \"server 2\",\n        \"notFound\": {\n            \"status\": 404,\n            \"body\": {\n                \"error\": \"not_found\"\n            }\n        },\n        \"port\": 4000,\n        \"paths\": &#91;\n            {\n                \"path\": \"\/login\",\n                \"methods\": &#91;\n                    {\n                        \"method\": \"post\",\n                        \"response\": {\n                            \"status\": 200,\n                            \"body\": {\n                                \"token\": \"123456789\"\n                            }\n                        }\n                    }\n                ]\n            }\n        ]\n    }\n]<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Propiedades del JSON<\/h2>\n\n\n\n<figure class=\"wp-block-table is-style-stripes\"><table><tbody><tr><td><strong>Propiedad<\/strong><\/td><td><strong>Descripci\u00f3n<\/strong> <\/td><\/tr><tr><td>name<\/td><td>Simplemente el nombre del servicio, no es necesario, simplemente se imprime en un log y como descripci\u00f3n al iniciar el servicio.<\/td><\/tr><tr><td>port<\/td><td>Es el numero de puerto donde se creara el servicio, si este es menor a 80 entonces no se creara el servicio.<\/td><\/tr><tr><td>paths<\/td><td>Array que describen las rutas que se van a generar para el servicio<\/td><\/tr><tr><td>path<\/td><td>Ruta a la cual responder\u00e1 una petici\u00f3n.<\/td><\/tr><tr><td>methods<\/td><td>Array de todos los metodos o verbos http que soportara una ruta<\/td><\/tr><tr><td>method<\/td><td>Nombre del m\u00e9todo o verbo http que soportara una ruta, pueden ser los t\u00edpicos, GET, PUT, POST, DELETE, pero por la manera que esta escrito el c\u00f3digo puede ser cualquier texto. La condici\u00f3n es deben ser en min\u00fasculas nada mas.<\/td><\/tr><tr><td>response<\/td><td>Dentro tiene propiedades que describen la respuesta de la ruta.<\/td><\/tr><tr><td>status<\/td><td>Es el c\u00f3digo http de la respuesta a la petici\u00f3n.<\/td><\/tr><tr><td>body<\/td><td>Propiedad de respuesta a la petici\u00f3n y puede contener cualquier valor y\/o propiedad.<\/td><\/tr><tr><td>headers<\/td><td>Las cabeceras de respuesta a la peticion, en caso de no existir esta propiedad por default agregara la respuesta. &#8220;Content-Type&#8221;: &#8220;application\/json&#8221;<\/td><\/tr><tr><td>notFound<\/td><td>Contiene solo un body y un status que el servidor responder\u00e1 en caso de no encontrar una ruta valida.<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>El archivo JSON anterior genera dos servicios, uno escuchando en el puerto 3000 y otro en el puerto 4000 y dos rutas que responden.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>curl --location 'http:\/\/localhost:3000\/profile'<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>curl --location --request POST 'http:\/\/localhost:4000\/login'<\/code><\/pre>\n\n\n\n<p>Eso es todo lo que hace el c\u00f3digo, no es nada del otro mundo ni nada complejo, me llevo mas tiempo escribir esta entrada que programarlo &gt;D, <\/p>\n\n\n\n<p>Espero les sea de utilidad para m\u00faltiples proyectos, incluso deber\u00eda servir en ambientes productivos y con alta carga ya que todo se ejecuta en memoria ram.<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/genitalico\/fakeapi\" title=\"\">Puedes clonar el proyecto desde aqu\u00ed<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Generar micro servicios falsos en NodeJS mediante un archivo de configuraci\u00f3n JSON<\/p>\n","protected":false},"author":1,"featured_media":524,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[22,28,20,64,29,1],"tags":[79,78,34,35,32],"class_list":["post-517","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-frameworks","category-js","category-lenguajes-de-programacion","category-microservicios","category-nodejs","category-sin-categoria","tag-api","tag-http","tag-javascript","tag-js","tag-nodejs"],"jetpack_featured_media_url":"https:\/\/80bits.blog\/wp-content\/uploads\/2023\/09\/an_astronaut_surfing_on_the_moon_with_earth_in_the-background.jpeg","jetpack-related-posts":[],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/posts\/517","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/comments?post=517"}],"version-history":[{"count":24,"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/posts\/517\/revisions"}],"predecessor-version":[{"id":546,"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/posts\/517\/revisions\/546"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/media\/524"}],"wp:attachment":[{"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/media?parent=517"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/categories?post=517"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/tags?post=517"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}