mirror of
https://github.com/fleetdm/fleet
synced 2026-05-22 00:18:27 +00:00
final adjustments to return timeout errors for software (#19772)
for #19453  I don't know how to test this in the server without a significant refactor. # Checklist for submitter If some of the following don't apply, delete the relevant line. <!-- Note that API documentation changes are now addressed by the product design team. --> - [ ] Added/updated tests - [x] Manual QA for all new/changed functionality
This commit is contained in:
parent
7fb3d12477
commit
48ea95385e
5 changed files with 51 additions and 9 deletions
|
|
@ -74,6 +74,8 @@ import (
|
|||
|
||||
var allowedURLPrefixRegexp = regexp.MustCompile("^(?:/[a-zA-Z0-9_.~-]+)+$")
|
||||
|
||||
const softwareInstallerUploadTimeout = 2 * time.Minute
|
||||
|
||||
type initializer interface {
|
||||
// Initialize is used to populate a datastore with
|
||||
// preloaded data
|
||||
|
|
@ -1056,9 +1058,15 @@ the way that the Fleet server works.
|
|||
// the frontend times out waiting for the upload after 2 minutes, so
|
||||
// use that same timeout:
|
||||
// https://www.figma.com/design/oQl2oQUG0iRkUy0YOxc307/%2314921-Deploy-security-agents-to-macOS%2C-Windows%2C-and-Linux-hosts?node-id=773-18032&t=QjEU6tc73tddNSqn-0
|
||||
if err := rc.SetReadDeadline(time.Now().Add(2 * time.Minute)); err != nil {
|
||||
if err := rc.SetReadDeadline(time.Now().Add(softwareInstallerUploadTimeout)); err != nil {
|
||||
level.Error(logger).Log("msg", "http middleware failed to override endpoint read timeout", "err", err)
|
||||
}
|
||||
// the write timeout should be extended as well to give the server time to
|
||||
// write a response body with the right error, otherwise the connection is
|
||||
// terminated abruptly.
|
||||
if err := rc.SetWriteDeadline(time.Now().Add(softwareInstallerUploadTimeout + 30*time.Second)); err != nil {
|
||||
level.Error(logger).Log("msg", "http middleware failed to override endpoint write timeout", "err", err)
|
||||
}
|
||||
req.Body = http.MaxBytesReader(rw, req.Body, service.MaxSoftwareInstallerSize)
|
||||
}
|
||||
apiHandler.ServeHTTP(rw, req)
|
||||
|
|
|
|||
|
|
@ -1,21 +1,23 @@
|
|||
import React, { useContext, useEffect, useState } from "react";
|
||||
import { InjectedRouter } from "react-router";
|
||||
import { AxiosResponse } from "axios";
|
||||
|
||||
import PATHS from "router/paths";
|
||||
import team, { APP_CONTEXT_ALL_TEAMS_ID } from "interfaces/team";
|
||||
import { getErrorReason } from "interfaces/errors";
|
||||
import { APP_CONTEXT_ALL_TEAMS_ID } from "interfaces/team";
|
||||
import softwareAPI from "services/entities/software";
|
||||
import { NotificationContext } from "context/notification";
|
||||
import { QueryParams, buildQueryStringFromParams } from "utilities/url";
|
||||
import { IApiError } from "interfaces/errors";
|
||||
|
||||
import Modal from "components/Modal";
|
||||
import Button from "components/buttons/Button";
|
||||
|
||||
import AddSoftwareForm from "../AddSoftwareForm";
|
||||
import { IAddSoftwareFormData } from "../AddSoftwareForm/AddSoftwareForm";
|
||||
import { getErrorMessage } from "./helpers";
|
||||
|
||||
// 2 minutes
|
||||
const UPLOAD_TIMEOUT = 120000;
|
||||
// 2 minutes + 15 seconds to account for extra roundtrip time.
|
||||
const UPLOAD_TIMEOUT = (2 * 60 + 15) * 1000;
|
||||
const MAX_FILE_SIZE_MB = 500;
|
||||
const MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024;
|
||||
|
||||
|
|
@ -97,7 +99,7 @@ const AddSoftwareModal = ({
|
|||
|
||||
// TODO: confirm we are deleting the second sentence (not modifying it) for non-self-service installers
|
||||
try {
|
||||
await softwareAPI.addSoftwarePackage(formData, teamId);
|
||||
await softwareAPI.addSoftwarePackage(formData, teamId, UPLOAD_TIMEOUT);
|
||||
renderFlash(
|
||||
"success",
|
||||
<>
|
||||
|
|
@ -120,7 +122,7 @@ const AddSoftwareModal = ({
|
|||
`${PATHS.SOFTWARE_TITLES}?${buildQueryStringFromParams(newQueryParams)}`
|
||||
);
|
||||
} catch (e) {
|
||||
renderFlash("error", getErrorReason(e));
|
||||
renderFlash("error", getErrorMessage(e));
|
||||
onExit();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
import { getErrorReason } from "interfaces/errors";
|
||||
|
||||
const UPLOAD_ERROR_MESSAGES = {
|
||||
default: {
|
||||
message: "Couldn't add. Please try again.",
|
||||
},
|
||||
};
|
||||
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export const getErrorMessage = (err: unknown) => {
|
||||
if (typeof err === "string") return err;
|
||||
return getErrorReason(err) || UPLOAD_ERROR_MESSAGES.default.message;
|
||||
};
|
||||
|
|
@ -191,7 +191,11 @@ export default {
|
|||
return sendRequest("GET", path);
|
||||
},
|
||||
|
||||
addSoftwarePackage: (data: IAddSoftwareFormData, teamId?: number) => {
|
||||
addSoftwarePackage: (
|
||||
data: IAddSoftwareFormData,
|
||||
teamId?: number,
|
||||
timeout?: number
|
||||
) => {
|
||||
const { SOFTWARE_PACKAGE_ADD } = endpoints;
|
||||
|
||||
if (!data.software) {
|
||||
|
|
@ -208,7 +212,14 @@ export default {
|
|||
formData.append("post_install_script", data.postInstallScript);
|
||||
teamId && formData.append("team_id", teamId.toString());
|
||||
|
||||
return sendRequest("POST", SOFTWARE_PACKAGE_ADD, formData);
|
||||
return sendRequest(
|
||||
"POST",
|
||||
SOFTWARE_PACKAGE_ADD,
|
||||
formData,
|
||||
undefined,
|
||||
timeout,
|
||||
true
|
||||
);
|
||||
},
|
||||
|
||||
deleteSoftwarePackage: (softwareId: number, teamId: number) => {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
|
|
@ -47,6 +48,13 @@ func (uploadSoftwareInstallerRequest) DecodeRequest(ctx context.Context, r *http
|
|||
InternalErr: err,
|
||||
}
|
||||
}
|
||||
var nerr net.Error
|
||||
if errors.As(err, &nerr) && nerr.Timeout() {
|
||||
return nil, fleet.NewUserMessageError(
|
||||
ctxerr.New(ctx, "Couldn't upload. Please ensure your internet connection speed is sufficient and stable."),
|
||||
http.StatusRequestTimeout,
|
||||
)
|
||||
}
|
||||
return nil, &fleet.BadRequestError{
|
||||
Message: "failed to parse multipart form: " + err.Error(),
|
||||
InternalErr: err,
|
||||
|
|
|
|||
Loading…
Reference in a new issue