Можем ли мы сохранить животных с помощью Golang?

от автора

Статья, главным образом, состоит из двух частей: описания проблемы и описания ее решения. Если сама проблема вас не интересует, первый раздел можно пропустить без ущерба для себя либо животных. Или вообще можно всю статью пропустить.

Идентифицируем проблему

В начале вас ждет небольшое, но важное вступление. Оно поможет увидеть как я докопался до сути проблемы и затем, перешел к ее решению.

Я разработчик и я предпочитаю проводить время со своим компьютером. Но все же иногда мне нужно выходить из дома, вы знаете, делать все те вещи, что делают другие люди. И вот однажды, возвращаясь домой со своей сумкой продуктов я увидел некоторую картину: группа людей с плакатами на которых написано “Save animals”. Как я уже говорил, я разработчик и прекрасно понимаю английский. Они, очевидно, хотели сохранить животных. И раз столько людей собрались вместе — это очень серьезная проблема, подумал я.

У меня нет фото с стого протеста, но есть одно фото с протеста против использования javascript на бэкэнде.

У меня нет фото с стого протеста, но есть одно фото с протеста против использования javascript на бэкэнде.

Эти люди не знали кто только что прошел мимо них. Я разработчик — один из тех людей которые делают мир лучше. И я намерен решить их проблему.

Не могу удержаться от проэктирования своего кода на стену. Но вот IDE хочу поменять, может что-то от JetBrains попробую.

Не могу удержаться от проэктирования своего кода на стену. Но вот IDE хочу поменять, может что-то от JetBrains попробую.

Хотя было кое-что, что воспрепятствовало мне тут же приступить к самому решению. Этим фактором было непонимание данной проблемы. Я ведь с детства интересовался компьютерами, а животные меня не слишком привлекали. Но это не беда, ведь у нас есть ChatGPT. Всего-то нужно задать ему правильный вопрос. И вот полученный ответ, понятный мне как инженеру:

Если подойти к этому вопросу чисто с технической стороны, я бы предположил что термин “животные” может относиться к набору данных или категорий в компьютерной системе. В этом контексте, “сохранить животных” может означать сохранение и защиту информации или данных внутри приложения или базы данных.

ChatGPT

Правда ChatGPT замечательная вещь? Немного помучал его вопросами, и он выдал нужный мне ответ. Теперь все стало понятно: этим людям нужно решение, которое позволит им сохранять изображения котов, собак или других животных. 

Ну что же, проблема идентифицирована и мы наконец-то можем приступить к ее решению.

Реализуем решение

Давайте определимся с требованиями к нашему приложению. Наш сервис сохранения животных будет доступен по HTTP. Он будет принимать POST запрос с одним или несколькими файлами изображений животных. Также мы будем использовать путь нашего URL для целей категоризации изображений животных. 

В итоге, моя инфраструктура будет выглядеть наподобие той что на диаграмме ниже.

Синие коробки, стрелочки и облачные бумажные шредеры.

Синие коробки, стрелочки и облачные бумажные шредеры.

Первое чем было решено заняться — это процессинг файлов. Естественно, я имею вполне нормальное желание сделать все быстро. Всю работу связанную с файлам я скину на небольшой сервис под названием Capyfile, код которого можно найти на GitHub. Ему нужно вскормить небольшой конфигурационный файл, которых скажет что я хочу делать с загружаемыми файлам. Мой конфиг выглядит так:

{   "version": "1.0",   "name": "upload",   "processors": [     {       "name": "animal",       "operations": [         {           "name": "file_size_validate",           "params": {             "maxFileSize": {               "sourceType": "http_header",               "source": "X-Capyfile-FileSizeValidate-MaxFileSize"             }           }         },         {           "name": "file_type_validate",           "params": {             "allowedMimeTypes": {               "sourceType": "http_header",               "source": "X-Capyfile-FileTypeValidate-AllowedMimeTypes"             }           }         },         {           "name": "metadata_cleanup"         },         {           "name": "image_convert",           "params": {             "toMimeType": {               "sourceType": "value",               "source": "image/jpeg"             },             "quality": {               "sourceType": "value",               "source": "high"             }           }         },         {           "name": "s3_upload",           "params": {             "accessKeyId": {               "sourceType": "secret",               "source": "aws_access_key_id"             },             "secretAccessKey": {               "sourceType": "secret",               "source": "aws_secret_access_key"             },             "endpoint": {               "sourceType": "env_var",               "source": "AWS_ENDPOINT"             },             "region": {               "sourceType": "env_var",               "source": "AWS_REGION"             },             "bucket": {               "sourceType": "http_header",               "source": "X-Capyfile-S3Upload-Bucket"             }           }         }       ]     }   ] }

Из него ясно, что я хочу сделать с каждым загруженным файлом:

  • Проверить размер файла

  • Проверить MIME-тип файла

  • Очистить метаданные файла

  • Конвертировать файл в JPEG формат

  • Сохранить файл в совместимое с S3 хранилище

Некоторые из необходимых параметров будут пробрасываться из приложения которое я напишу далее. Другие же параметры будут получены из окружения Docker контейнера.

Теперь финальная часть — написание приложения, которое будет содержит некую бизнес-логику удовлетворяющую моим требованиям. По большей части, оно будет проксировать запросы, попутно обогащая их нужными параметрами. Эти параметры будут говорить Capyfile как проверять файлы и где эти файлы сохранять.

package main  import (     "net/http"     "net/http/httputil"     "net/url"     "strconv"     "strings" )  const (     Byte = 1 << (iota * 10)     KiByte     MiByte     GiByte     TiByte     PiByte     EiByte )  func main() {     http.HandleFunc("/", capyfileProxyHandler)      http.ListenAndServe(":8080", nil) }  func capyfileProxyHandler(w http.ResponseWriter, r *http.Request) {     if r.Method != http.MethodPost {         w.WriteHeader(http.StatusMethodNotAllowed)         return     }      path := strings.Split(         strings.TrimLeft(r.URL.Path, "/"),         "/")      if len(path) != 1 {         w.WriteHeader(http.StatusNotFound)         return     }      animal := path[0]      if animal == "seagull" {         w.WriteHeader(http.StatusForbidden)         return     }      if animal == "capybara" {         r.Header.Set(             "X-Capyfile-FileSizeValidate-MaxFileSize",             strconv.Itoa(100*MiByte))         r.Header.Set(             "X-Capyfile-FileTypeValidate-AllowedMimeTypes",             `["image/jpeg", "image/png", "image/gif", "image/bmp", "image/webp", "image/heic", "image/heif"]`)     } else {         r.Header.Set(             "X-Capyfile-FileSizeValidate-MaxFileSize",             strconv.Itoa(1*MiByte))         r.Header.Set(             "X-Capyfile-FileTypeValidate-AllowedMimeTypes",             `["image/jpeg", "image/png"]`)     }     // We assume that all the necessary buckets are already created      // or can be created on the fly.     r.Header.Set("X-Capyfile-S3Upload-Bucket", animal)      r.URL.Path = "/upload/animal"      proxy := httputil.NewSingleHostReverseProxy(&url.URL{         Scheme: "http",         Host:   "localhost:8024",     })     proxy.ServeHTTP(w, r) }

Запускаем и тестируем

Первым делом, мы запустим Capyfile сервер:

docker run --rm \     --name capyfile_server \     --mount type=bind,source=./service-definition.json,target=/etc/capyfile/service-definition.json \     --env CAPYFILE_SERVICE_DEFINITION_FILE=/etc/capyfile/service-definition.json \     --env AWS_ENDPOINT=s3.amazonaws.com \     --env AWS_REGION=us-west-1 \     --secret aws_access_key_id \     --secret aws_secret_access_key \     -p 8024:8024 \     capyfile/capysvr:latest

Затем запускаем наше приложение:

go run animal_saver.go

Теперь все готово для сохранения животных в S3 хранилище.

Сохранил одну капибару.

Сохранил одну капибару.

Заключение

Здесь вы могли увидеть как легко я решил проблему сохранения животных. 

Также вы не могли не заметить, что Capyfile существенно ускорил разработку данного решения. Поэтому хочу побудить вас оказать этому проекту свою поддержку. С благодарностью принимаются дельные мысли, идеи, пул-реквесты.


ссылка на оригинал статьи https://habr.com/ru/articles/753966/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *