Skip to content

Commit

Permalink
add fake data support & bump (#40)
Browse files Browse the repository at this point in the history
  • Loading branch information
Clivern committed Nov 11, 2020
1 parent 3a9139c commit 173b148
Show file tree
Hide file tree
Showing 8 changed files with 259 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM golang:1.15.4

ARG RHINO_VERSION=1.3.0
ARG RHINO_VERSION=1.4.0

ENV GO111MODULE=on

Expand Down
53 changes: 50 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<p align="center">
<img alt="Rhino Logo" src="https://raw.githubusercontent.com/clivern/Rhino/master/assets/img/gopher.png?v=1.3.0" width="150" />
<img alt="Rhino Logo" src="https://raw.githubusercontent.com/clivern/Rhino/master/assets/img/gopher.png?v=1.4.0" width="150" />
<h3 align="center">Rhino</h3>
<p align="center">HTTP Mocking & Debugging Service</p>
<p align="center">
<a href="https://travis-ci.com/Clivern/Rhino"><img src="https://travis-ci.com/Clivern/Rhino.svg?branch=master"></a>
<a href="https://github.com/Clivern/Rhino/releases"><img src="https://img.shields.io/badge/Version-1.3.0-red.svg"></a>
<a href="https://goreportcard.com/report/github.com/Clivern/Rhino"><img src="https://goreportcard.com/badge/github.com/clivern/Rhino?v=1.3.0"></a>
<a href="https://github.com/Clivern/Rhino/releases"><img src="https://img.shields.io/badge/Version-1.4.0-red.svg"></a>
<a href="https://goreportcard.com/report/github.com/Clivern/Rhino"><img src="https://goreportcard.com/badge/github.com/clivern/Rhino?v=1.4.0"></a>
<a href="https://hub.docker.com/r/clivern/rhino"><img src="https://img.shields.io/badge/Docker-Latest-green"></a>
<a href="https://github.com/Clivern/Rhino/blob/master/LICENSE"><img src="https://img.shields.io/badge/LICENSE-MIT-orange.svg"></a>
</p>
Expand Down Expand Up @@ -113,6 +113,53 @@ Test it.
$ curl http://127.0.0.1:8080/_health
```

You can use fake data flags inside response body and rhino will auto generate them. Here is the full list of supported types:

```bash
Latitude: @fake(:lat)
Longitude: @fake(:long)
CreditCardNumber: @fake(:cc_number)
CreditCardType: @fake(:cc_type)
Email: @fake(:email)
DomainName: @fake(:domain_name)
IPV4: @fake(:ipv4)
IPV6: @fake(:ipv6)
Password: @fake(:password)
PhoneNumber: @fake(:phone_number)
MacAddress: @fake(:mac_address)
URL: @fake(:url)
UserName: @fake(:username)
TollFreeNumber: @fake(:toll_free_number)
E164PhoneNumber: @fake(:e_164_phone_number)
TitleMale: @fake(:title_male)
TitleFemale: @fake(:title_female)
FirstName: @fake(:first_name)
FirstNameMale: @fake(:first_name_male)
FirstNameFemale: @fake(:first_name_female)
LastName: @fake(:last_name)
Name: @fake(:name)
UnixTime: @fake(:unix_time)
Date: @fake(:date)
Time: @fake(:time)
MonthName: @fake(:month_name)
Year: @fake(:year)
DayOfWeek: @fake(:day_of_week)
DayOfMonth: @fake(:day_of_month)
Timestamp: @fake(:timestamp)
Century: @fake(:century)
TimeZone: @fake(:timezone)
TimePeriod: @fake(:time_period)
Word: @fake(:word)
Sentence: @fake(:sentence)
Paragraph: @fake(:paragraph)
Currency: @fake(:currency)
Amount: @fake(:amount)
AmountWithCurrency: @fake(:amount_with_currency)
UUIDHypenated: @fake(:uuid_hyphenated)
UUID: @fake(:uuid_digit)
```


### Docker

Clone and then run docker containers.
Expand Down
18 changes: 18 additions & 0 deletions config.dist.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,24 @@
"latency": "0s",
"failRate": "0%"
}
},
{
"path": "/_fake_data",
"request": {
"method": "get",
"parameters": {}
},
"response": {
"statusCode": 200,
"headers": [
{"key": "Content-Type", "value": "application/json"}
],
"body": "{\"Latitude\":\"@fake(:lat)\",\"Longitude\":\"@fake(:long)\",\"CreditCardNumber\":\"@fake(:cc_number)\",\"CreditCardType\":\"@fake(:cc_type)\",\"Email\":\"@fake(:email)\",\"DomainName\":\"@fake(:domain_name)\",\"IPV4\":\"@fake(:ipv4)\",\"IPV6\":\"@fake(:ipv6)\",\"Password\":\"@fake(:password)\",\"PhoneNumber\":\"@fake(:phone_number)\",\"MacAddress\":\"@fake(:mac_address)\",\"URL\":\"@fake(:url)\",\"UserName\":\"@fake(:username)\",\"TollFreeNumber\":\"@fake(:toll_free_number)\",\"E164PhoneNumber\":\"@fake(:e_164_phone_number)\",\"TitleMale\":\"@fake(:title_male)\",\"TitleFemale\":\"@fake(:title_female)\",\"FirstName\":\"@fake(:first_name)\",\"FirstNameMale\":\"@fake(:first_name_male)\",\"FirstNameFemale\":\"@fake(:first_name_female)\",\"LastName\":\"@fake(:last_name)\",\"Name\":\"@fake(:name)\",\"UnixTime\":\"@fake(:unix_time)\",\"Date\":\"@fake(:date)\",\"Time\":\"@fake(:time)\",\"MonthName\":\"@fake(:month_name)\",\"Year\":\"@fake(:year)\",\"DayOfWeek\":\"@fake(:day_of_week)\",\"DayOfMonth\":\"@fake(:day_of_month)\",\"Timestamp\":\"@fake(:timestamp)\",\"Century\":\"@fake(:century)\",\"TimeZone\":\"@fake(:timezone)\",\"TimePeriod\":\"@fake(:time_period)\",\"Word\":\"@fake(:word)\",\"Sentence\":\"@fake(:sentence)\",\"Paragraph\":\"@fake(:paragraph)\",\"Currency\":\"@fake(:currency)\",\"Amount\":\"@fake(:amount)\",\"AmountWithCurrency\":\"@fake(:amount_with_currency)\",\"UUIDHypenated\":\"@fake(:uuid_hyphenated)\",\"UUID\":\"@fake(:uuid_digit)\"}"
},
"chaos": {
"latency": "0s",
"failRate": "0%"
}
}
],
"debug": [
Expand Down
9 changes: 9 additions & 0 deletions core/controller/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"time"

"github.com/clivern/rhino/core/model"
"github.com/clivern/rhino/core/module"

"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -102,5 +103,13 @@ func Mock(c *gin.Context) {
route.Response.Body = strings.Replace(route.Response.Body, value, parameters[key], -1)
}

faker := &module.Faker{}
var err error
route.Response.Body, err = faker.Transform(route.Response.Body)

if err != nil {
panic(err)
}

c.String(route.Response.StatusCode, route.Response.Body)
}
174 changes: 174 additions & 0 deletions core/module/faker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
// Copyright 2020 Clivern. All rights reserved.
// Use of this source code is governed by the MIT
// license that can be found in the LICENSE file.

package module

import (
"fmt"
"regexp"
"strings"

"github.com/bxcodec/faker/v3"
)

// Faker type
type Faker struct {
Latitude float32 `faker:"lat"`
Longitude float32 `faker:"long"`
CreditCardNumber string `faker:"cc_number"`
CreditCardType string `faker:"cc_type"`
Email string `faker:"email"`
DomainName string `faker:"domain_name"`
IPV4 string `faker:"ipv4"`
IPV6 string `faker:"ipv6"`
Password string `faker:"password"`
PhoneNumber string `faker:"phone_number"`
MacAddress string `faker:"mac_address"`
URL string `faker:"url"`
UserName string `faker:"username"`
TollFreeNumber string `faker:"toll_free_number"`
E164PhoneNumber string `faker:"e_164_phone_number"`
TitleMale string `faker:"title_male"`
TitleFemale string `faker:"title_female"`
FirstName string `faker:"first_name"`
FirstNameMale string `faker:"first_name_male"`
FirstNameFemale string `faker:"first_name_female"`
LastName string `faker:"last_name"`
Name string `faker:"name"`
UnixTime int64 `faker:"unix_time"`
Date string `faker:"date"`
Time string `faker:"time"`
MonthName string `faker:"month_name"`
Year string `faker:"year"`
DayOfWeek string `faker:"day_of_week"`
DayOfMonth string `faker:"day_of_month"`
Timestamp string `faker:"timestamp"`
Century string `faker:"century"`
TimeZone string `faker:"timezone"`
TimePeriod string `faker:"time_period"`
Word string `faker:"word"`
Sentence string `faker:"sentence"`
Paragraph string `faker:"paragraph"`
Currency string `faker:"currency"`
Amount float64 `faker:"amount"`
AmountWithCurrency string `faker:"amount_with_currency"`
UUIDHypenated string `faker:"uuid_hyphenated"`
UUID string `faker:"uuid_digit"`
}

// Transform populate faked data
func (f *Faker) Transform(data string) (string, error) {
types := f.GetTypesFound(data)

err := faker.FakeData(f)

if err != nil {
return data, err
}

for i := 0; i < len(types); i++ {

if types[i] == "@fake(:lat)" {
data = strings.Replace(data, types[i], fmt.Sprintf("%f", f.Latitude), -1)
} else if types[i] == "@fake(:long)" {
data = strings.Replace(data, types[i], fmt.Sprintf("%f", f.Longitude), -1)
} else if types[i] == "@fake(:cc_number)" {
data = strings.Replace(data, types[i], f.CreditCardNumber, -1)
} else if types[i] == "@fake(:cc_type)" {
data = strings.Replace(data, types[i], f.CreditCardType, -1)
} else if types[i] == "@fake(:email)" {
data = strings.Replace(data, types[i], f.Email, -1)
} else if types[i] == "@fake(:domain_name)" {
data = strings.Replace(data, types[i], f.DomainName, -1)
} else if types[i] == "@fake(:ipv4)" {
data = strings.Replace(data, types[i], f.IPV4, -1)
} else if types[i] == "@fake(:ipv6)" {
data = strings.Replace(data, types[i], f.IPV6, -1)
} else if types[i] == "@fake(:password)" {
data = strings.Replace(data, types[i], f.Password, -1)
} else if types[i] == "@fake(:phone_number)" {
data = strings.Replace(data, types[i], f.PhoneNumber, -1)
} else if types[i] == "@fake(:mac_address)" {
data = strings.Replace(data, types[i], f.MacAddress, -1)
} else if types[i] == "@fake(:url)" {
data = strings.Replace(data, types[i], f.URL, -1)
} else if types[i] == "@fake(:username)" {
data = strings.Replace(data, types[i], f.UserName, -1)
} else if types[i] == "@fake(:toll_free_number)" {
data = strings.Replace(data, types[i], f.TollFreeNumber, -1)
} else if types[i] == "@fake(:e_164_phone_number)" {
data = strings.Replace(data, types[i], f.E164PhoneNumber, -1)
} else if types[i] == "@fake(:title_male)" {
data = strings.Replace(data, types[i], f.TitleMale, -1)
} else if types[i] == "@fake(:title_female)" {
data = strings.Replace(data, types[i], f.TitleFemale, -1)
} else if types[i] == "@fake(:first_name)" {
data = strings.Replace(data, types[i], f.FirstName, -1)
} else if types[i] == "@fake(:first_name_male)" {
data = strings.Replace(data, types[i], f.FirstNameMale, -1)
} else if types[i] == "@fake(:first_name_female)" {
data = strings.Replace(data, types[i], f.FirstNameFemale, -1)
} else if types[i] == "@fake(:last_name)" {
data = strings.Replace(data, types[i], f.LastName, -1)
} else if types[i] == "@fake(:name)" {
data = strings.Replace(data, types[i], f.Name, -1)
} else if types[i] == "@fake(:unix_time)" {
data = strings.Replace(data, types[i], fmt.Sprintf("%d", f.UnixTime), -1)
} else if types[i] == "@fake(:date)" {
data = strings.Replace(data, types[i], f.Date, -1)
} else if types[i] == "@fake(:time)" {
data = strings.Replace(data, types[i], f.Time, -1)
} else if types[i] == "@fake(:month_name)" {
data = strings.Replace(data, types[i], f.MonthName, -1)
} else if types[i] == "@fake(:year)" {
data = strings.Replace(data, types[i], f.Year, -1)
} else if types[i] == "@fake(:day_of_week)" {
data = strings.Replace(data, types[i], f.DayOfWeek, -1)
} else if types[i] == "@fake(:day_of_month)" {
data = strings.Replace(data, types[i], f.DayOfMonth, -1)
} else if types[i] == "@fake(:timestamp)" {
data = strings.Replace(data, types[i], f.Timestamp, -1)
} else if types[i] == "@fake(:century)" {
data = strings.Replace(data, types[i], f.Century, -1)
} else if types[i] == "@fake(:timezone)" {
data = strings.Replace(data, types[i], f.TimeZone, -1)
} else if types[i] == "@fake(:time_period)" {
data = strings.Replace(data, types[i], f.TimePeriod, -1)
} else if types[i] == "@fake(:word)" {
data = strings.Replace(data, types[i], f.Word, -1)
} else if types[i] == "@fake(:sentence)" {
data = strings.Replace(data, types[i], f.Sentence, -1)
} else if types[i] == "@fake(:paragraph)" {
data = strings.Replace(data, types[i], f.Paragraph, -1)
} else if types[i] == "@fake(:currency)" {
data = strings.Replace(data, types[i], f.Currency, -1)
} else if types[i] == "@fake(:amount)" {
data = strings.Replace(data, types[i], fmt.Sprintf("%f", f.Amount), -1)
} else if types[i] == "@fake(:amount_with_currency)" {
data = strings.Replace(data, types[i], f.AmountWithCurrency, -1)
} else if types[i] == "@fake(:uuid_hyphenated)" {
data = strings.Replace(data, types[i], f.UUIDHypenated, -1)
} else if types[i] == "@fake(:uuid_digit)" {
data = strings.Replace(data, types[i], f.UUID, -1)
}
}

return data, nil
}

// GetTypesFound grep all fake data tags
func (f *Faker) GetTypesFound(data string) []string {
result := []string{}
r := regexp.MustCompile(`@fake\((.)+?\)`)
matches := r.FindAllStringIndex(data, -1)

for n := 0; n < len(matches); n++ {
result = append(
result,
data[matches[n][0]:matches[n][1]],
)
}

return result
}
2 changes: 1 addition & 1 deletion deployment/docker-compose/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
version: '3'
services:
rhino:
image: 'clivern/rhino:release-1.3.0'
image: 'clivern/rhino:release-1.4.0'
ports:
- "8080:8080"
command: '/app/rhino serve -c /app/configs/config.prod.json'
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/clivern/rhino
go 1.15

require (
github.com/bxcodec/faker/v3 v3.5.0
github.com/drone/envsubst v1.0.2
github.com/gin-gonic/gin v1.6.3
github.com/prometheus/client_golang v1.8.0
Expand Down
Loading

0 comments on commit 173b148

Please sign in to comment.