newContext returns a [Context] by parsing a "multipart/form-data" request.
(echoCtx echo.Context, logger *slog.Logger, fs *gotenberg.FileSystem, timeout time.Duration, bodyLimit int64, downloadFromCfg downloadFromConfig)
| 99 | |
| 100 | // newContext returns a [Context] by parsing a "multipart/form-data" request. |
| 101 | func newContext(echoCtx echo.Context, logger *slog.Logger, fs *gotenberg.FileSystem, timeout time.Duration, bodyLimit int64, downloadFromCfg downloadFromConfig) (*Context, context.CancelFunc, error) { |
| 102 | processCtx, processCancel := context.WithTimeout(echoCtx.Request().Context(), timeout) |
| 103 | |
| 104 | // We want to make sure the multipart/form-data does not exceed a given |
| 105 | // limit. We consider: form fields (keys, values, files) and files |
| 106 | // downloaded remotely ("download from" feature). |
| 107 | var totalBytesRead atomic.Int64 |
| 108 | |
| 109 | addReadBytes := func(n int64) error { |
| 110 | newTotal := totalBytesRead.Add(n) |
| 111 | if bodyLimit != 0 && newTotal > bodyLimit { |
| 112 | return WrapError( |
| 113 | fmt.Errorf("body limit reached (> %d)", bodyLimit), |
| 114 | NewSentinelHttpError(http.StatusRequestEntityTooLarge, "The request body exceeds the configured size limit. Increase it with --api-body-limit, or send a smaller request."), |
| 115 | ) |
| 116 | } |
| 117 | return nil |
| 118 | } |
| 119 | |
| 120 | ctx := &Context{ |
| 121 | outputPaths: make([]string, 0), |
| 122 | cancelled: false, |
| 123 | logger: logger, |
| 124 | echoCtx: echoCtx, |
| 125 | mkdirAll: new(gotenberg.OsMkdirAll), |
| 126 | pathRename: new(gotenberg.OsPathRename), |
| 127 | Context: processCtx, |
| 128 | } |
| 129 | |
| 130 | // A custom cancel function which removes the context's working directory |
| 131 | // when called. |
| 132 | cancel := func() context.CancelFunc { |
| 133 | return func() { |
| 134 | if ctx.cancelled { |
| 135 | return |
| 136 | } |
| 137 | |
| 138 | processCancel() |
| 139 | |
| 140 | if ctx.dirPath == "" { |
| 141 | return |
| 142 | } |
| 143 | |
| 144 | err := os.RemoveAll(ctx.dirPath) |
| 145 | if err != nil { |
| 146 | ctx.logger.ErrorContext(context.Background(), fmt.Sprintf("remove context's working directory: %s", err)) |
| 147 | |
| 148 | return |
| 149 | } |
| 150 | |
| 151 | ctx.logger.DebugContext(context.Background(), fmt.Sprintf("'%s' context's working directory removed", ctx.dirPath)) |
| 152 | ctx.cancelled = true |
| 153 | } |
| 154 | }() |
| 155 | |
| 156 | form, err := echoCtx.MultipartForm() |
| 157 | if err != nil { |
| 158 | if errors.Is(err, http.ErrNotMultipart) { |