@@ -10,6 +10,7 @@ import (
10
10
"net/http"
11
11
"net/http/httptest"
12
12
"os"
13
+ "path/filepath"
13
14
"strings"
14
15
"testing"
15
16
@@ -706,6 +707,34 @@ func TestServer_UploadFiles(t *testing.T) {
706
707
expectedStatusCode : http .StatusOK ,
707
708
expectFilePath : true ,
708
709
},
710
+ {
711
+ name : "upload file with absolute path filename" ,
712
+ filename : "/tmp/absolute-path-file.txt" ,
713
+ fileContent : "absolute path content" ,
714
+ expectedStatusCode : http .StatusOK ,
715
+ expectFilePath : true ,
716
+ },
717
+ {
718
+ name : "upload file with relative path filename" ,
719
+ filename : "../relative-path-file.txt" ,
720
+ fileContent : "relative path content" ,
721
+ expectedStatusCode : http .StatusOK ,
722
+ expectFilePath : true ,
723
+ },
724
+ {
725
+ name : "upload file with nested relative path" ,
726
+ filename : "nested/path/file.txt" ,
727
+ fileContent : "nested content" ,
728
+ expectedStatusCode : http .StatusOK ,
729
+ expectFilePath : true ,
730
+ },
731
+ {
732
+ name : "upload file with backslash path separators" ,
733
+ filename : "windows\\ style\\ path.txt" ,
734
+ fileContent : "windows path content" ,
735
+ expectedStatusCode : http .StatusOK ,
736
+ expectFilePath : true ,
737
+ },
709
738
}
710
739
711
740
for _ , tc := range cases {
@@ -766,8 +795,8 @@ func TestServer_UploadFiles(t *testing.T) {
766
795
require .NoError (t , err )
767
796
require .Equal (t , tc .fileContent , string (savedContent ), "file content should match" )
768
797
769
- // Verify filename is preserved in the path
770
- expectedFilename := tc .filename
798
+ // Verify filename is preserved in the path (only the base filename for security)
799
+ expectedFilename := filepath . Base ( tc .filename )
771
800
if expectedFilename == "" {
772
801
expectedFilename = "uploaded_file"
773
802
}
@@ -839,4 +868,91 @@ func TestServer_UploadFiles_Errors(t *testing.T) {
839
868
840
869
require .Equal (t , http .StatusUnprocessableEntity , resp .StatusCode )
841
870
})
871
+
872
+ t .Run ("file size exactly 10MB" , func (t * testing.T ) {
873
+ t .Parallel ()
874
+
875
+ // Create exactly 10MB of data
876
+ const tenMB = 10 << 20
877
+ fileContent := make ([]byte , tenMB )
878
+ for i := range fileContent {
879
+ fileContent [i ] = byte (i % 256 )
880
+ }
881
+
882
+ var buf bytes.Buffer
883
+ writer := multipart .NewWriter (& buf )
884
+ part , err := writer .CreateFormFile ("file" , "10mb-file.bin" )
885
+ require .NoError (t , err )
886
+ _ , err = part .Write (fileContent )
887
+ require .NoError (t , err )
888
+ err = writer .Close ()
889
+ require .NoError (t , err )
890
+
891
+ req , err := http .NewRequest ("POST" , tsServer .URL + "/upload" , & buf )
892
+ require .NoError (t , err )
893
+ req .Header .Set ("Content-Type" , writer .FormDataContentType ())
894
+
895
+ client := & http.Client {}
896
+ resp , err := client .Do (req )
897
+ require .NoError (t , err )
898
+ t .Cleanup (func () {
899
+ _ = resp .Body .Close ()
900
+ })
901
+
902
+ require .Equal (t , http .StatusOK , resp .StatusCode )
903
+
904
+ // Parse response to get file path for cleanup
905
+ body , err := io .ReadAll (resp .Body )
906
+ require .NoError (t , err )
907
+ var uploadResp struct {
908
+ Ok bool `json:"ok"`
909
+ FilePath string `json:"filePath"`
910
+ }
911
+ err = json .Unmarshal (body , & uploadResp )
912
+ require .NoError (t , err )
913
+ require .True (t , uploadResp .Ok )
914
+
915
+ // Clean up the uploaded file
916
+ t .Cleanup (func () {
917
+ _ = os .Remove (uploadResp .FilePath )
918
+ })
919
+ })
920
+
921
+ t .Run ("file size exceeds 10MB limit" , func (t * testing.T ) {
922
+ t .Parallel ()
923
+
924
+ // Create slightly more than 10MB of data
925
+ const tenMBPlusOne = (10 << 20 ) + 1
926
+ fileContent := make ([]byte , tenMBPlusOne )
927
+ for i := range fileContent {
928
+ fileContent [i ] = byte (i % 256 )
929
+ }
930
+
931
+ var buf bytes.Buffer
932
+ writer := multipart .NewWriter (& buf )
933
+ part , err := writer .CreateFormFile ("file" , "large-file.bin" )
934
+ require .NoError (t , err )
935
+ _ , err = part .Write (fileContent )
936
+ require .NoError (t , err )
937
+ err = writer .Close ()
938
+ require .NoError (t , err )
939
+
940
+ req , err := http .NewRequest ("POST" , tsServer .URL + "/upload" , & buf )
941
+ require .NoError (t , err )
942
+ req .Header .Set ("Content-Type" , writer .FormDataContentType ())
943
+
944
+ client := & http.Client {}
945
+ resp , err := client .Do (req )
946
+ require .NoError (t , err )
947
+ t .Cleanup (func () {
948
+ _ = resp .Body .Close ()
949
+ })
950
+
951
+ require .Equal (t , http .StatusBadRequest , resp .StatusCode )
952
+
953
+ // Verify error message
954
+ body , err := io .ReadAll (resp .Body )
955
+ require .NoError (t , err )
956
+ require .Contains (t , string (body ), "file size exceeds 10MB limit" )
957
+ })
842
958
}
0 commit comments