Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iter3 #6

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 95 additions & 1 deletion cmd/shortener/main.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,97 @@
package main

func main() {}
import (
"encoding/base64"
"errors"
"fmt"
"net/http"
"io"
"github.com/go-chi/chi/v5"
"log"
)

var urls map[string]string // хранилище ссылок

func main() {

urls = make(map[string]string)

r := chi.NewRouter()
r.Post("/", handlerPost)
r.Get("/{link}", handlerGet)


fmt.Println("Server is starter")
log.Fatal(http.ListenAndServe(":8080", r))

}


// Обрабатывает POST-запрос. Возвращает заголовок со статусом 201, если результат Ок
func handlerPost(rw http.ResponseWriter, rq *http.Request) {
fmt.Println("Отрабатывает метод", rq.Method)
// Проверяем, есть ли в теле запроса данные (ссылка)
body, _ := io.ReadAll(rq.Body)

if string(body) != "" {
// Сокращаем принятую ссылку
res, err := encodeURL(string(body))

// Если ошибки нет, возвращаем результат сокращения в заголовке
// а также сохраняем короткую ссылку в хранилище

if err == nil {
urls[res] = string(body)
rw.Header().Set("Content-Type", "text/plain")
rw.WriteHeader(201)
rw.Write([]byte("http://localhost:8080/" + res))
} else {
panic("Something wrong in encoding")
}

} else {
rw.WriteHeader(400)
rw.Write([]byte("No URL in request"))
}
}

func handlerGet(rw http.ResponseWriter, rq *http.Request) {
fmt.Println("Отрабатывает метод", rq.Method)
// Получаем короткий URL из запроса
shortURL := rq.URL.String()[1:]
fmt.Println(urls)

// Если URL уже имеется в хранилище, возвращем в браузер ответ и делаем редирект
if value, ok := urls[shortURL]; ok {
rw.Header().Set("Location", value)
rw.WriteHeader(307)
} else {
rw.Header().Set("Location", "URL not found")
rw.WriteHeader(400)
}

}

// Функция кодирования URL в сокращенный вид
func encodeURL(url string) (string, error) {
if url != "" {
var shortURL string
// кодируем URL по алгоритму base64 и сокращаем строку до 6 символов
fmt.Println("Закодированная ссылка =", base64.StdEncoding.EncodeToString([]byte(url)))
start := len(base64.StdEncoding.EncodeToString([]byte(url)))
shortURL = base64.StdEncoding.EncodeToString([]byte(url))[start-6:]
fmt.Println("Короткая ссылка =", shortURL)
return shortURL, nil
} else {
return "", errors.New("URL is empty")
}
}

// Функция декодирования URL в адрес полной длины
func decodeURL(shortURL string) (string, error) {
// Ищем shortUrl в хранилище как ключ, если есть, позвращаем значение из мапы по данному ключу
if value, ok := urls[shortURL]; ok {
return value, nil
}
return "", errors.New("short URL not foud")
}
107 changes: 107 additions & 0 deletions cmd/shortener/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package main

import (
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"testing"
"strings"
"fmt"
)

func TestHandlerPost(t *testing.T){
urls = make(map[string]string)

type want struct {
code int
}
tests := []struct {
name string
param string
want want
}{
{
name: "post test 1. body doesn't consist of data",
param: "",
want: want{
code: 400,
},
},
{
name: "post test 2. body consist of data",
param: "http://ya.ru",
want: want{
code: 201,
},

},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
fmt.Printf("\n\nTest %v Body %v\n", test.name, test.param)
param := strings.NewReader(test.param)
request := httptest.NewRequest(http.MethodPost, "/", param)
w := httptest.NewRecorder()
handlerPost(w, request)

res := w.Result()
defer res.Body.Close()
fmt.Printf("want code = %d StatusCode %d\n", test.want.code, res.StatusCode)
assert.Equal(t, test.want.code, res.StatusCode)
})
}

}

func TestHandlerGet(t *testing.T){
type want struct {
code int
}
tests := []struct {
name string
body string
want want
}{
{
name: "get test 1. body doesn't consist of data",
body: "",
want: want{
code: 400,
},
},
{
name: "get test 2. body consist of data",
body: "http://ya.ru",
want: want{
code: 307,
},

},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
var addr string
if test.body == "/"{
addr =""
} else {
for k, v := range urls {
if v == test.body {
addr = k
}
}
}
fmt.Printf("\n\nTest %v Body %v Addr %v\n", test.name, test.body, addr)
request := httptest.NewRequest(http.MethodGet, "/"+addr, nil)
w := httptest.NewRecorder()
handlerGet(w, request)

res := w.Result()
defer res.Body.Close()
fmt.Printf("want code = %d StatusCode %d\n", test.want.code, res.StatusCode)
assert.Equal(t, test.want.code, res.StatusCode)
})
}

}
15 changes: 15 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module github.com/evgenygavriluk/go-musthave-shortener-tpl

go 1.21.3

require (
github.com/go-chi/chi v1.5.5
github.com/stretchr/testify v1.8.4
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/go-chi/chi/v5 v5.0.10 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
14 changes: 14 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-chi/chi v1.5.5 h1:vOB/HbEMt9QqBqErz07QehcOKHaWFtuj87tTDVz2qXE=
github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw=
github.com/go-chi/chi/v5 v5.0.10 h1:rLz5avzKpjqxrYwXNfmjkrYYXOyLJd37pz53UFHC6vk=
github.com/go-chi/chi/v5 v5.0.10/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=