cmd/swarm, swarm: cross-platform Content-Type detection (#17782)
- Mime types generator (Standard "mime" package rely on system-settings, see mime.osInitMime)
- Changed swarm/api.Upload:
    - simplify I/O throttling by semaphore primitive and use file name where possible
    - f.Close() must be called in Defer - otherwise panic or future added early return will cause leak of file descriptors
    - one error was suppressed
			
			
This commit is contained in:
		
				
					committed by
					
						 Anton Evangelatov
						Anton Evangelatov
					
				
			
			
				
	
			
			
			
						parent
						
							b69942befe
						
					
				
				
					commit
					dc5d643bb5
				
			| @@ -16,6 +16,9 @@ | ||||
|  | ||||
| package api | ||||
|  | ||||
| //go:generate mimegen --types=./../../cmd/swarm/mimegen/mime.types --package=api --out=gen_mime.go | ||||
| //go:generate gofmt -s -w gen_mime.go | ||||
|  | ||||
| import ( | ||||
| 	"archive/tar" | ||||
| 	"context" | ||||
| @@ -29,8 +32,6 @@ import ( | ||||
| 	"path" | ||||
| 	"strings" | ||||
|  | ||||
| 	"github.com/ethereum/go-ethereum/swarm/storage/mru/lookup" | ||||
|  | ||||
| 	"bytes" | ||||
| 	"mime" | ||||
| 	"path/filepath" | ||||
| @@ -45,7 +46,8 @@ import ( | ||||
| 	"github.com/ethereum/go-ethereum/swarm/spancontext" | ||||
| 	"github.com/ethereum/go-ethereum/swarm/storage" | ||||
| 	"github.com/ethereum/go-ethereum/swarm/storage/mru" | ||||
| 	opentracing "github.com/opentracing/opentracing-go" | ||||
| 	"github.com/ethereum/go-ethereum/swarm/storage/mru/lookup" | ||||
| 	"github.com/opentracing/opentracing-go" | ||||
| ) | ||||
|  | ||||
| var ( | ||||
| @@ -757,9 +759,14 @@ func (a *API) UploadTar(ctx context.Context, bodyReader io.ReadCloser, manifestP | ||||
|  | ||||
| 		// add the entry under the path from the request | ||||
| 		manifestPath := path.Join(manifestPath, hdr.Name) | ||||
| 		contentType := hdr.Xattrs["user.swarm.content-type"] | ||||
| 		if contentType == "" { | ||||
| 			contentType = mime.TypeByExtension(filepath.Ext(hdr.Name)) | ||||
| 		} | ||||
| 		//DetectContentType("") | ||||
| 		entry := &ManifestEntry{ | ||||
| 			Path:        manifestPath, | ||||
| 			ContentType: hdr.Xattrs["user.swarm.content-type"], | ||||
| 			ContentType: contentType, | ||||
| 			Mode:        hdr.Mode, | ||||
| 			Size:        hdr.Size, | ||||
| 			ModTime:     hdr.ModTime, | ||||
| @@ -770,10 +777,15 @@ func (a *API) UploadTar(ctx context.Context, bodyReader io.ReadCloser, manifestP | ||||
| 			return nil, fmt.Errorf("error adding manifest entry from tar stream: %s", err) | ||||
| 		} | ||||
| 		if hdr.Name == defaultPath { | ||||
| 			contentType := hdr.Xattrs["user.swarm.content-type"] | ||||
| 			if contentType == "" { | ||||
| 				contentType = mime.TypeByExtension(filepath.Ext(hdr.Name)) | ||||
| 			} | ||||
|  | ||||
| 			entry := &ManifestEntry{ | ||||
| 				Hash:        contentKey.Hex(), | ||||
| 				Path:        "", // default entry | ||||
| 				ContentType: hdr.Xattrs["user.swarm.content-type"], | ||||
| 				ContentType: contentType, | ||||
| 				Mode:        hdr.Mode, | ||||
| 				Size:        hdr.Size, | ||||
| 				ModTime:     hdr.ModTime, | ||||
| @@ -1033,3 +1045,32 @@ func (a *API) ResolveResourceView(ctx context.Context, uri *URI, values mru.Valu | ||||
| 	} | ||||
| 	return view, nil | ||||
| } | ||||
|  | ||||
| // MimeOctetStream default value of http Content-Type header | ||||
| const MimeOctetStream = "application/octet-stream" | ||||
|  | ||||
| // DetectContentType by file file extension, or fallback to content sniff | ||||
| func DetectContentType(fileName string, f io.ReadSeeker) (string, error) { | ||||
| 	ctype := mime.TypeByExtension(filepath.Ext(fileName)) | ||||
| 	if ctype != "" { | ||||
| 		return ctype, nil | ||||
| 	} | ||||
|  | ||||
| 	// save/rollback to get content probe from begin of file | ||||
| 	currentPosition, err := f.Seek(0, io.SeekCurrent) | ||||
| 	if err != nil { | ||||
| 		return MimeOctetStream, fmt.Errorf("seeker can't seek, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	// read a chunk to decide between utf-8 text and binary | ||||
| 	var buf [512]byte | ||||
| 	n, _ := f.Read(buf[:]) | ||||
| 	ctype = http.DetectContentType(buf[:n]) | ||||
|  | ||||
| 	_, err = f.Seek(currentPosition, io.SeekStart) // rewind to output whole file | ||||
| 	if err != nil { | ||||
| 		return MimeOctetStream, fmt.Errorf("seeker can't seek, %s", err) | ||||
| 	} | ||||
|  | ||||
| 	return ctype, nil | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user