Read decodes JSON from the HTTP request into the value provided. It uses go-validator to validate the incoming request body. ctx is used for tracing and can be nil. Although tracing this function isn't likely too helpful, it was done to be consistent with Write.
(ctx context.Context, rw http.ResponseWriter, r *http.Request, value interface{})
| 234 | // and can be nil. Although tracing this function isn't likely too helpful, it |
| 235 | // was done to be consistent with Write. |
| 236 | func Read(ctx context.Context, rw http.ResponseWriter, r *http.Request, value interface{}) bool { |
| 237 | ctx, span := tracing.StartSpan(ctx) |
| 238 | defer span.End() |
| 239 | |
| 240 | err := json.NewDecoder(r.Body).Decode(value) |
| 241 | if err != nil { |
| 242 | Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 243 | Message: "Request body must be valid JSON.", |
| 244 | Detail: err.Error(), |
| 245 | }) |
| 246 | return false |
| 247 | } |
| 248 | err = Validate.Struct(value) |
| 249 | var validationErrors validator.ValidationErrors |
| 250 | if errors.As(err, &validationErrors) { |
| 251 | apiErrors := make([]codersdk.ValidationError, 0, len(validationErrors)) |
| 252 | for _, validationError := range validationErrors { |
| 253 | apiErrors = append(apiErrors, codersdk.ValidationError{ |
| 254 | Field: validationError.Field(), |
| 255 | Detail: fmt.Sprintf("Validation failed for tag %q with value: \"%v\"", validationError.Tag(), validationError.Value()), |
| 256 | }) |
| 257 | } |
| 258 | Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ |
| 259 | Message: "Validation failed.", |
| 260 | Validations: apiErrors, |
| 261 | }) |
| 262 | return false |
| 263 | } |
| 264 | if err != nil { |
| 265 | Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ |
| 266 | Message: "Internal error validating request body payload.", |
| 267 | Detail: err.Error(), |
| 268 | }) |
| 269 | return false |
| 270 | } |
| 271 | return true |
| 272 | } |
| 273 | |
| 274 | const websocketCloseMaxLen = 123 |
| 275 |