-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
228 additions
and
97 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,32 @@ | ||
# cmd/shortener | ||
# go-musthave-shortener-tpl | ||
|
||
В данной директории будет содержаться код, который скомпилируется в бинарное приложение | ||
Шаблон репозитория для трека «Сервис сокращения URL». | ||
|
||
## Начало работы | ||
|
||
1. Склонируйте репозиторий в любую подходящую директорию на вашем компьютере. | ||
2. В корне репозитория выполните команду `go mod init <name>` (где `<name>` — адрес вашего репозитория на GitHub без префикса `https://`) для создания модуля. | ||
|
||
## Обновление шаблона | ||
|
||
Чтобы иметь возможность получать обновления автотестов и других частей шаблона, выполните команду: | ||
|
||
``` | ||
git remote add -m main template https://github.com/Yandex-Practicum/go-musthave-shortener-tpl.git | ||
``` | ||
|
||
Для обновления кода автотестов выполните команду: | ||
|
||
``` | ||
git fetch template && git checkout template/main .github | ||
``` | ||
|
||
Затем добавьте полученные изменения в свой репозиторий. | ||
|
||
## Запуск автотестов | ||
|
||
Для успешного запуска автотестов называйте ветки `iter<number>`, где `<number>` — порядковый номер инкремента. Например, в ветке с названием `iter4` запустятся автотесты для инкрементов с первого по четвёртый. | ||
|
||
При мёрже ветки с инкрементом в основную ветку `main` будут запускаться все автотесты. | ||
|
||
Подробнее про локальный и автоматический запуск читайте в [README автотестов](https://github.com/Yandex-Practicum/go-autotests). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package main | ||
|
||
import ( | ||
"bufio" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
"net/url" | ||
"os" | ||
"strings" | ||
) | ||
|
||
func main() { | ||
endpoint := "http://localhost:8080/" | ||
// контейнер данных для запроса | ||
data := url.Values{} | ||
// приглашение в консоли | ||
fmt.Println("Введите длинный URL") | ||
// открываем потоковое чтение из консоли | ||
reader := bufio.NewReader(os.Stdin) | ||
// читаем строку из консоли | ||
long, err := reader.ReadString('\n') | ||
if err != nil { | ||
panic(err) | ||
} | ||
long = strings.TrimSuffix(long, "\n") | ||
// заполняем контейнер данными | ||
data.Set("url", long) | ||
// добавляем HTTP-клиент | ||
client := &http.Client{} | ||
// пишем запрос | ||
// запрос методом POST должен, помимо заголовков, содержать тело | ||
// тело должно быть источником потокового чтения io.Reader | ||
request, err := http.NewRequest(http.MethodPost, endpoint, strings.NewReader(data.Encode())) | ||
if err != nil { | ||
panic(err) | ||
} | ||
// в заголовках запроса указываем кодировку | ||
request.Header.Add("Content-Type", "application/x-www-form-urlencoded") | ||
// отправляем запрос и получаем ответ | ||
response, err := client.Do(request) | ||
if err != nil { | ||
panic(err) | ||
} | ||
// выводим код ответа | ||
fmt.Println("Статус-код ", response.Status) | ||
defer response.Body.Close() | ||
// читаем поток из тела ответа | ||
body, err := io.ReadAll(response.Body) | ||
if err != nil { | ||
panic(err) | ||
} | ||
// и печатаем его | ||
fmt.Println(string(body)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package config | ||
|
||
import ( | ||
flag "github.com/spf13/pflag" | ||
) | ||
|
||
// Config структура для хранения настроек | ||
type Config struct { | ||
RunAddr string | ||
ResultURL string | ||
} | ||
|
||
// parseFlags обрабатывает аргументы командной строки | ||
// и сохраняет их значения в соответствующих переменных | ||
func ParseFlags(cfg *Config) { | ||
//fs := flag.NewFlagSet("myflags", flag.ExitOnError) | ||
flag.StringVarP(&cfg.RunAddr, "a", "a", "localhost:8080", "Адрес запуска HTTP-сервера.") | ||
flag.StringVarP(&cfg.ResultURL, "b", "b", "http://localhost:8080", "Адрес результирующего сокращённого URL.") | ||
// парсим переданные серверу аргументы в зарегистрированные переменные | ||
flag.Parse() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,94 @@ | ||
package main | ||
|
||
func main() {} | ||
import ( | ||
"encoding/base64" | ||
"fmt" | ||
"github.com/gorilla/mux" | ||
"github.com/nabbat/url-shortener-server.git/cmd/config" | ||
"io" | ||
"log" | ||
"net/http" | ||
) | ||
|
||
// Словарь для хранения соответствий между сокращёнными и оригинальными URL | ||
// TODO Создать хранилище | ||
var urlMap = map[string]string{} | ||
|
||
// Перенаправляем по полной ссылке | ||
func redirectHandler(w http.ResponseWriter, r *http.Request) { | ||
if r.Method != http.MethodGet { | ||
http.Error(w, "invalid request type", http.StatusBadRequest) | ||
return | ||
} | ||
// Добавляем тестовое соответствие в словарь | ||
urlMap["aHR0cH"] = "https://practicum.yandex.ru/" | ||
// Получаем идентификатор из URL-пути | ||
id := r.URL.Path[1:] | ||
|
||
// Получаем оригинальный URL из словаря | ||
|
||
if originalURL, found := urlMap[id]; found { | ||
// Устанавливаем заголовок Location и возвращаем ответ с кодом 307 | ||
w.Header().Set("Location", originalURL) | ||
w.WriteHeader(http.StatusTemporaryRedirect) | ||
return | ||
} | ||
http.Error(w, "Ссылка не найдена", http.StatusBadRequest) | ||
|
||
} | ||
|
||
func shortenURLHandler(w http.ResponseWriter, r *http.Request, cfg *config.Config) { | ||
// Читаем тело запроса (URL) | ||
urlBytes, err := io.ReadAll(r.Body) | ||
if err != nil { | ||
http.Error(w, "Ошибка чтения запроса", http.StatusBadRequest) | ||
return | ||
} | ||
|
||
// Преобразуем в строку | ||
url := string(urlBytes) | ||
|
||
// Генерируем уникальный идентификатор сокращённого URL | ||
id := generateID(url) | ||
|
||
// Добавляем соответствие в словарь | ||
urlMap[id] = url | ||
|
||
// Отправляем ответ с сокращённым URL | ||
shortenedURL := fmt.Sprintf("%s/%s", cfg.ResultURL, id) | ||
w.Header().Set("Content-Type", "text/plain") | ||
w.WriteHeader(http.StatusCreated) | ||
if _, err := io.WriteString(w, shortenedURL); err != nil { | ||
log.Fatal(err) | ||
} | ||
} | ||
|
||
// Простая функция для генерации уникального идентификатора | ||
func generateID(fullURL string) string { | ||
encodedStr := base64.URLEncoding.EncodeToString([]byte(fullURL)) | ||
// Возвращаем первые 6 символов закодированной строки | ||
if len(encodedStr) > 6 { | ||
return encodedStr[:6] | ||
} | ||
return encodedStr | ||
} | ||
|
||
func main() { | ||
// Create a Config instance | ||
cfg := &config.Config{} | ||
|
||
// Parse command line flags and populate the Config instance | ||
config.ParseFlags(cfg) | ||
|
||
// Run server | ||
r := mux.NewRouter() | ||
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { | ||
shortenURLHandler(w, r, cfg) | ||
}).Methods("POST") | ||
r.HandleFunc("/{idShortenURL}", redirectHandler).Methods("GET") | ||
fmt.Println("Running server on", cfg.RunAddr) | ||
err := http.ListenAndServe(cfg.RunAddr, r) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
module github.com/nabbat/url-shortener-server.git | ||
|
||
go 1.20 | ||
|
||
require ( | ||
github.com/gorilla/mux v1.8.0 | ||
github.com/spf13/pflag v1.0.5 | ||
github.com/stretchr/testify v1.8.4 | ||
) | ||
|
||
require ( | ||
github.com/davecgh/go-spew v1.1.1 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= | ||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= | ||
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/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= | ||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= | ||
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= |