Skip to content

Commit

Permalink
Merge pull request #95 from heyyakash/main
Browse files Browse the repository at this point in the history
Added MySQL-Golang sample application and documentation
  • Loading branch information
Sonichigo authored Jan 25, 2024
2 parents 6fec9fc + 8771851 commit a3ca0db
Show file tree
Hide file tree
Showing 12 changed files with 460 additions and 0 deletions.
15 changes: 15 additions & 0 deletions mux-mysql/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM golang:1.21.4-alpine AS build
RUN mkdir /app
COPY . /app
WORKDIR /app

ENV ConnectionString="root:my-secret-pw@tcp(mysql:3306)/mysql"

RUN go build -o main .
RUN chmod +x /app/main

#### Stage 2
FROM scratch
COPY --from=build /app/main /main
ENV ConnectionString="root:my-secret-pw@tcp(mysql:3306)/mysql"
ENTRYPOINT [ "/main" ]
64 changes: 64 additions & 0 deletions mux-mysql/controller/controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package controller

import (
"database/sql"
"encoding/json"
"log"
"net/http"
"strconv"

"github.com/gorilla/mux"
"github.com/heyyakash/keploy-go-samples/db"
"github.com/heyyakash/keploy-go-samples/helpers"
"github.com/heyyakash/keploy-go-samples/models"
)

func CreateLink(store *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req models.Request
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
log.Print("Error decoding json", err)
helpers.SendResponse(w, http.StatusBadRequest, "Error decoding JSON", "", false)
return
}
if valid := helpers.CheckValidURL(req.Link); valid == false {
helpers.SendResponse(w, http.StatusBadRequest, "Enter Valid url (starting with 'http:// or https://')", "", false)
return
}
id, err := db.EnterWebsiteToDB(req.Link, store)
if err != nil {
log.Print("Error ", err)
helpers.SendResponse(w, http.StatusInternalServerError, err.Error(), "", false)
return
}
link := "http://localhost:8080" + "/link/" + strconv.FormatInt(id, 10)
helpers.SendResponse(w, http.StatusOK, "Converted", link, true)
}
}

func RedirectUser(store *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
id := vars["id"]
log.Printf("%v", id)
link, err := db.GetWebsiteFromId(id, store)
if err != nil {
log.Print("Error ", err)
helpers.SendResponse(w, http.StatusNotFound, "Website not found", "", false)
return
}
http.Redirect(w, r, link, http.StatusTemporaryRedirect)
}
}

func GetAllLinksFromWebsite(store *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
array, err := db.GetAllLinks(store)
if err != nil {
log.Print("Error ", err)
helpers.SendResponse(w, http.StatusNotFound, "Some Error Retrieving the data"+err.Error(), "", false)
return
}
helpers.SendGetResponse(w, array, http.StatusOK, true)
}
}
60 changes: 60 additions & 0 deletions mux-mysql/db/database.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package db

import (
"database/sql"
"fmt"
"log"

_ "github.com/go-sql-driver/mysql"
"github.com/heyyakash/keploy-go-samples/models"
)

func EnterWebsiteToDB(link string, db *sql.DB) (int64, error) {
query := `insert into list (website) values("` + link + `")`
resp, err := db.Exec(query)
if err != nil {
return 0, err
}
lastInsertID, err := resp.LastInsertId()
if err != nil {
return 0, err
}

log.Printf("\n inserted %+v ", resp)
return lastInsertID, err
}

func GetWebsiteFromId(id string, db *sql.DB) (string, error) {
query := `select website from list where id=` + id
var link string
row := db.QueryRow(query)
err := row.Scan(&link)
if err != nil {
if err == sql.ErrNoRows {
return "", fmt.Errorf("Website not found")
}
return "", err
}

return link, nil
}

func GetAllLinks(db *sql.DB) ([]models.Table, error) {
query := `select * from list`
var array []models.Table
rows, err := db.Query(query)
if err != nil {
return nil, err
}
defer rows.Close()

for rows.Next() {
var link models.Table
if err := rows.Scan(&link.Id, &link.Website); err != nil {
return nil, err
}
array = append(array, link)

}
return array, nil
}
8 changes: 8 additions & 0 deletions mux-mysql/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module github.com/heyyakash/keploy-go-samples

go 1.21.3

require (
github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/gorilla/mux v1.8.1 // indirect
)
4 changes: 4 additions & 0 deletions mux-mysql/go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
20 changes: 20 additions & 0 deletions mux-mysql/helpers/checkValidUrl.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package helpers

import (
"log"
"regexp"
"strings"
)

func CheckValidURL(link string) bool {
r, err := regexp.Compile("^(http|https)://")
if err != nil {
log.Print(err)
return false
}
link = strings.TrimSpace(link)
if r.MatchString(link) {
return true
}
return false
}
14 changes: 14 additions & 0 deletions mux-mysql/helpers/getConnectionString.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package helpers

import (
"log"
"os"
)

func GetDBConnectionString() string {
value := os.Getenv("ConnectionString")
if value == "" {
log.Fatal("Connection string empty")
}
return value
}
23 changes: 23 additions & 0 deletions mux-mysql/helpers/response.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package helpers

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

"github.com/heyyakash/keploy-go-samples/models"
)

func SendResponse(w http.ResponseWriter, code int, message string, link string, status bool) {
w.WriteHeader(code)
if err := json.NewEncoder(w).Encode(&models.Response{Message: message, Link: link, Status: status}); err != nil {
log.Fatalf("Error writing JSON: %v", err)
}
}

func SendGetResponse(w http.ResponseWriter, data interface{}, status int, success bool) {
w.WriteHeader(status)
if err := json.NewEncoder(w).Encode(&models.GETResponse{Message: data, Status: success}); err != nil {
log.Fatalf("Error writing JSON: %v", err)
}
}
1 change: 1 addition & 0 deletions mux-mysql/helpers/urlshortener.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package helpers
53 changes: 53 additions & 0 deletions mux-mysql/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package main

import (
"database/sql"
"log"
"net/http"
"os"
"time"

"github.com/gorilla/mux"
"github.com/heyyakash/keploy-go-samples/controller"
"github.com/heyyakash/keploy-go-samples/helpers"
)

var Port = ":8080"

func main() {
store, err := CreateStore()
if err != nil {
log.Fatal("Couldnt create store ", err)
}

defer store.Close()
router := mux.NewRouter()
router.HandleFunc("/create", controller.CreateLink(store)).Methods("POST")
router.HandleFunc("/all", controller.GetAllLinksFromWebsite(store)).Methods("GET")
router.HandleFunc("/links/{id}", controller.RedirectUser(store)).Methods("GET")
log.Print("Server is running")
log.Fatal(http.ListenAndServe(Port, router))
}

func CreateStore() (*sql.DB, error) {
log.Print(os.Getenv("DOCKER_ENV"))
connStr := helpers.GetDBConnectionString()
store, err := sql.Open("mysql", connStr)
if err != nil {
return nil, err
}
if err := store.Ping(); err != nil {
return nil, err
}
query := `create table if not exists list(
id int auto_increment primary key,
website varchar(400)
)`
_, err = store.Exec(query)
if err != nil {
return nil, err
}
store.SetConnMaxLifetime(time.Hour)
log.Print("*** DB Initiated at ***")
return store, nil
}
20 changes: 20 additions & 0 deletions mux-mysql/models/request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package models

type Request struct {
Link string `json:"link"`
}

type Response struct {
Message string `json:"message"`
Link string `json:"link"`
Status bool `json:"status"`
}
type GETResponse struct {
Message interface{} `json:"message"`
Status bool `json:"status"`
}

type Table struct {
Id string `json:"id"`
Website string `json:"website"`
}
Loading

0 comments on commit a3ca0db

Please sign in to comment.