-
Notifications
You must be signed in to change notification settings - Fork 0
First iteration #1
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
base: main
Are you sure you want to change the base?
Changes from all commits
7842fdf
62910ae
1e6f0eb
225bced
95f397a
e0010ee
f9f7a2c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,18 @@ | ||
| package main | ||
|
|
||
| import ( | ||
| "log" | ||
| "os" | ||
|
|
||
| "github.com/Yandex-Practicum/go1fl-sprint6-final/internal/server" | ||
| ) | ||
|
|
||
| func main() { | ||
| logger := log.New(os.Stdout, "SERVER:", log.LstdFlags) | ||
| srv := server.New(logger) | ||
|
|
||
| logger.Println("Запуск сервера...") | ||
| if err := srv.Start(); err != nil { | ||
| logger.Fatalf("ошибка запуска сервера: %v", err) | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,112 @@ | ||
| // Пакет handlers | ||
| package handlers | ||
|
|
||
| import ( | ||
| "io" | ||
| "log" | ||
| "net/http" | ||
| "os" | ||
| "path/filepath" | ||
| "strings" | ||
| "time" | ||
|
|
||
| "github.com/Yandex-Practicum/go1fl-sprint6-final/internal/service" | ||
| ) | ||
|
|
||
| func ReturnHTML(w http.ResponseWriter, r *http.Request) { | ||
| // Получаем текущую рабочую директорию | ||
| wd, err := os.Getwd() | ||
| if err != nil { | ||
| log.Printf("Ошибка получения рабочей директории: %v", err) | ||
| http.Error(w, "Internal Server Error", http.StatusInternalServerError) | ||
| return | ||
| } | ||
|
|
||
| // Формируем абсолютный путь к index.html | ||
| indexPath := filepath.Join(wd, "index.html") | ||
| data, err := os.ReadFile(indexPath) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. можно проще http.ServeFile |
||
| if err != nil { | ||
| log.Printf("Ошибка чтения %s: %v", indexPath, err) | ||
| http.Error(w, "Internal Server Error", http.StatusInternalServerError) | ||
| return | ||
| } | ||
|
|
||
| w.Header().Set("Content-Type", "text/html; charset=utf-8") | ||
| w.Write(data) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ошибка не обработана |
||
| } | ||
|
|
||
| func ConvertStr(w http.ResponseWriter, r *http.Request) { | ||
| const maxMemory = 32 << 20 // 32MB | ||
|
|
||
| if r.Method != http.MethodPost { | ||
| http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed) | ||
| return | ||
| } | ||
|
|
||
| // Парсинг формы с увеличенным лимитом памяти | ||
| if err := r.ParseMultipartForm(maxMemory); err != nil { | ||
| log.Printf("Ошибка парсинга формы: %v", err) | ||
| http.Error(w, "Bad Request", http.StatusBadRequest) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. по заданию статус при ошибках http.StatusInternalServerError |
||
| return | ||
| } | ||
|
|
||
| file, header, err := r.FormFile("myFile") | ||
| if err != nil { | ||
| log.Printf("Файл не найден: %v", err) | ||
| http.Error(w, "Bad Request", http.StatusBadRequest) | ||
| return | ||
| } | ||
| defer file.Close() | ||
|
|
||
| // Чтение содержимого файла | ||
| data, err := io.ReadAll(file) | ||
| if err != nil { | ||
| log.Printf("Ошибка чтения файла: %v", err) | ||
| http.Error(w, "Internal Server Error", http.StatusInternalServerError) | ||
| return | ||
| } | ||
|
|
||
| content := strings.TrimSpace(string(data)) | ||
| if content == "" { | ||
| http.Error(w, "Empty File", http.StatusBadRequest) | ||
| return | ||
| } | ||
|
|
||
| // Конвертация | ||
| converted, err := service.AutoConvert(content) | ||
| if err != nil { | ||
| log.Printf("Ошибка конвертации: %v", err) | ||
| http.Error(w, "Conversion Error", http.StatusInternalServerError) | ||
| return | ||
| } | ||
|
|
||
| // Создание результата | ||
| timestamp := strings.ReplaceAll( | ||
| time.Now().UTC().Format("2006-01-02_15-04-05"), | ||
| ":", "-", | ||
| ) | ||
| ext := filepath.Ext(header.Filename) | ||
| if ext == "" { | ||
| ext = ".txt" | ||
| } | ||
| outputFilename := "result_" + timestamp + ext | ||
|
|
||
| outputFile, err := os.Create(outputFilename) | ||
| if err != nil { | ||
| log.Printf("Ошибка создания файла: %v", err) | ||
| http.Error(w, "Internal Server Error", http.StatusInternalServerError) | ||
| return | ||
| } | ||
| defer outputFile.Close() | ||
|
|
||
| if _, err := outputFile.WriteString(converted); err != nil { | ||
| log.Printf("Ошибка записи файла: %v", err) | ||
| http.Error(w, "Internal Server Error", http.StatusInternalServerError) | ||
| return | ||
| } | ||
|
|
||
| // Ответ клиенту | ||
| w.Header().Set("Content-Type", "text/plain; charset=utf-8") | ||
| w.WriteHeader(http.StatusOK) | ||
| w.Write([]byte(converted)) | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,40 @@ | ||
| package server | ||
|
|
||
| import ( | ||
| "log" | ||
| "net/http" | ||
| "time" | ||
|
|
||
| "github.com/Yandex-Practicum/go1fl-sprint6-final/internal/handlers" | ||
| ) | ||
|
|
||
| type Server struct { | ||
| logger *log.Logger // Логгер | ||
| httpServer *http.Server // HTTP-сервер | ||
| } | ||
|
|
||
| func New(logger *log.Logger) *Server { | ||
| router := http.NewServeMux() | ||
|
|
||
| router.HandleFunc("/", handlers.ReturnHTML) | ||
| router.HandleFunc("/upload", handlers.ConvertStr) | ||
|
|
||
| httpServer := &http.Server{ | ||
| Addr: ":8080", | ||
| Handler: router, | ||
| ErrorLog: logger, | ||
| ReadTimeout: 5 * time.Second, | ||
| WriteTimeout: 10 * time.Second, | ||
| IdleTimeout: 15 * time.Second, | ||
| } | ||
|
|
||
| return &Server{ | ||
| logger: logger, | ||
| httpServer: httpServer, | ||
| } | ||
| } | ||
|
|
||
| func (s *Server) Start() error { | ||
| s.logger.Printf("Сервер запущен на %s", s.httpServer.Addr) | ||
| return s.httpServer.ListenAndServe() | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,38 @@ | ||
| // Пакет service | ||
| package service | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "regexp" | ||
| "strings" | ||
|
|
||
| "github.com/Yandex-Practicum/go1fl-sprint6-final/pkg/morse" | ||
| ) | ||
|
|
||
| func AutoConvert(input string) (string, error) { | ||
| input = strings.TrimSpace(input) | ||
| if input == "" { | ||
| return "", fmt.Errorf("empty input") | ||
| } | ||
|
|
||
| // Проверка | ||
| if isMorse(input) { | ||
| text := morse.ToText(input) | ||
| if text == "" { | ||
| return "", fmt.Errorf("invalid morse code") | ||
| } | ||
| return text, nil | ||
| } | ||
|
|
||
| // Конвертация | ||
| morseCode := morse.ToMorse(strings.ToUpper(input)) | ||
| if morseCode == "" { | ||
| return "", fmt.Errorf("invalid text") | ||
| } | ||
|
|
||
| return morseCode, nil | ||
| } | ||
|
|
||
| func isMorse(s string) bool { | ||
| return regexp.MustCompile(`^[\s.\-/]+$`).MatchString(s) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. лучше использовать strings.ContainsFunc чем регулярки |
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
тут в лог стоило добавить порт на котором сервер запускается