github.com/isi-lincoln/grab@v2.0.1-0.20200331080741-9f014744ee41+incompatible/request.go (about)

     1  package grab
     2  
     3  import (
     4  	"context"
     5  	"hash"
     6  	"net/http"
     7  	"net/url"
     8  )
     9  
    10  // A Hook is a user provided callback function that can be called by grab at
    11  // various stages of a requests lifecycle. If a hook returns an error, the
    12  // associated request is canceled and the same error is returned on the Response
    13  // object.
    14  //
    15  // Hook functions are called synchronously and should never block unnecessarily.
    16  // Response methods that block until a download is complete, such as
    17  // Response.Err, Response.Cancel or Response.Wait will deadlock. To cancel a
    18  // download from a callback, simply return a non-nil error.
    19  type Hook func(*Response) error
    20  
    21  // A Request represents an HTTP file transfer request to be sent by a Client.
    22  type Request struct {
    23  	// Label is an arbitrary string which may used to label a Request with a
    24  	// user friendly name.
    25  	Label string
    26  
    27  	// Tag is an arbitrary interface which may be used to relate a Request to
    28  	// other data.
    29  	Tag interface{}
    30  
    31  	// HTTPRequest specifies the http.Request to be sent to the remote server to
    32  	// initiate a file transfer. It includes request configuration such as URL,
    33  	// protocol version, HTTP method, request headers and authentication.
    34  	HTTPRequest *http.Request
    35  
    36  	// Filename specifies the path where the file transfer will be stored in
    37  	// local storage. If Filename is empty or a directory, the true Filename will
    38  	// be resolved using Content-Disposition headers or the request URL.
    39  	//
    40  	// An empty string means the transfer will be stored in the current working
    41  	// directory.
    42  	Filename string
    43  
    44  	// SkipExisting specifies that ErrFileExists should be returned if the
    45  	// destination path already exists. The existing file will not be checked for
    46  	// completeness.
    47  	SkipExisting bool
    48  
    49  	// NoResume specifies that a partially completed download will be restarted
    50  	// without attempting to resume any existing file. If the download is already
    51  	// completed in full, it will not be restarted.
    52  	NoResume bool
    53  
    54  	// NoStore specifies that grab should not write to the local file system.
    55  	// Instead, the download will be stored in memory and accessible only via
    56  	// Response.Open or Response.Bytes.
    57  	NoStore bool
    58  
    59  	// NoCreateDirectories specifies that any missing directories in the given
    60  	// Filename path should not be created automatically, if they do not already
    61  	// exist.
    62  	NoCreateDirectories bool
    63  
    64  	// IgnoreBadStatusCodes specifies that grab should accept any status code in
    65  	// the response from the remote server. Otherwise, grab expects the response
    66  	// status code to be within the 2XX range (after following redirects).
    67  	IgnoreBadStatusCodes bool
    68  
    69  	// IgnoreRemoteTime specifies that grab should not attempt to set the
    70  	// timestamp of the local file to match the remote file.
    71  	IgnoreRemoteTime bool
    72  
    73  	// Size specifies the expected size of the file transfer if known. If the
    74  	// server response size does not match, the transfer is cancelled and
    75  	// ErrBadLength returned.
    76  	Size int64
    77  
    78  	// BufferSize specifies the size in bytes of the buffer that is used for
    79  	// transferring the requested file. Larger buffers may result in faster
    80  	// throughput but will use more memory and result in less frequent updates
    81  	// to the transfer progress statistics. If a RateLimiter is configured,
    82  	// BufferSize should be much lower than the rate limit. Default: 32KB.
    83  	BufferSize int
    84  
    85  	// RateLimiter allows the transfer rate of a download to be limited. The given
    86  	// Request.BufferSize determines how frequently the RateLimiter will be
    87  	// polled.
    88  	RateLimiter RateLimiter
    89  
    90  	// BeforeCopy is a user provided callback that is called immediately before
    91  	// a request starts downloading. If BeforeCopy returns an error, the request
    92  	// is cancelled and the same error is returned on the Response object.
    93  	BeforeCopy Hook
    94  
    95  	// AfterCopy is a user provided callback that is called immediately after a
    96  	// request has finished downloading, before checksum validation and closure.
    97  	// This hook is only called if the transfer was successful. If AfterCopy
    98  	// returns an error, the request is canceled and the same error is returned on
    99  	// the Response object.
   100  	AfterCopy Hook
   101  
   102  	// hash, checksum and deleteOnError - set via SetChecksum.
   103  	hash          hash.Hash
   104  	checksum      []byte
   105  	deleteOnError bool
   106  
   107  	// Context for cancellation and timeout - set via WithContext
   108  	ctx context.Context
   109  }
   110  
   111  // NewRequest returns a new file transfer Request suitable for use with
   112  // Client.Do.
   113  func NewRequest(dst, urlStr string) (*Request, error) {
   114  	if dst == "" {
   115  		dst = "."
   116  	}
   117  	req, err := http.NewRequest("GET", urlStr, nil)
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  	return &Request{
   122  		HTTPRequest: req,
   123  		Filename:    dst,
   124  	}, nil
   125  }
   126  
   127  // Context returns the request's context. To change the context, use
   128  // WithContext.
   129  //
   130  // The returned context is always non-nil; it defaults to the background
   131  // context.
   132  //
   133  // The context controls cancelation.
   134  func (r *Request) Context() context.Context {
   135  	if r.ctx != nil {
   136  		return r.ctx
   137  	}
   138  
   139  	return context.Background()
   140  }
   141  
   142  // WithContext returns a shallow copy of r with its context changed
   143  // to ctx. The provided ctx must be non-nil.
   144  func (r *Request) WithContext(ctx context.Context) *Request {
   145  	if ctx == nil {
   146  		panic("nil context")
   147  	}
   148  	r2 := new(Request)
   149  	*r2 = *r
   150  	r2.ctx = ctx
   151  	r2.HTTPRequest = r2.HTTPRequest.WithContext(ctx)
   152  	return r2
   153  }
   154  
   155  // URL returns the URL to be downloaded.
   156  func (r *Request) URL() *url.URL {
   157  	return r.HTTPRequest.URL
   158  }
   159  
   160  // SetChecksum sets the desired hashing algorithm and checksum value to validate
   161  // a downloaded file. Once the download is complete, the given hashing algorithm
   162  // will be used to compute the actual checksum of the downloaded file. If the
   163  // checksums do not match, an error will be returned by the associated
   164  // Response.Err method.
   165  //
   166  // If deleteOnError is true, the downloaded file will be deleted automatically
   167  // if it fails checksum validation.
   168  //
   169  // To prevent corruption of the computed checksum, the given hash must not be
   170  // used by any other request or goroutines.
   171  //
   172  // To disable checksum validation, call SetChecksum with a nil hash.
   173  func (r *Request) SetChecksum(h hash.Hash, sum []byte, deleteOnError bool) {
   174  	r.hash = h
   175  	r.checksum = sum
   176  	r.deleteOnError = deleteOnError
   177  }