Skip to content

Commit 1b2ea7f

Browse files
committed
version file, SaveFile, SaveFiles returns the saved file size and error
1 parent 57eb043 commit 1b2ea7f

File tree

5 files changed

+129
-91
lines changed

5 files changed

+129
-91
lines changed

ahttp.go

-3
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ import (
1111
"net/http"
1212
)
1313

14-
// Version no. of aah framework ahttp library
15-
const Version = "0.10-dev"
16-
1714
// HTTP Method names
1815
const (
1916
MethodGet = http.MethodGet

content_type_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func TestHTTPParseContentType(t *testing.T) {
9797

9898
req5 := createRawHTTPRequest(HeaderContentType, "text/html;charset")
9999
contentType = ParseContentType(req5)
100-
assert.Equal(t, "", contentType.Mime)
101-
assert.Equal(t, "", contentType.String())
100+
assert.True(t, (contentType.Mime == "" || contentType.Mime == "text/html"))
101+
assert.True(t, (contentType.String() == "" || contentType.String() == "text/html"))
102102
assert.Equal(t, "iso-8859-1", contentType.Charset("iso-8859-1"))
103103
}

request.go

+15-13
Original file line numberDiff line numberDiff line change
@@ -209,18 +209,18 @@ func (r *Request) Unwrap() *http.Request {
209209

210210
// SaveFile method saves an uploaded multipart file for given key from the HTTP
211211
// request into given destination
212-
func (r *Request) SaveFile(key, dstFile string) error {
212+
func (r *Request) SaveFile(key, dstFile string) (int64, error) {
213213
if ess.IsStrEmpty(dstFile) || ess.IsStrEmpty(key) {
214-
return errors.New("ahttp: key or dstFile is empty")
214+
return 0, errors.New("ahttp: key or dstFile is empty")
215215
}
216216

217217
if ess.IsDir(dstFile) {
218-
return errors.New("ahttp: dstFile should not be a directory")
218+
return 0, errors.New("ahttp: dstFile should not be a directory")
219219
}
220220

221221
uploadedFile, _, err := r.FormFile(key)
222222
if err != nil {
223-
return err
223+
return 0, err
224224
}
225225
defer ess.CloseQuietly(uploadedFile)
226226

@@ -230,29 +230,32 @@ func (r *Request) SaveFile(key, dstFile string) error {
230230
// SaveFiles method saves an uploaded multipart file(s) for the given key
231231
// from the HTTP request into given destination directory. It uses the filename
232232
// as uploaded filename from the request
233-
func (r *Request) SaveFiles(key, dstPath string) []error {
233+
func (r *Request) SaveFiles(key, dstPath string) ([]int64, []error) {
234234
if !ess.IsDir(dstPath) {
235-
return []error{fmt.Errorf("ahttp: destination path, %s is not a directory", dstPath)}
235+
return []int64{0}, []error{fmt.Errorf("ahttp: destination path, '%s' is not a directory", dstPath)}
236236
}
237237

238238
if ess.IsStrEmpty(key) {
239-
return []error{fmt.Errorf("ahttp: form file key, %s is empty", key)}
239+
return []int64{0}, []error{fmt.Errorf("ahttp: form file key, '%s' is empty", key)}
240240
}
241241

242242
var errs []error
243+
var sizes []int64
243244
for _, file := range r.Params.File[key] {
244245
uploadedFile, err := file.Open()
245246
if err != nil {
247+
sizes = append(sizes, 0)
246248
errs = append(errs, err)
247249
continue
248250
}
249251

250-
if err := saveFile(uploadedFile, filepath.Join(dstPath, file.Filename)); err != nil {
252+
if size, err := saveFile(uploadedFile, filepath.Join(dstPath, file.Filename)); err != nil {
253+
sizes = append(sizes, size)
251254
errs = append(errs, err)
252255
}
253256
ess.CloseQuietly(uploadedFile)
254257
}
255-
return errs
258+
return sizes, errs
256259
}
257260

258261
// Reset method resets request instance for reuse.
@@ -415,13 +418,12 @@ func isGzipAccepted(req *Request, r *http.Request) bool {
415418
return false
416419
}
417420

418-
func saveFile(r io.Reader, destFile string) error {
421+
func saveFile(r io.Reader, destFile string) (int64, error) {
419422
f, err := os.OpenFile(destFile, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0666)
420423
if err != nil {
421-
return err
424+
return 0, fmt.Errorf("ahttp: %s", err)
422425
}
423426
defer ess.CloseQuietly(f)
424427

425-
_, err = io.Copy(f, r)
426-
return err
428+
return io.Copy(f, r)
427429
}

request_test.go

+104-73
Original file line numberDiff line numberDiff line change
@@ -195,41 +195,14 @@ func TestRequestSchemeDerived(t *testing.T) {
195195
assert.Equal(t, "http", scheme4)
196196
}
197197

198-
func createRequestWithHost(host, remote string) *http.Request {
199-
return &http.Request{Host: host, RemoteAddr: remote, Header: http.Header{}}
200-
}
201-
202-
func setUpRequestSaveFile(t *testing.T) (*Request, string, func()) {
203-
buf := new(bytes.Buffer)
204-
multipartWriter := multipart.NewWriter(buf)
205-
_, err := multipartWriter.CreateFormFile("framework", "aah")
206-
assert.Nil(t, err)
207-
208-
ess.CloseQuietly(multipartWriter)
209-
210-
req, _ := http.NewRequest("POST", "http://localhost:8080", buf)
211-
req.Header.Add(HeaderContentType, multipartWriter.FormDataContentType())
212-
aahReq := AcquireRequest(req)
213-
aahReq.Params.File = make(map[string][]*multipart.FileHeader)
214-
215-
_, header, err := req.FormFile("framework")
216-
assert.Nil(t, err)
217-
218-
aahReq.Params.File["framework"] = []*multipart.FileHeader{header}
219-
220-
path := "testdata/aah.txt"
221-
222-
return aahReq, path, func() {
223-
_ = os.Remove(path) //Teardown
224-
}
225-
}
226-
227198
func TestRequestSaveFile(t *testing.T) {
228199
aahReq, path, teardown := setUpRequestSaveFile(t)
229200
defer teardown()
230201

231-
assert.Nil(t, aahReq.SaveFile("framework", path))
232-
_, err := os.Stat(path)
202+
size, err := aahReq.SaveFile("framework", path)
203+
assert.Nil(t, err)
204+
assert.Equal(t, int64(0), size)
205+
_, err = os.Stat(path)
233206
assert.Nil(t, err)
234207
}
235208

@@ -238,64 +211,46 @@ func TestRequestSaveFileFailsValidation(t *testing.T) {
238211
defer teardown()
239212

240213
// Empty keys should error out
241-
assert.NotNil(t, aahReq.SaveFile("", path))
214+
_, err := aahReq.SaveFile("", path)
215+
assert.NotNil(t, err)
216+
assert.Equal(t, "ahttp: key or dstFile is empty", err.Error())
242217

243218
// Empty path should error out
244-
assert.NotNil(t, aahReq.SaveFile("framework", ""))
219+
_, err = aahReq.SaveFile("framework", "")
220+
assert.NotNil(t, err)
221+
assert.Equal(t, "ahttp: key or dstFile is empty", err.Error())
245222

246223
// If "path" is a directory, it should error out
247-
assert.NotNil(t, aahReq.SaveFile("framework", "testdata"))
224+
_, err = aahReq.SaveFile("framework", "testdata")
225+
assert.NotNil(t, err)
226+
assert.Equal(t, "ahttp: dstFile should not be a directory", err.Error())
248227
}
249228

250229
func TestRequestSaveFileFailsForNotFoundFile(t *testing.T) {
251230
aahReq, path, teardown := setUpRequestSaveFile(t)
252231
defer teardown()
253232

254-
assert.NotNil(t, aahReq.SaveFile("unknown-key", path))
233+
_, err := aahReq.SaveFile("unknown-key", path)
234+
assert.NotNil(t, err)
235+
assert.Equal(t, "ahttp: no such key/file: unknown-key", err.Error())
255236
}
256237

257238
func TestRequestSaveFileCannotCreateFile(t *testing.T) {
258239
aahReq, _, teardown := setUpRequestSaveFile(t)
259240
defer teardown()
260241

261-
assert.NotNil(t, aahReq.SaveFile("framework", "/root/aah.txt"))
262-
}
263-
264-
func setUpRequestSaveFiles(t *testing.T) (*Request, string, func()) {
265-
buf := new(bytes.Buffer)
266-
multipartWriter := multipart.NewWriter(buf)
267-
_, err := multipartWriter.CreateFormFile("framework", "aah")
268-
assert.Nil(t, err)
269-
_, err = multipartWriter.CreateFormFile("framework2", "aah2")
270-
assert.Nil(t, err)
271-
272-
ess.CloseQuietly(multipartWriter)
273-
274-
req, _ := http.NewRequest("POST", "http://localhost:8080", buf)
275-
req.Header.Add(HeaderContentType, multipartWriter.FormDataContentType())
276-
aahReq := AcquireRequest(req)
277-
aahReq.Params.File = make(map[string][]*multipart.FileHeader)
278-
279-
_, header, err := req.FormFile("framework")
280-
assert.Nil(t, err)
281-
_, header2, err := req.FormFile("framework2")
282-
assert.Nil(t, err)
283-
284-
aahReq.Params.File["framework"] = []*multipart.FileHeader{header, header2}
285-
286-
dir := "testdata/upload"
287-
288-
_ = ess.MkDirAll(dir, 0755)
289-
return aahReq, dir, func() {
290-
_ = os.RemoveAll(dir)
291-
}
242+
_, err := aahReq.SaveFile("framework", "/root/aah.txt")
243+
assert.NotNil(t, err)
244+
assert.True(t, strings.HasPrefix(err.Error(), "ahttp: open /root/aah.txt"))
292245
}
293246

294247
func TestRequestSaveFiles(t *testing.T) {
295248
aahReq, dir, teardown := setUpRequestSaveFiles(t)
296249
defer teardown()
297250

298-
assert.Nil(t, aahReq.SaveFiles("framework", dir))
251+
sizes, errs := aahReq.SaveFiles("framework", dir)
252+
assert.Nil(t, errs)
253+
assert.Nil(t, sizes)
299254
_, err := os.Stat(dir + "/aah")
300255
assert.Nil(t, err)
301256
_, err = os.Stat(dir + "/aah2")
@@ -307,23 +262,99 @@ func TestRequestSaveFilesFailsVaildation(t *testing.T) {
307262
defer teardown()
308263

309264
// Empty key
310-
assert.NotNil(t, aahReq.SaveFiles("", dir))
265+
sizes, errs := aahReq.SaveFiles("", dir)
266+
assert.NotNil(t, errs)
267+
assert.Equal(t, "ahttp: form file key, '' is empty", errs[0].Error())
268+
assert.Equal(t, int64(0), sizes[0])
311269

312270
// Empty directory
313-
assert.NotNil(t, aahReq.SaveFiles("key", ""))
271+
sizes, errs = aahReq.SaveFiles("key", "")
272+
assert.NotNil(t, errs)
273+
assert.Equal(t, "ahttp: destination path, '' is not a directory", errs[0].Error())
274+
assert.Equal(t, int64(0), sizes[0])
314275
}
315276

316277
func TestRequestSaveFilesCannotCreateFile(t *testing.T) {
317278
aahReq, _, teardown := setUpRequestSaveFiles(t)
318279
defer teardown()
319280

320-
assert.NotNil(t, aahReq.SaveFiles("framework", "/root"))
281+
sizes, errs := aahReq.SaveFiles("framework", "/root")
282+
assert.NotNil(t, errs)
283+
assert.Equal(t, int64(0), sizes[0])
284+
285+
errMsg := errs[0].Error()
286+
assert.True(t, ("ahttp: open /root/aah: permission denied" == errMsg ||
287+
"ahttp: destination path, '/root' is not a directory" == errMsg))
321288
}
322289

323-
func TestRequestsaveFileForExistingFile(t *testing.T) {
290+
func TestRequestSaveFileForExistingFile(t *testing.T) {
324291
var buf bytes.Buffer
325292

326-
err := saveFile(&buf, "testdata/file1.txt")
293+
size, err := saveFile(&buf, "testdata/file1.txt")
327294
assert.NotNil(t, err)
328-
assert.Equal(t, "open testdata/file1.txt: file exists", err.Error())
295+
assert.Equal(t, "ahttp: open testdata/file1.txt: file exists", err.Error())
296+
assert.Equal(t, int64(0), size)
297+
}
298+
299+
//‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾
300+
// test unexported methods
301+
//___________________________________
302+
303+
func createRequestWithHost(host, remote string) *http.Request {
304+
return &http.Request{Host: host, RemoteAddr: remote, Header: http.Header{}}
305+
}
306+
307+
func setUpRequestSaveFile(t *testing.T) (*Request, string, func()) {
308+
buf := new(bytes.Buffer)
309+
multipartWriter := multipart.NewWriter(buf)
310+
_, err := multipartWriter.CreateFormFile("framework", "aah")
311+
assert.Nil(t, err)
312+
313+
ess.CloseQuietly(multipartWriter)
314+
315+
req, _ := http.NewRequest("POST", "http://localhost:8080", buf)
316+
req.Header.Add(HeaderContentType, multipartWriter.FormDataContentType())
317+
aahReq := AcquireRequest(req)
318+
aahReq.Params.File = make(map[string][]*multipart.FileHeader)
319+
320+
_, header, err := req.FormFile("framework")
321+
assert.Nil(t, err)
322+
323+
aahReq.Params.File["framework"] = []*multipart.FileHeader{header}
324+
325+
path := "testdata/aah.txt"
326+
327+
return aahReq, path, func() {
328+
_ = os.Remove(path) //Teardown
329+
}
330+
}
331+
332+
func setUpRequestSaveFiles(t *testing.T) (*Request, string, func()) {
333+
buf := new(bytes.Buffer)
334+
multipartWriter := multipart.NewWriter(buf)
335+
_, err := multipartWriter.CreateFormFile("framework", "aah")
336+
assert.Nil(t, err)
337+
_, err = multipartWriter.CreateFormFile("framework2", "aah2")
338+
assert.Nil(t, err)
339+
340+
ess.CloseQuietly(multipartWriter)
341+
342+
req, _ := http.NewRequest("POST", "http://localhost:8080", buf)
343+
req.Header.Add(HeaderContentType, multipartWriter.FormDataContentType())
344+
aahReq := AcquireRequest(req)
345+
aahReq.Params.File = make(map[string][]*multipart.FileHeader)
346+
347+
_, header, err := req.FormFile("framework")
348+
assert.Nil(t, err)
349+
_, header2, err := req.FormFile("framework2")
350+
assert.Nil(t, err)
351+
352+
aahReq.Params.File["framework"] = []*multipart.FileHeader{header, header2}
353+
354+
dir := "testdata/upload"
355+
356+
_ = ess.MkDirAll(dir, 0755)
357+
return aahReq, dir, func() {
358+
_ = os.RemoveAll(dir)
359+
}
329360
}

version.go

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// Copyright (c) Jeevanandam M (https://github.com/jeevatkm)
2+
// go-aah/ahttp source code and usage is governed by a MIT style
3+
// license that can be found in the LICENSE file.
4+
5+
package ahttp
6+
7+
// Version no. of aah framework ahttp library
8+
const Version = "0.10"

0 commit comments

Comments
 (0)