{"id":955,"date":"2024-12-02T15:43:28","date_gmt":"2024-12-02T20:43:28","guid":{"rendered":"https:\/\/80bits.blog\/?p=955"},"modified":"2024-12-02T15:43:30","modified_gmt":"2024-12-02T20:43:30","slug":"golang-codigo-para-crear-servicios-http-rest-falsos","status":"publish","type":"post","link":"https:\/\/80bits.blog\/index.php\/2024\/12\/02\/golang-codigo-para-crear-servicios-http-rest-falsos\/","title":{"rendered":"Golang &#8211; C\u00f3digo para crear servicios Http Rest falsos"},"content":{"rendered":"\n<p>En estos d\u00edas he estado desarrollando un proxy inverso simple en NodeJS para un servidor en Linux que tengo con algunos servicios, por lo que para algunas pruebas necesito precisamente ver si redirecciona peticiones a distintos puertos y rutas diferentes.<\/p>\n\n\n\n<p>Hay herramientas como <a href=\"https:\/\/wiremock.org\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Wiremock<\/a> que son opensource o que funcionan muy bien, pero yo necesitaba algo m\u00e1s sencillo y que adem\u00e1s pudiera en caso de ser necesario integrarlo f\u00e1cil en pruebas unitarias, por ello utilize <a href=\"https:\/\/go.dev\/\" target=\"_blank\" rel=\"noopener\" title=\"\">Golang<\/a> para crear esta herramienta ya que puedo simplemente agregar el binario a mi proyecto y listo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Servicio Http Rest m\u00ednimo<\/h2>\n\n\n\n<p>En Golang se puede crear un servicio rest bastante r\u00e1pido y de manera muy simple:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>package main\n\nimport (\n\t\"encoding\/json\"\n\t\"fmt\"\n\t\"log\"\n\t\"net\/http\"\n)\n\ntype Response struct {\n\tMessage string `json:\"message\"`\n}\n\nfunc handler(w http.ResponseWriter, r *http.Request) {\n\t\/\/ Crear una respuesta\n\tresponse := Response{\n\t\tMessage: \"Hola, este es un servicio REST en Go\",\n\t}\n\n\n\tw.Header().Set(\"Content-Type\", \"application\/json\")\n\tw.WriteHeader(http.StatusOK)\n\n\tif err := json.NewEncoder(w).Encode(response); err != nil {\n\t\thttp.Error(w, err.Error(), http.StatusInternalServerError)\n\t}\n}\n\nfunc main() {\n\thttp.HandleFunc(\"\/api\", handler)\n\tfmt.Println(\"Servidor corriendo en http:\/\/localhost:8080\")\n\tlog.Fatal(http.ListenAndServe(\":8080\", nil))\n}<\/code><\/pre>\n\n\n\n<p>El c\u00f3digo anterior permite peticiones en \/api de todo tipo no hay m\u00e1s l\u00f3gica en ello.<\/p>\n\n\n\n<p>Y bas\u00e1ndome en esto mismo lo que hice fue crear un servicio que escuchara en varios puertos y que atendieran a distintas rutas y m\u00e9todos, toda esta configuraci\u00f3n debe ser le\u00edda desde un archivo JSON ahi se va a describir las rutas, m\u00e9todos, la respuesta de los c\u00f3digos de estado y cuerpo.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Ejemplo de configuraci\u00f3n JSON<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>&#91;\n    {\n        \"name\": \"Fake server\",\n        \"notFound\": {\n            \"status\": 404,\n            \"body\": {\n                \"error\": \"not_found\"\n            }\n        },\n        \"port\": 6000,\n        \"paths\": &#91;\n            {\n                \"path\": \"\/login?parameter=1\",\n                \"methods\": &#91;\n                    {\n                        \"method\": \"post\",\n                        \"response\": {\n                            \"status\": 200,\n                            \"body\": {\n                                \"message\": \"OK\",\n                                \"One\": 1\n                            },\n                            \"headers\": {\n                                \"Content-Type\": \"application\/json\"\n                            }\n                        }\n                    },\n                    {\n                        \"method\": \"get\",\n                        \"description\": \"login fake simulate just to get the god response error\",\n                        \"response\": {\n                            \"status\": 401,\n                            \"body\": {\n                                \"message\": \"invalid password\"\n                            }\n                        },\n                        \"headers\": {\n                            \"Content-Type\": \"application\/json\"\n                        }\n                    }\n                ]\n            }\n        ]\n    },\n    {\n        \"name\": \"Fake server 2\",\n        \"notFound\": {\n            \"status\": 404,\n            \"body\": {\n                \"error\": \"not_found\"\n            }\n        },\n        \"port\": 8000,\n        \"paths\": &#91;\n            {\n                \"path\": \"\/auth\/login\",\n                \"methods\": &#91;\n                    {\n                        \"method\": \"post\",\n                        \"response\": {\n                            \"status\": 200,\n                            \"body\": {\n                                \"message\": \"Login\"\n                            },\n                            \"headers\": {\n                                \"Content-Type\": \"application\/json\"\n                            }\n                        }\n                    },\n                    {\n                        \"method\": \"get\",\n                        \"description\": \"login fake simulate just to get the god response error\",\n                        \"response\": {\n                            \"status\": 401,\n                            \"body\": {\n                                \"message\": \"invalid\"\n                            }\n                        },\n                        \"headers\": {\n                            \"Content-Type\": \"application\/json\"\n                        }\n                    }\n                ]\n            }\n        ]\n    }\n]<\/code><\/pre>\n\n\n\n<p>El ejemplo anterior es un array de objetos con las siguientes propiedades:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Settings<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Propiedad<\/th><th>Tipo<\/th><\/tr><\/thead><tbody><tr><td>Name<\/td><td>string<\/td><\/tr><tr><td>NotFound<\/td><td>NotFoundModel<\/td><\/tr><tr><td>Port<\/td><td>int<\/td><\/tr><tr><td>Path<\/td><td>[]PathModel<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">NotFoundModel<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Propiedad<\/th><th>Tipo<\/th><\/tr><\/thead><tbody><tr><td>Status<\/td><td>int<\/td><\/tr><tr><td>Body<\/td><td>map[string]interface{}<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">PathModel<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Propiedad<\/th><th>Tipo<\/th><\/tr><\/thead><tbody><tr><td>Path<\/td><td>string<\/td><\/tr><tr><td>Methods<\/td><td>[]MethodModel<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">MethodModel<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Propiedad<\/th><th>Tipo<\/th><\/tr><\/thead><tbody><tr><td>Method<\/td><td>string<\/td><\/tr><tr><td>Response<\/td><td>ResponseModel<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">ResponseModel<\/h3>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th>Propiedad<\/th><th>Tipo<\/th><\/tr><\/thead><tbody><tr><td>Status<\/td><td>int<\/td><\/tr><tr><td>Body<\/td><td>map[string]interface{}<\/td><\/tr><tr><td>Headers<\/td><td>map[string]string<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Las m\u00e1s importantes son <code>port<\/code> que va a definir el puerto donde escuchara cada servicio y <code>path<\/code> que es la ruta que va a definir la petici\u00f3n para que funcione, en caso de que la ruta no este definida lo que responder\u00e1 el servicio sera lo que este descrito en <code>NotFoundModel<\/code> o en caso contrario regresara un http 500.<\/p>\n\n\n\n<p>Dentro de cada <code>path<\/code> hay un array de m\u00e9todos http, los cuales ser\u00e1n los distintos m\u00e9todos <code>MethodModel<\/code> a los cuales puede responder el servidor, una ruta, por ejemplo \/api puede regresar datos usando GET o POST seg\u00fan sea el caso.<\/p>\n\n\n\n<p>Por \u00faltimo, dentro de cada <code>MethodModel<\/code> existe un <code>ResponseModel<\/code> que tiene el <code>Body<\/code> y <code>Headers<\/code> que va a retornar cada path.<\/p>\n\n\n\n<p>Eso es todo bastante sencillo y practico para crear respuestas falsas o mocks.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Ejecutar C\u00f3digo<\/h2>\n\n\n\n<p>Para ejecutar el c\u00f3digo simplemente hay que hacer <code>go run .<\/code> y listo, el archivo JSON debe tener el nombre <code>servers.json<\/code> o se le tiene que pasar un nombre por par\u00e1metros en la consola <code>go run . file.json<\/code>.<\/p>\n\n\n\n<p>Tambien dentro del proyecto y c\u00f3digo existe un archivo makefile que tiene algunos targets para compilar a distintas plataformas y sistemas, estos targets generan un ejecutable de nombre <code>fakeapi.exe<\/code>. <\/p>\n\n\n\n<p>Por ejemplo, para compilar para Apple silicon el comando es: <code>make build.darwinM<\/code>.<\/p>\n\n\n\n<p>Para ejecutarlo simplemente hay que hacer en la consola: <code>.\/fakeapi.exe file.json<\/code><\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/genitalico\/golangfakeapi\" target=\"_blank\" rel=\"noopener\" title=\"\">El c\u00f3digo lo pueden encontrar en github<\/a>, <a href=\"https:\/\/80bits.blog\/index.php\/2023\/09\/24\/fake-api-generar-servicios-http-rest-en-nodejs-para-simular-micro-servicios\/\" target=\"_blank\" rel=\"noopener\" title=\"\">tengo uno similar en NodeJS pero al no ser un binario ejecutable no serv\u00eda para estos prop\u00f3sitos.<\/a> Ademas de ser mas enrreado considero que lo programe peor \ud83d\ude00 <\/p>\n","protected":false},"excerpt":{"rendered":"<p>En estos d\u00edas he estado desarrollando un proxy inverso simple en NodeJS para un servidor en Linux que tengo con algunos servicios, por lo que para algunas pruebas necesito precisamente ver si redirecciona peticiones a distintos puertos y rutas diferentes. Hay herramientas como Wiremock que son opensource o que funcionan muy bien, pero yo necesitaba [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":975,"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":[80,20,66,49,64,1,65,67],"tags":[79,52,78,73,107,108],"class_list":["post-955","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-golang","category-lenguajes-de-programacion","category-linux","category-macos","category-microservicios","category-sin-categoria","category-sistemas-operativos","category-windows","tag-api","tag-consola","tag-http","tag-linux","tag-microservices","tag-microservicios"],"jetpack_featured_media_url":"https:\/\/80bits.blog\/wp-content\/uploads\/2024\/12\/A-cartoon-of-a-hamster-running-a-marathon.webp","jetpack-related-posts":[],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/posts\/955","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=955"}],"version-history":[{"count":20,"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/posts\/955\/revisions"}],"predecessor-version":[{"id":976,"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/posts\/955\/revisions\/976"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/media\/975"}],"wp:attachment":[{"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/media?parent=955"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/categories?post=955"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/80bits.blog\/index.php\/wp-json\/wp\/v2\/tags?post=955"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}