feat: upload audio, get a private Swedish transcript, discuss it (#33, ADR-033) #39
+10
-4
@@ -95,7 +95,7 @@ func (a *App) handleUploadPost(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
var tooBig *http.MaxBytesError
|
var tooBig *http.MaxBytesError
|
||||||
if a.abandoned(r) {
|
if a.abandoned(w, r) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !errors.As(err, &tooBig) {
|
if !errors.As(err, &tooBig) {
|
||||||
@@ -113,6 +113,9 @@ func (a *App) handleUploadPost(w http.ResponseWriter, r *http.Request) {
|
|||||||
case "title":
|
case "title":
|
||||||
b, err := io.ReadAll(io.LimitReader(part, maxTitleRunes*utf8.UTFMax))
|
b, err := io.ReadAll(io.LimitReader(part, maxTitleRunes*utf8.UTFMax))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if a.abandoned(w, r) {
|
||||||
|
return
|
||||||
|
}
|
||||||
a.renderUploadsPage(w, r, userID, http.StatusBadRequest, "That upload could not be read. Please try again.")
|
a.renderUploadsPage(w, r, userID, http.StatusBadRequest, "That upload could not be read. Please try again.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -133,14 +136,17 @@ func (a *App) handleUploadPost(w http.ResponseWriter, r *http.Request) {
|
|||||||
a.renderUploadsPage(w, r, userID, http.StatusBadRequest, "Choose an audio file to upload.")
|
a.renderUploadsPage(w, r, userID, http.StatusBadRequest, "Choose an audio file to upload.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// abandoned reports, and logs at INFO, that the client has already gone: its request
|
// abandoned reports, logs at INFO and answers 499, because the client has already gone: its request
|
||||||
// context is cancelled, so there is nobody to answer and rendering a page would run its
|
// context is cancelled, so there is nobody to answer and rendering a page would run its
|
||||||
// database read on a dead context and log a false ERROR. A hang-up mid-upload is routine.
|
// database read on a dead context and log a false ERROR. A hang-up mid-upload is routine.
|
||||||
func (a *App) abandoned(r *http.Request) bool {
|
func (a *App) abandoned(w http.ResponseWriter, r *http.Request) bool {
|
||||||
if r.Context().Err() == nil {
|
if r.Context().Err() == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
a.logger().Info("upload abandoned", "reason", "client_gone")
|
a.logger().Info("upload abandoned", "reason", "client_gone")
|
||||||
|
// 499 (the "client closed request" convention): a client that half-closed after sending
|
||||||
|
// can still read, and an unwritten status would reach it as a false, empty 200.
|
||||||
|
w.WriteHeader(499)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,7 +154,7 @@ func (a *App) abandoned(r *http.Request) bool {
|
|||||||
// rejection is the user's to fix (422, or 413 for size) and carries its own
|
// rejection is the user's to fix (422, or 413 for size) and carries its own
|
||||||
// message; anything else is ours.
|
// message; anything else is ours.
|
||||||
func (a *App) uploadFailure(w http.ResponseWriter, r *http.Request, userID string, err error) {
|
func (a *App) uploadFailure(w http.ResponseWriter, r *http.Request, userID string, err error) {
|
||||||
if a.abandoned(r) {
|
if a.abandoned(w, r) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var rej *uploads.RejectError
|
var rej *uploads.RejectError
|
||||||
|
|||||||
Reference in New Issue
Block a user