👔 Created download route for media HTTP delivery with test

This commit is contained in:
Maxim Lebedev 2023-09-29 20:45:10 +06:00
parent e822d7273f
commit de300a6413
Signed by: toby3d
GPG Key ID: 1F14E25B7C119FC5
2 changed files with 70 additions and 10 deletions

View File

@ -1,10 +1,12 @@
package http
import (
"bytes"
"encoding/json"
"io"
"mime"
"net/http"
"time"
"source.toby3d.me/toby3d/pub/internal/common"
"source.toby3d.me/toby3d/pub/internal/domain"
@ -31,21 +33,44 @@ func NewHandler(media media.UseCase, config domain.Config) *Handler {
}
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
switch r.Method {
default:
WriteError(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
case "", http.MethodGet:
h.handleDownload(w, r)
case http.MethodPost:
h.handleUpload(w, r)
}
}
func (h *Handler) handleDownload(w http.ResponseWriter, r *http.Request) {
if r.Method != "" && r.Method != http.MethodGet {
WriteError(w, "method MUST be "+http.MethodGet, http.StatusMethodNotAllowed)
return
}
out, err := h.media.Download(r.Context(), r.RequestURI)
if err != nil {
WriteError(w, "cannot download media: "+err.Error(), http.StatusInternalServerError)
return
}
http.ServeContent(w, r, out.LogicalName(), time.Time{}, bytes.NewReader(out.Content))
}
func (h *Handler) handleUpload(w http.ResponseWriter, r *http.Request) {
if r.Method != http.MethodPost {
WriteError(w, "method MUST be "+http.MethodPost, http.StatusBadRequest)
WriteError(w, "method MUST be "+http.MethodPost, http.StatusMethodNotAllowed)
return
}
mediaType, _, err := mime.ParseMediaType(r.Header.Get(common.HeaderContentType))
if err != nil {
WriteError(w, "Content-Type header MUST be "+common.MIMEMultipartForm, http.StatusBadRequest)
return
}
if mediaType != common.MIMEMultipartForm {
WriteError(w, "Content-Type header MUST be "+common.MIMEMultipartForm, http.StatusBadRequest)
if err != nil || mediaType != common.MIMEMultipartForm {
WriteError(w, common.HeaderContentType+" header MUST be "+common.MIMEMultipartForm,
http.StatusBadRequest)
return
}

View File

@ -2,6 +2,7 @@ package http_test
import (
"bytes"
"io"
"mime/multipart"
"net/http"
"net/http/httptest"
@ -13,7 +14,7 @@ import (
delivery "source.toby3d.me/toby3d/pub/internal/media/delivery/http"
)
func TestUpload(t *testing.T) {
func TestHandler_Upload(t *testing.T) {
t.Parallel()
testConfig := domain.TestConfig(t)
@ -54,3 +55,37 @@ func TestUpload(t *testing.T) {
t.Errorf("%s %s = %s, want not empty", req.Method, req.RequestURI, location)
}
}
func TestHandler_Download(t *testing.T) {
t.Parallel()
testConfig := domain.TestConfig(t)
testFile := domain.TestFile(t)
req := httptest.NewRequest(http.MethodGet, "https://example.com/media/"+testFile.LogicalName(), nil)
w := httptest.NewRecorder()
delivery.NewHandler(
media.NewStubUseCase(nil, testFile, nil), *testConfig).
ServeHTTP(w, req)
resp := w.Result()
if resp.StatusCode != http.StatusOK {
t.Errorf("%s %s = %d, want %d", req.Method, req.RequestURI, resp.StatusCode, http.StatusOK)
}
contentType, mediaType := resp.Header.Get(common.HeaderContentType), testFile.MediaType()
if contentType != mediaType {
t.Errorf("%s %s = '%s', want '%s'", req.Method, req.RequestURI, contentType, mediaType)
}
body, err := io.ReadAll(resp.Body)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(body, testFile.Content) {
t.Error("stored and received file contents is not the same")
}
}