Я создал сервер обслуживания модели с библиотекой Python Tornado
, и его единственная цель — принять http-запрос с полезной нагрузкой и вернуть результат в json. Запрос можно сделать с помощью application/json
или multipart/form-data
.
Для аутентификации и авторизации пользователей я сделал еще один сервер с библиотекой Golang echo
. Таким образом, все запросы пользователей должны поступать сюда до того, как они достигнут моего сервера ресурсов.
Здесь у меня проблема, потому что моя программа требует изображений в качестве входных данных, поэтому пользователи отправят свой запрос с FormData
. Когда он впервые попал на мой сервер Golang, мне нужно выполнить следующие шаги.
- Прочитайте файл формы.
- Сохраните его на локальном диске.
- Загрузите файл и сохраните его в байтовом буфере.
- Инициализировать составной модуль записи
- Сделать запрос на мой сервер ресурсов
- Получил результат, вернуть пользователю
Я чувствую, что это избыточно, поскольку я полагаю, что есть способ передать этот запрос непосредственно на мой сервер ресурсов (после выполнения аутентификации), без необходимости проходить через части ввода-вывода.
Мой код в настоящее время выглядит так, на данный момент аутентификация выполняется через промежуточное программное обеспечение. Есть ли способ оптимизировать этот поток?
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)
}
io.Copy(part, file)
. Удалите весь код, связанный с переменнымиf
иfilepath
. - person Cerise Limón   schedule 11.01.2020