FIX: Changed Content Type From Static mp4 To Input
Build, Push and Deploy CMS / build-push-deploy (push) Successful in 2m18s
Build, Push and Deploy CMS / build-push-deploy (push) Successful in 2m18s
This commit is contained in:
+7
-3
@@ -95,7 +95,7 @@ const docTemplate = `{
|
||||
},
|
||||
"/api/videos/presign": {
|
||||
"post": {
|
||||
"description": "Step 1 of the upload flow. Returns a short-lived presigned S3 URL that the client PUTs the video file to directly, plus the storage key identifying it. Once the PUT succeeds, pass that same key to POST /api/videos to register the video and start transcoding. The file itself never passes through this API.",
|
||||
"description": "Step 1 of the upload flow. Returns a short-lived presigned S3 URL that the client PUTs the video file to directly, plus the storage key identifying it. The submitted contentType is signed into that URL, so the PUT must carry an identical Content-Type header or S3 rejects it as a signature mismatch. Once the PUT succeeds, pass the key to POST /api/videos to register the video and start transcoding. The file itself never passes through this API.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
@@ -108,7 +108,7 @@ const docTemplate = `{
|
||||
"summary": "Create a presigned upload URL",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Name and media type of the file to be uploaded. contentType must be a video/* type.",
|
||||
"description": "Name and media type of the file to be uploaded. contentType must be exactly 'video/mp4' or 'video/quicktime'.",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
@@ -131,7 +131,7 @@ const docTemplate = `{
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "contentType was not a video/* media type",
|
||||
"description": "contentType was not 'video/mp4' or 'video/quicktime'",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/handlers.problemDetails"
|
||||
}
|
||||
@@ -231,6 +231,10 @@ const docTemplate = `{
|
||||
"properties": {
|
||||
"contentType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"video/mp4",
|
||||
"video/quicktime"
|
||||
],
|
||||
"example": "video/quicktime"
|
||||
},
|
||||
"fileName": {
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
},
|
||||
"/api/videos/presign": {
|
||||
"post": {
|
||||
"description": "Step 1 of the upload flow. Returns a short-lived presigned S3 URL that the client PUTs the video file to directly, plus the storage key identifying it. Once the PUT succeeds, pass that same key to POST /api/videos to register the video and start transcoding. The file itself never passes through this API.",
|
||||
"description": "Step 1 of the upload flow. Returns a short-lived presigned S3 URL that the client PUTs the video file to directly, plus the storage key identifying it. The submitted contentType is signed into that URL, so the PUT must carry an identical Content-Type header or S3 rejects it as a signature mismatch. Once the PUT succeeds, pass the key to POST /api/videos to register the video and start transcoding. The file itself never passes through this API.",
|
||||
"consumes": [
|
||||
"application/json"
|
||||
],
|
||||
@@ -101,7 +101,7 @@
|
||||
"summary": "Create a presigned upload URL",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Name and media type of the file to be uploaded. contentType must be a video/* type.",
|
||||
"description": "Name and media type of the file to be uploaded. contentType must be exactly 'video/mp4' or 'video/quicktime'.",
|
||||
"name": "request",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
@@ -124,7 +124,7 @@
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "contentType was not a video/* media type",
|
||||
"description": "contentType was not 'video/mp4' or 'video/quicktime'",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/handlers.problemDetails"
|
||||
}
|
||||
@@ -224,6 +224,10 @@
|
||||
"properties": {
|
||||
"contentType": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"video/mp4",
|
||||
"video/quicktime"
|
||||
],
|
||||
"example": "video/quicktime"
|
||||
},
|
||||
"fileName": {
|
||||
|
||||
@@ -44,6 +44,9 @@ definitions:
|
||||
handlers.presignRequest:
|
||||
properties:
|
||||
contentType:
|
||||
enum:
|
||||
- video/mp4
|
||||
- video/quicktime
|
||||
example: video/quicktime
|
||||
type: string
|
||||
fileName:
|
||||
@@ -190,12 +193,13 @@ paths:
|
||||
- application/json
|
||||
description: Step 1 of the upload flow. Returns a short-lived presigned S3 URL
|
||||
that the client PUTs the video file to directly, plus the storage key identifying
|
||||
it. Once the PUT succeeds, pass that same key to POST /api/videos to register
|
||||
the video and start transcoding. The file itself never passes through this
|
||||
API.
|
||||
it. The submitted contentType is signed into that URL, so the PUT must carry
|
||||
an identical Content-Type header or S3 rejects it as a signature mismatch.
|
||||
Once the PUT succeeds, pass the key to POST /api/videos to register the video
|
||||
and start transcoding. The file itself never passes through this API.
|
||||
parameters:
|
||||
- description: Name and media type of the file to be uploaded. contentType must
|
||||
be a video/* type.
|
||||
be exactly 'video/mp4' or 'video/quicktime'.
|
||||
in: body
|
||||
name: request
|
||||
required: true
|
||||
@@ -213,7 +217,7 @@ paths:
|
||||
schema:
|
||||
$ref: '#/definitions/handlers.problemDetails'
|
||||
"422":
|
||||
description: contentType was not a video/* media type
|
||||
description: contentType was not 'video/mp4' or 'video/quicktime'
|
||||
schema:
|
||||
$ref: '#/definitions/handlers.problemDetails'
|
||||
"500":
|
||||
|
||||
@@ -47,9 +47,19 @@ func ListCategories(w http.ResponseWriter, r *http.Request) {
|
||||
writeJSON(w, http.StatusOK, categoriesResponse{Categories: categories})
|
||||
}
|
||||
|
||||
// allowedUploadContentTypes is the set of media types accepted for upload,
|
||||
// keyed by the exact string a client must send. Matched verbatim rather than
|
||||
// normalised: the value is signed into the presigned URL, so rewriting it
|
||||
// here would leave the client PUTting a header that no longer matches the
|
||||
// signature.
|
||||
var allowedUploadContentTypes = map[string]struct{}{
|
||||
"video/mp4": {}, // .mp4
|
||||
"video/quicktime": {}, // .mov
|
||||
}
|
||||
|
||||
type presignRequest struct {
|
||||
FileName string `json:"fileName" example:"interview-cut.mov"`
|
||||
ContentType string `json:"contentType" example:"video/quicktime"`
|
||||
ContentType string `json:"contentType" enums:"video/mp4,video/quicktime" example:"video/quicktime"`
|
||||
}
|
||||
|
||||
type presignResponse struct {
|
||||
@@ -60,14 +70,14 @@ type presignResponse struct {
|
||||
// PresignVideoUpload issues a presigned S3 PUT URL for a video upload.
|
||||
//
|
||||
// @Summary Create a presigned upload URL
|
||||
// @Description Step 1 of the upload flow. Returns a short-lived presigned S3 URL that the client PUTs the video file to directly, plus the storage key identifying it. Once the PUT succeeds, pass that same key to POST /api/videos to register the video and start transcoding. The file itself never passes through this API.
|
||||
// @Description Step 1 of the upload flow. Returns a short-lived presigned S3 URL that the client PUTs the video file to directly, plus the storage key identifying it. The submitted contentType is signed into that URL, so the PUT must carry an identical Content-Type header or S3 rejects it as a signature mismatch. Once the PUT succeeds, pass the key to POST /api/videos to register the video and start transcoding. The file itself never passes through this API.
|
||||
// @Tags videos
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body presignRequest true "Name and media type of the file to be uploaded. contentType must be a video/* type."
|
||||
// @Param request body presignRequest true "Name and media type of the file to be uploaded. contentType must be exactly 'video/mp4' or 'video/quicktime'."
|
||||
// @Success 200 {object} presignResponse
|
||||
// @Failure 400 {object} problemDetails "Request body was not valid JSON"
|
||||
// @Failure 422 {object} problemDetails "contentType was not a video/* media type"
|
||||
// @Failure 422 {object} problemDetails "contentType was not 'video/mp4' or 'video/quicktime'"
|
||||
// @Failure 500 {object} problemDetails "Upload URL could not be issued"
|
||||
// @Router /api/videos/presign [post]
|
||||
func PresignVideoUpload(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -80,9 +90,9 @@ func PresignVideoUpload(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(req.ContentType, "video/") {
|
||||
writeProblem(w, http.StatusUnprocessableEntity, "Unsupported file type. Please upload a video.",
|
||||
fmt.Sprintf("The 'contentType' field was %q, but only video/* media types can be uploaded. Set it to the file's own MIME type, for example 'video/mp4'.", req.ContentType))
|
||||
if _, ok := allowedUploadContentTypes[req.ContentType]; !ok {
|
||||
writeProblem(w, http.StatusUnprocessableEntity, "Unsupported file type. Please upload an MP4 or MOV video.",
|
||||
fmt.Sprintf("The 'contentType' field was %q, but only 'video/mp4' (.mp4) and 'video/quicktime' (.mov) are accepted. Send one of those two values exactly — it is signed into the upload URL, so the PUT must use the identical header.", req.ContentType))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -94,7 +104,7 @@ func PresignVideoUpload(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
key := videoUploadPrefix + "/" + filename
|
||||
|
||||
presignedURL, err := services.S3Client.GetPresignedURL(r.Context(), key, "video/mp4", time.Hour)
|
||||
presignedURL, err := services.S3Client.GetPresignedURL(r.Context(), key, req.ContentType, time.Hour)
|
||||
if err != nil {
|
||||
writeProblem(w, http.StatusInternalServerError, "Could not prepare upload.",
|
||||
"A presigned upload URL could not be issued for the storage bucket. This is a server-side fault; no upload slot was reserved, so retry the request.")
|
||||
|
||||
Reference in New Issue
Block a user