Golang – Código para crear servicios Http Rest falsos

Golang – Código para crear servicios Http Rest falsos

En estos días 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 algo más sencillo y que además pudiera en caso de ser necesario integrarlo fácil en pruebas unitarias, por ello utilize Golang para crear esta herramienta ya que puedo simplemente agregar el binario a mi proyecto y listo.

Servicio Http Rest mínimo

En Golang se puede crear un servicio rest bastante rápido y de manera muy simple:

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"net/http"
)

type Response struct {
	Message string `json:"message"`
}

func handler(w http.ResponseWriter, r *http.Request) {
	// Crear una respuesta
	response := Response{
		Message: "Hola, este es un servicio REST en Go",
	}


	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(http.StatusOK)

	if err := json.NewEncoder(w).Encode(response); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func main() {
	http.HandleFunc("/api", handler)
	fmt.Println("Servidor corriendo en http://localhost:8080")
	log.Fatal(http.ListenAndServe(":8080", nil))
}

El código anterior permite peticiones en /api de todo tipo no hay más lógica en ello.

Y basándome en esto mismo lo que hice fue crear un servicio que escuchara en varios puertos y que atendieran a distintas rutas y métodos, toda esta configuración debe ser leída desde un archivo JSON ahi se va a describir las rutas, métodos, la respuesta de los códigos de estado y cuerpo.

Ejemplo de configuración JSON

[
    {
        "name": "Fake server",
        "notFound": {
            "status": 404,
            "body": {
                "error": "not_found"
            }
        },
        "port": 6000,
        "paths": [
            {
                "path": "/login?parameter=1",
                "methods": [
                    {
                        "method": "post",
                        "response": {
                            "status": 200,
                            "body": {
                                "message": "OK",
                                "One": 1
                            },
                            "headers": {
                                "Content-Type": "application/json"
                            }
                        }
                    },
                    {
                        "method": "get",
                        "description": "login fake simulate just to get the god response error",
                        "response": {
                            "status": 401,
                            "body": {
                                "message": "invalid password"
                            }
                        },
                        "headers": {
                            "Content-Type": "application/json"
                        }
                    }
                ]
            }
        ]
    },
    {
        "name": "Fake server 2",
        "notFound": {
            "status": 404,
            "body": {
                "error": "not_found"
            }
        },
        "port": 8000,
        "paths": [
            {
                "path": "/auth/login",
                "methods": [
                    {
                        "method": "post",
                        "response": {
                            "status": 200,
                            "body": {
                                "message": "Login"
                            },
                            "headers": {
                                "Content-Type": "application/json"
                            }
                        }
                    },
                    {
                        "method": "get",
                        "description": "login fake simulate just to get the god response error",
                        "response": {
                            "status": 401,
                            "body": {
                                "message": "invalid"
                            }
                        },
                        "headers": {
                            "Content-Type": "application/json"
                        }
                    }
                ]
            }
        ]
    }
]

El ejemplo anterior es un array de objetos con las siguientes propiedades:

Settings

PropiedadTipo
Namestring
NotFoundNotFoundModel
Portint
Path[]PathModel

NotFoundModel

PropiedadTipo
Statusint
Bodymap[string]interface{}

PathModel

PropiedadTipo
Pathstring
Methods[]MethodModel

MethodModel

PropiedadTipo
Methodstring
ResponseResponseModel

ResponseModel

PropiedadTipo
Statusint
Bodymap[string]interface{}
Headersmap[string]string

Las más importantes son port que va a definir el puerto donde escuchara cada servicio y path que es la ruta que va a definir la petición para que funcione, en caso de que la ruta no este definida lo que responderá el servicio sera lo que este descrito en NotFoundModel o en caso contrario regresara un http 500.

Dentro de cada path hay un array de métodos http, los cuales serán los distintos métodos MethodModel a los cuales puede responder el servidor, una ruta, por ejemplo /api puede regresar datos usando GET o POST según sea el caso.

Por último, dentro de cada MethodModel existe un ResponseModel que tiene el Body y Headers que va a retornar cada path.

Eso es todo bastante sencillo y practico para crear respuestas falsas o mocks.

Ejecutar Código

Para ejecutar el código simplemente hay que hacer go run . y listo, el archivo JSON debe tener el nombre servers.json o se le tiene que pasar un nombre por parámetros en la consola go run . file.json.

Tambien dentro del proyecto y código existe un archivo makefile que tiene algunos targets para compilar a distintas plataformas y sistemas, estos targets generan un ejecutable de nombre fakeapi.exe.

Por ejemplo, para compilar para Apple silicon el comando es: make build.darwinM.

Para ejecutarlo simplemente hay que hacer en la consola: ./fakeapi.exe file.json

El código lo pueden encontrar en github, tengo uno similar en NodeJS pero al no ser un binario ejecutable no servía para estos propósitos. Ademas de ser mas enrreado considero que lo programe peor 😀