示例#1
0
        private IWebRequest CreateDs3WebRequest(Ds3Request request, Stream content)
        {
            if (request.Verb == HttpVerb.PUT || request.Verb == HttpVerb.POST)
            {
                if (content != Stream.Null && !content.CanRead)
                {
                    throw new Ds3RequestException(Resources.InvalidStreamException);
                }
            }

            var date = DateTime.UtcNow;
            var uriBuilder = new UriBuilder(_endpoint)
            {
                Path = HttpHelper.PercentEncodePath(request.Path)
            };

            if (request.QueryParams.Count > 0)
            {
                uriBuilder.Query = BuildQueryParams(request.QueryParams);
            }

            var httpRequest = (HttpWebRequest)WebRequest.Create(uriBuilder.ToString());
            httpRequest.ServicePoint.ConnectionLimit = _connectionLimit;
            httpRequest.Method = request.Verb.ToString();
            if (Proxy != null)
            {
                var webProxy = new WebProxy
                {
                    Address = Proxy
                };
                httpRequest.Proxy = webProxy;
            }
            httpRequest.Date = date;
            httpRequest.Host = CreateHostString(_endpoint);
            httpRequest.AllowAutoRedirect = false;
            httpRequest.AllowWriteStreamBuffering = false;
            // hangs on Mono's NET framework for DELETEs (NETSDK-58)
            if (request.Verb == HttpVerb.DELETE)
            {
                httpRequest.AllowWriteStreamBuffering = true;
            }
            httpRequest.ReadWriteTimeout = this._readWriteTimeout;
            httpRequest.Timeout = this._requestTimeout;

            var chucksumValue = ComputeChecksum(request.ChecksumValue, content, request.CType);
            if (!string.IsNullOrEmpty(chucksumValue))
            {
                switch (request.CType)
                {
                    case ChecksumType.Type.MD5:
                        if (SdkNetworkSwitch.TraceVerbose) Trace.WriteLine(string.Format("MD5 checksum is {0}", chucksumValue));
                        httpRequest.Headers.Add(HttpHeaders.ContentMd5, chucksumValue);
                        break;
                    case ChecksumType.Type.SHA_256:
                        if (SdkNetworkSwitch.TraceVerbose) Trace.WriteLine(string.Format("SHA-256 checksum is {0}", chucksumValue));
                        httpRequest.Headers.Add(HttpHeaders.ContentSha256, chucksumValue);
                        break;
                    case ChecksumType.Type.SHA_512:
                        if (SdkNetworkSwitch.TraceVerbose) Trace.WriteLine(string.Format("SHA-512 checksum is {0}", chucksumValue));
                        httpRequest.Headers.Add(HttpHeaders.ContentSha512, chucksumValue);
                        break;
                    case ChecksumType.Type.CRC_32:
                        if (SdkNetworkSwitch.TraceVerbose) Trace.WriteLine(string.Format("Crc32 checksum is {0}", chucksumValue));
                        httpRequest.Headers.Add(HttpHeaders.ContentCRC32, chucksumValue);
                        break;
                    case ChecksumType.Type.CRC_32C:
                        if (SdkNetworkSwitch.TraceVerbose) Trace.WriteLine(string.Format("Crc32C checksum is {0}", chucksumValue));
                        httpRequest.Headers.Add(HttpHeaders.ContentCRC32C, chucksumValue);
                        break;
                }
            }

            httpRequest.Headers.Add(HttpHeaders.Authorization, S3Signer.AuthField(
                _creds,
                request.Verb.ToString(),
                date.ToString("r"),
                request.Path,
                request.QueryParams,
                chucksumValue,
                amzHeaders: request.Headers
            ));

            foreach (var byteRange in request.GetByteRanges())
            {
                httpRequest.AddRange(byteRange.Start, byteRange.End);
            }

            foreach (var header in request.Headers)
            {
                httpRequest.Headers.Add(header.Key, header.Value);
            }

            if (request.Verb == HttpVerb.PUT || request.Verb == HttpVerb.POST)
            {
                httpRequest.ContentLength = request.GetContentLength();
                if (content != Stream.Null)
                {
                    var ds3ContentLengthNotMatchCatched = false;
                    Ds3ContentLengthNotMatch ds3ContentLengthNotMatch = null;
                    try
                    {
                        using (var requestStream = httpRequest.GetRequestStream())
                        {
                            if (content.CanSeek && content.Position != 0)
                            {
                                content.Seek(0, SeekOrigin.Begin);
                            }
                            using (var webStream = new Ds3WebStream(content, request.GetContentLength()))
                            {
                                try
                                {
                                    webStream.CopyTo(requestStream, this.CopyBufferSize);
                                }
                                catch (Ds3ContentLengthNotMatch ex)
                                {
                                    ds3ContentLengthNotMatchCatched = true;
                                    ds3ContentLengthNotMatch = ex;
                                    throw ds3ContentLengthNotMatch;
                                }
                                catch (Exception ex)
                                {
                                    const string windowsMessage = "Bytes to be written to the stream exceed the Content-Length bytes size specified.";
                                    const string monoMessage = "The number of bytes to be written is greater than the specified ContentLength.";
                                    if (ex.Message.Equals(windowsMessage) || ex.Message.Equals(monoMessage))
                                    {
                                        ds3ContentLengthNotMatchCatched = true;
                                        ds3ContentLengthNotMatch = new Ds3ContentLengthNotMatch(ex.Message, ex);
                                        throw ds3ContentLengthNotMatch;
                                    }
                                    throw;
                                }
                                requestStream.Flush();
                            }
                        }
                    }
                    //if only Ds3ContentLengthNotMatch was thrown than just re-throw it
                    catch (Ds3ContentLengthNotMatch)
                    {
                        throw;
                    }
                    //if an Exception was thrown from closing requestStream in finally block and also Ds3ContentLengthNotMatch than we will aggregate them,
                    //and if not than just re-throw
                    catch (Exception ex)
                    {
                        if (!ds3ContentLengthNotMatchCatched) throw;

                        var innerExceptions = ds3ContentLengthNotMatch.InnerExceptions.Select(e => e).ToList();
                        innerExceptions.Add(ex);
                        throw new Ds3ContentLengthNotMatch(ds3ContentLengthNotMatch.Message, innerExceptions);
                    }
                }
            }
            return new Ds3WebRequest(httpRequest);
        }