Я создал модель обслуживающего сервера с библиотекой Python Tornado
, и его единственная цель - принять http-запрос с полезной нагрузкой и вернуть результат в json. Запрос можно сделать с помощью application/json
или multipart/form-data
.
. Для аутентификации и авторизации пользователей я создал другой сервер с библиотекой Golang echo
. Таким образом, все пользовательские запросы должны поступать сюда до того, как они достигнут моего сервера ресурсов.
Здесь у меня проблема, потому что моей программе требуются изображения в качестве входных данных, поэтому пользователи отправят свой запрос с помощью FormData
. Когда он впервые попадает на мой Golang сервер, мне нужно выполнить следующие шаги
- Прочитать файл формы.
- Сохранить его на локальном диске.
- Загрузить файл и сохраните его в байтовом буфере.
- Инициализируйте составной модуль записи
- Сделайте запрос к моему серверу ресурсов
- Получите результат, вернитесь к пользователю
Мне кажется, что это излишне, так как я представляю, что есть способ распространить эти запросы непосредственно на мой сервер ресурсов (после выполнения аутентификации), без необходимости go через части ввода / вывода.
Мой код в настоящее время выглядит следующим образом, на данный момент аутентификация выполняется через промежуточное ПО. Есть ли способ оптимизировать этот поток?
func (h Handler) ProcessFormData(c echo.Context) error {
// some validation
file, err := c.FormFile("file")
if err != nil {
return c.JSON(http.StatusBadRequest, response.Exception{
Code: errcode.InvalidRequest,
Detail: "Invalid file uploaded",
Error: err,
})
}
filePath, err := fileUtil.SaveNetworkFile(file)
if err != nil {
return c.JSON(http.StatusInternalServerError, response.Exception{
Code: errcode.SystemError,
Detail: "Error when processing file",
Error: err,
})
}
f, err := os.Open(filePath)
if err != nil {
return c.JSON(http.StatusInternalServerError, response.Exception{
Code: errcode.SystemError,
Detail: "Error when processing file",
Error: err,
})
}
defer f.Close()
fi, err := f.Stat()
if err != nil {
return c.JSON(http.StatusInternalServerError, response.Exception{
Code: errcode.SystemError,
Detail: "Error when processing file",
Error: err,
})
}
var body bytes.Buffer
writer := multipart.NewWriter(&body)
part, err := writer.CreateFormFile("file", fi.Name())
if err != nil {
return c.JSON(http.StatusInternalServerError, response.Exception{
Code: errcode.SystemError,
Detail: "Error when processing file",
Error: err,
})
}
if _, err := io.Copy(part, f); err != nil {
return c.JSON(http.StatusInternalServerError, response.Exception{
Code: errcode.SystemError,
Detail: "Error when processing file",
Error: err,
})
}
writer.Close()
req, err := http.NewRequest("POST", fmt.Sprintf("%s", env.ResourceServer), &body)
req.Header.Set("Content-Type", writer.FormDataContentType())
if err != nil {
return c.JSON(http.StatusInternalServerError, response.Exception{
Code: errcode.APIRequestError,
Error: err,
})
}
client := &http.Client{}
res, err := client.Do(req)
if err != nil {
return c.JSON(http.StatusInternalServerError, response.Exception{
Code: errcode.APIRequestError,
Detail: "Error when posting request to resource server",
Error: err,
})
}
defer res.Body.Close()
data, _ := ioutil.ReadAll(res.Body)
if res.StatusCode != 200 {
errorData := &model.PanicResponse{}
err := json.Unmarshal(data, errorData)
if err != nil {
return c.JSON(http.StatusInternalServerError, response.Exception{
Code: errcode.UnmarshalError,
Error: err,
})
}
return c.JSON(res.StatusCode, errorData)
}
result := &model.SuccessResponse{}
err = json.Unmarshal(data, result)
if err != nil {
return c.JSON(http.StatusInternalServerError, response.Exception{
Code: errcode.UnmarshalError,
Error: err,
})
}
if fileUtil.IsFileExists(filePath) {
fileUtil.DeleteFile(filePath)
}
// track and update usage
userData := c.Get("USER")
user := userData.(model.User)
db.UpdateUsage(h.Db, &user.ID)
return c.JSON(200, result)
}