Пример #1
0
		private RangeHeaderValue (RangeHeaderValue source)
			: this ()
		{
			if (source.ranges != null) {
				foreach (var item in source.ranges)
					Ranges.Add (item);
			}
		}
Пример #2
0
        public void TryParse_SetOfValidValueStrings_ParsedCorrectly()
        {
            CheckValidParsedValue("X bytes=1-2 ", 1, new RangeHeaderValue(1, 2), 12);

            RangeHeaderValue expected = new RangeHeaderValue();
            expected.Unit = "custom";
            expected.Ranges.Add(new RangeItemHeaderValue(null, 5));
            expected.Ranges.Add(new RangeItemHeaderValue(1, 4));
            CheckValidParsedValue("custom = -  5 , 1 - 4 ,,", 0, expected, 24);
        }
Пример #3
0
 private void CheckValidParsedValue(string input, int startIndex, RangeHeaderValue expectedResult,
     int expectedIndex)
 {
     HttpHeaderParser parser = GenericHeaderParser.RangeParser;
     object result = null;
     Assert.True(parser.TryParseValue(input, null, ref startIndex, out result),
         string.Format("TryParse returned false. Input: '{0}'", input));
     Assert.Equal(expectedIndex, startIndex);
     Assert.Equal(expectedResult, result);
 }
 public void Ctor_ThrowsOnNullContent()
 {
     RangeHeaderValue range = new RangeHeaderValue();
     Assert.ThrowsArgumentNull(() => new ByteRangeStreamContent(
         content: null,
         range: range,
         mediaType: _expectedMediatype,
         bufferSize: 128),
         "content");
 }
Пример #5
0
 private RangeHeaderValue(RangeHeaderValue source)
     : this()
 {
     if (source.ranges != null)
     {
         foreach (var item in source.ranges)
         {
             Ranges.Add(item);
         }
     }
 }
Пример #6
0
        public void ToString_UseDifferentRanges_AllSerializedCorrectly()
        {
            RangeHeaderValue range = new RangeHeaderValue();
            range.Unit = "myunit";
            range.Ranges.Add(new RangeItemHeaderValue(1, 3));
            Assert.Equal("myunit=1-3", range.ToString());

            range.Ranges.Add(new RangeItemHeaderValue(5, null));
            range.Ranges.Add(new RangeItemHeaderValue(null, 17));
            Assert.Equal("myunit=1-3, 5-, -17", range.ToString());
        }
Пример #7
0
        public void Unit_GetAndSetValidAndInvalidValues_MatchExpectation()
        {
            RangeHeaderValue range = new RangeHeaderValue();
            range.Unit = "myunit";
            Assert.Equal("myunit", range.Unit);

            Assert.Throws<ArgumentException>(() => { range.Unit = null; });
            Assert.Throws<ArgumentException>(() => { range.Unit = ""; });
            Assert.Throws<FormatException>(() => { range.Unit = " x"; });
            Assert.Throws<FormatException>(() => { range.Unit = "x "; });
            Assert.Throws<FormatException>(() => { range.Unit = "x y"; });
        }
Пример #8
0
		public void Equals ()
		{
			var value = new RangeHeaderValue (4, null);
			Assert.AreEqual (value, new RangeHeaderValue (4, null), "#1");
			Assert.AreNotEqual (value, new RangeHeaderValue (4, 5), "#2");
			Assert.AreNotEqual (value, new RangeHeaderValue (), "#3");

			value = new RangeHeaderValue (2, 4);
			Assert.AreEqual (value, new RangeHeaderValue (2, 4), "#4");
			Assert.AreNotEqual (value, new RangeHeaderValue (2, null), "#5");
			Assert.AreNotEqual (value, new RangeHeaderValue (2, 3), "#6");
		}
Пример #9
0
        public override bool Equals(object obj)
        {
            RangeHeaderValue other = obj as RangeHeaderValue;

            if (other == null)
            {
                return(false);
            }

            return(string.Equals(_unit, other._unit, StringComparison.OrdinalIgnoreCase) &&
                   HeaderUtilities.AreEqualCollections(_ranges, other._ranges));
        }
Пример #10
0
        private RangeHeaderValue(RangeHeaderValue source)
        {
            Debug.Assert(source != null);

            _unit = source._unit;
            if (source._ranges != null)
            {
                foreach (RangeItemHeaderValue range in source._ranges)
                {
                    this.Ranges.Add(new RangeItemHeaderValue(range));
                }
            }
        }
Пример #11
0
        private RangeHeaderValue(RangeHeaderValue source)
        {
            Debug.Assert(source != null);

            _unit = source._unit;
            if (source._ranges != null)
            {
                foreach (RangeItemHeaderValue range in source._ranges)
                {
                    this.Ranges.Add((RangeItemHeaderValue)((ICloneable)range).Clone());
                }
            }
        }
Пример #12
0
        private RangeHeaderValue(RangeHeaderValue source)
        {
            Debug.Assert(source != null);

            _unit = source._unit;
            if (source._ranges != null)
            {
                foreach (RangeItemHeaderValue range in source._ranges)
                {
                    this.Ranges.Add((RangeItemHeaderValue)((ICloneable)range).Clone());
                }
            }
        }
Пример #13
0
        private RangeHeaderValue(RangeHeaderValue source)
        {
            Contract.Requires(source != null);

            _unit = source._unit;
            if (source._ranges != null)
            {
                foreach (RangeItemHeaderValue range in source._ranges)
                {
                    this.Ranges.Add((RangeItemHeaderValue)((ICloneable)range).Clone());
                }
            }
        }
Пример #14
0
        private RangeHeaderValue(RangeHeaderValue source)
        {
            Contract.Requires(source != null);

            _unit = source._unit;
            if (source._ranges != null)
            {
                foreach (RangeItemHeaderValue range in source._ranges)
                {
                    this.Ranges.Add((RangeItemHeaderValue)((ICloneable)range).Clone());
                }
            }
        }
Пример #15
0
        public static bool TryParse(string input, out RangeHeaderValue parsedValue)
        {
            int    index = 0;
            object output;

            parsedValue = null;

            if (GenericHeaderParser.RangeParser.TryParseValue(input, null, ref index, out output))
            {
                parsedValue = (RangeHeaderValue)output;
                return(true);
            }
            return(false);
        }
        public void Ctor_ThrowsIfCantSeekContent()
        {
            // Arrange
            Mock<Stream> mockInnerStream = new Mock<Stream>();
            mockInnerStream.Setup(s => s.CanSeek).Returns(false);
            RangeHeaderValue range = new RangeHeaderValue();

            // Act/Assert
            Assert.ThrowsArgument(() => new ByteRangeStreamContent(
                content: mockInnerStream.Object,
                range: range,
                mediaType: _expectedMediatype,
                bufferSize: 128),
                "content");
        }
Пример #17
0
        internal static int GetRangeLength(string input, int startIndex, out object parsedValue)
        {
            Contract.Requires(startIndex >= 0);

            parsedValue = null;

            if (string.IsNullOrEmpty(input) || (startIndex >= input.Length))
            {
                return(0);
            }

            // Parse the unit string: <unit> in '<unit>=<from1>-<to1>, <from2>-<to2>'
            int unitLength = HttpRuleParser.GetTokenLength(input, startIndex);

            if (unitLength == 0)
            {
                return(0);
            }

            RangeHeaderValue result = new RangeHeaderValue();

            result._unit = input.Substring(startIndex, unitLength);
            int current = startIndex + unitLength;

            current = current + HttpRuleParser.GetWhitespaceLength(input, current);

            if ((current == input.Length) || (input[current] != '='))
            {
                return(0);
            }

            current++; // skip '=' separator
            current = current + HttpRuleParser.GetWhitespaceLength(input, current);

            int rangesLength = RangeItemHeaderValue.GetRangeItemListLength(input, current, result.Ranges);

            if (rangesLength == 0)
            {
                return(0);
            }

            current = current + rangesLength;
            Debug.Assert(current == input.Length, "GetRangeItemListLength() should consume the whole string or fail.");

            parsedValue = result;
            return(current - startIndex);
        }
		public override void OnActionExecuting(HttpActionContext actionContext)
		{
			if(!actionContext.ActionDescriptor.ReturnType.IsGenericType ||
				actionContext.ActionDescriptor.ReturnType.GetGenericTypeDefinition()!=typeof(IEnumerable<>))
			{
				throw new InvalidOperationException("Return type must be IEnumerable<T>.");
			}
			else
			{
				_elementType = actionContext.ActionDescriptor.ReturnType.GetGenericArguments()[0];
			}

			_requestRangeHeader = actionContext.Request.Headers.Range;

			if (_requestRangeHeader!=null && _requestRangeHeader.Unit != EnityRangeUnit)
				throw new HttpResponseException(new HttpResponseMessage(HttpStatusCode.RequestedRangeNotSatisfiable));

			base.OnActionExecuting(actionContext);
		}
Пример #19
0
        public void GetHashCode_UseSameAndDifferentRanges_SameOrDifferentHashCodes()
        {
            RangeHeaderValue range1 = new RangeHeaderValue(1, 2);
            RangeHeaderValue range2 = new RangeHeaderValue(1, 2);
            range2.Unit = "BYTES";
            RangeHeaderValue range3 = new RangeHeaderValue(1, null);
            RangeHeaderValue range4 = new RangeHeaderValue(null, 2);
            RangeHeaderValue range5 = new RangeHeaderValue();
            range5.Ranges.Add(new RangeItemHeaderValue(1, 2));
            range5.Ranges.Add(new RangeItemHeaderValue(3, 4));
            RangeHeaderValue range6 = new RangeHeaderValue();
            range6.Ranges.Add(new RangeItemHeaderValue(3, 4)); // reverse order of range5
            range6.Ranges.Add(new RangeItemHeaderValue(1, 2));

            Assert.Equal(range1.GetHashCode(), range2.GetHashCode());
            Assert.NotEqual(range1.GetHashCode(), range3.GetHashCode());
            Assert.NotEqual(range1.GetHashCode(), range4.GetHashCode());
            Assert.NotEqual(range1.GetHashCode(), range5.GetHashCode());
            Assert.Equal(range5.GetHashCode(), range6.GetHashCode());
        }
Пример #20
0
        public void Equals_UseSameAndDifferentRanges_EqualOrNotEqualNoExceptions()
        {
            RangeHeaderValue range1 = new RangeHeaderValue(1, 2);
            RangeHeaderValue range2 = new RangeHeaderValue(1, 2);
            range2.Unit = "BYTES";
            RangeHeaderValue range3 = new RangeHeaderValue(1, null);
            RangeHeaderValue range4 = new RangeHeaderValue(null, 2);
            RangeHeaderValue range5 = new RangeHeaderValue();
            range5.Ranges.Add(new RangeItemHeaderValue(1, 2));
            range5.Ranges.Add(new RangeItemHeaderValue(3, 4));
            RangeHeaderValue range6 = new RangeHeaderValue();
            range6.Ranges.Add(new RangeItemHeaderValue(3, 4)); // reverse order of range5
            range6.Ranges.Add(new RangeItemHeaderValue(1, 2));
            RangeHeaderValue range7 = new RangeHeaderValue(1, 2);
            range7.Unit = "other";

            Assert.False(range1.Equals(null), "bytes=1-2 vs. <null>");
            Assert.True(range1.Equals(range2), "bytes=1-2 vs. BYTES=1-2");
            Assert.False(range1.Equals(range3), "bytes=1-2 vs. bytes=1-");
            Assert.False(range1.Equals(range4), "bytes=1-2 vs. bytes=-2");
            Assert.False(range1.Equals(range5), "bytes=1-2 vs. bytes=1-2,3-4");
            Assert.True(range5.Equals(range6), "bytes=1-2,3-4 vs. bytes=3-4,1-2");
            Assert.False(range1.Equals(range7), "bytes=1-2 vs. other=1-2");
        }
Пример #21
0
        public void Clone_Call_CloneFieldsMatchSourceFields()
        {
            RangeHeaderValue source = new RangeHeaderValue(1, 2);
            RangeHeaderValue clone = (RangeHeaderValue)((ICloneable)source).Clone();

            Assert.Equal(1, source.Ranges.Count);
            Assert.Equal(source.Unit, clone.Unit);
            Assert.Equal(source.Ranges.Count, clone.Ranges.Count);
            Assert.Equal(source.Ranges.ElementAt(0), clone.Ranges.ElementAt(0));

            source.Unit = "custom";
            source.Ranges.Add(new RangeItemHeaderValue(3, null));
            source.Ranges.Add(new RangeItemHeaderValue(null, 4));
            clone = (RangeHeaderValue)((ICloneable)source).Clone();

            Assert.Equal(3, source.Ranges.Count);
            Assert.Equal(source.Unit, clone.Unit);
            Assert.Equal(source.Ranges.Count, clone.Ranges.Count);
            Assert.Equal(source.Ranges.ElementAt(0), clone.Ranges.ElementAt(0));
            Assert.Equal(source.Ranges.ElementAt(1), clone.Ranges.ElementAt(1));
            Assert.Equal(source.Ranges.ElementAt(2), clone.Ranges.ElementAt(2));
        }
Пример #22
0
		public void Properties ()
		{
			var value = new RangeHeaderValue (3, 9);
			Assert.AreEqual ("bytes", value.Unit, "#1");
			Assert.AreEqual (3, value.Ranges.First ().From, "#2");
			Assert.AreEqual (9, value.Ranges.First ().To, "#3");

			value = new RangeHeaderValue ();
			Assert.AreEqual ("bytes", value.Unit, "#4");
			Assert.AreEqual (0, value.Ranges.Count, "#5");
		}
Пример #23
0
		public void Properties_Invalid ()
		{
			var value = new RangeHeaderValue ();
			try {
				value.Unit = "";
				Assert.Fail ("#1");
			} catch (ArgumentException) {
			}
		}
Пример #24
0
        public static bool TryParse(string input, out RangeHeaderValue parsedValue)
        {
            parsedValue = null;

            var lexer = new Lexer(input);
            var t     = lexer.Scan();

            if (t != Token.Type.Token)
            {
                return(false);
            }

            var value = new RangeHeaderValue();

            value.unit = lexer.GetStringValue(t);

            t = lexer.Scan();
            if (t != Token.Type.SeparatorEqual)
            {
                return(false);
            }

            bool token_read;

            do
            {
                int?from = null, to = null;
                int number;
                token_read = false;

                t = lexer.Scan();
                switch (t.Kind)
                {
                case Token.Type.SeparatorDash:
                    t = lexer.Scan();
                    if (!lexer.TryGetNumericValue(t, out number))
                    {
                        return(false);
                    }

                    to = number;
                    break;

                case Token.Type.Token:
                    string s      = lexer.GetStringValue(t);
                    var    values = s.Split(new [] { '-' }, StringSplitOptions.RemoveEmptyEntries);
                    if (!int.TryParse(values[0], out number))
                    {
                        return(false);
                    }

                    switch (values.Length)
                    {
                    case 1:
                        t    = lexer.Scan();
                        from = number;
                        switch (t.Kind)
                        {
                        case Token.Type.SeparatorDash:
                            t = lexer.Scan();
                            if (t != Token.Type.Token)
                            {
                                token_read = true;
                                break;
                            }

                            if (!lexer.TryGetNumericValue(t, out number))
                            {
                                return(false);
                            }

                            to = number;
                            if (to < from)
                            {
                                return(false);
                            }

                            break;

                        case Token.Type.End:
                            if (s.Length > 0 && s [s.Length - 1] != '-')
                            {
                                return(false);
                            }

                            token_read = true;
                            break;

                        case Token.Type.SeparatorComma:
                            token_read = true;
                            break;

                        default:
                            return(false);
                        }
                        break;

                    case 2:
                        from = number;

                        if (!int.TryParse(values[1], out number))
                        {
                            return(false);
                        }

                        to = number;
                        if (to < from)
                        {
                            return(false);
                        }

                        break;

                    default:
                        return(false);
                    }

                    break;

                default:
                    return(false);
                }

                value.Ranges.Add(new RangeItemHeaderValue(from, to));
                if (!token_read)
                {
                    t = lexer.Scan();
                }
            } while (t == Token.Type.SeparatorComma);

            if (t != Token.Type.End)
            {
                return(false);
            }

            parsedValue = value;
            return(true);
        }
Пример #25
0
 private static void CallGetRangeLength(string input, int startIndex, int expectedLength,
     out RangeHeaderValue result)
 {
     object temp = null;
     Assert.Equal(expectedLength, RangeHeaderValue.GetRangeLength(input, startIndex, out temp));
     result = temp as RangeHeaderValue;
 }
Пример #26
0
		public static bool TryParse (string input, out RangeHeaderValue parsedValue)
		{
			parsedValue = null;

			var lexer = new Lexer (input);
			var t = lexer.Scan ();
			if (t != Token.Type.Token)
				return false;

			var value = new RangeHeaderValue ();
			value.unit = lexer.GetStringValue (t);

			t = lexer.Scan ();
			if (t != Token.Type.SeparatorEqual)
				return false;

			bool token_read;
			do {
				int? from = null, to = null;
				int number;
				token_read = false;

				t = lexer.Scan ();
				switch (t.Kind) {
				case Token.Type.SeparatorDash:
					t = lexer.Scan ();
					if (!lexer.TryGetNumericValue (t, out number))
						return false;

					to = number;
					break;
				case Token.Type.Token:
					string s = lexer.GetStringValue (t);
					var values = s.Split (new [] { '-' }, StringSplitOptions.RemoveEmptyEntries);
					if (!int.TryParse (values[0], out number))
						return false;

					switch (values.Length) {
					case 1:
						t = lexer.Scan ();
						switch (t.Kind) {
						case Token.Type.SeparatorDash:
							from = number;

							t = lexer.Scan ();
							if (t != Token.Type.Token) {
								token_read = true;
								break;
							}

							if (!lexer.TryGetNumericValue (t, out number))
								return false;

							to = number;
							if (to < from)
								return false;

							break;
						default:
							return false;
						}
						break;
					case 2:
						from = number;

						if (!int.TryParse (values[1], out number))
							return false;

						to = number;
						if (to < from)
							return false;

						break;
					default:
						return false;
					}

					break;
				default:
					return false;
				}

				value.Ranges.Add (new RangeItemHeaderValue (from, to));
				if (!token_read)
					t = lexer.Scan ();

			} while (t == Token.Type.SeparatorComma);

			if (t != Token.Type.End)
				return false;

			parsedValue = value;
			return true;
		}
Пример #27
0
        public void Range_ReadAndWriteProperty_ValueMatchesPriorSetValue()
        {
            Assert.Null(headers.Range);
            RangeHeaderValue value = new RangeHeaderValue(1, 2);

            headers.Range = value;
            Assert.Equal(value, headers.Range);

            headers.Range = null;
            Assert.Null(headers.Range);
        }
Пример #28
0
        public static bool TryParse(string input, out RangeHeaderValue parsedValue)
        {
            int index = 0;
            object output;
            parsedValue = null;

            if (GenericHeaderParser.RangeParser.TryParseValue(input, null, ref index, out output))
            {
                parsedValue = (RangeHeaderValue)output;
                return true;
            }
            return false;
        }
        /// <summary>
        /// Runs an HttpClient issuing sample requests against controller using Range requests.
        /// </summary>
        static void RunClient()
        {
            HttpClient client = new HttpClient();
            client.BaseAddress = new Uri(_baseAddress, "/api/range");

            // Get the full content without any ranges
            using (HttpResponseMessage response = client.GetAsync("").Result)
            {
                response.EnsureSuccessStatusCode();
                string content = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine("Full Content without ranges: '{0}'\n", content);
            }

            // Get the first byte 
            HttpRequestMessage firstByteRequest = new HttpRequestMessage();
            firstByteRequest.Headers.Range = new RangeHeaderValue(0, 0);
            using (HttpResponseMessage response = client.SendAsync(firstByteRequest).Result)
            {
                response.EnsureSuccessStatusCode();
                string content = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine("Range '{0}' requesting the first byte: '{1}'\n", firstByteRequest.Headers.Range, content);
            }

            // Get the last byte 
            HttpRequestMessage lastByteRequest = new HttpRequestMessage();
            lastByteRequest.Headers.Range = new RangeHeaderValue(null, 1);
            using (HttpResponseMessage response = client.SendAsync(lastByteRequest).Result)
            {
                response.EnsureSuccessStatusCode();
                string content = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine("Range '{0}' requesting the last byte: '{1}'\n", lastByteRequest.Headers.Range, content);
            }

            // Get from byte 4 and up 
            HttpRequestMessage fourAndUpByteRequest = new HttpRequestMessage();
            fourAndUpByteRequest.Headers.Range = new RangeHeaderValue(4, null);
            using (HttpResponseMessage response = client.SendAsync(fourAndUpByteRequest).Result)
            {
                response.EnsureSuccessStatusCode();
                string content = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine("Range '{0}' requesting byte 4 and up: '{1}'\n", fourAndUpByteRequest.Headers.Range, content);
            }

            // Get the first and the last byte
            HttpRequestMessage firstAndLastByteRequest = new HttpRequestMessage();
            RangeHeaderValue firstAndLastByteRange = new RangeHeaderValue();
            firstAndLastByteRange.Ranges.Add(new RangeItemHeaderValue(0, 0));
            firstAndLastByteRange.Ranges.Add(new RangeItemHeaderValue(null, 1));
            firstAndLastByteRequest.Headers.Range = firstAndLastByteRange;
            using (HttpResponseMessage response = client.SendAsync(firstAndLastByteRequest).Result)
            {
                response.EnsureSuccessStatusCode();
                string content = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine("Range '{0}' requesting first and last byte:\n{1}\n", firstAndLastByteRange, content);
            }

            // Get the first, mid four, and the last byte
            HttpRequestMessage firstMidAndLastByteRequest = new HttpRequestMessage();
            RangeHeaderValue firstMidAndLastByteRange = new RangeHeaderValue();
            firstMidAndLastByteRange.Ranges.Add(new RangeItemHeaderValue(0, 0));
            firstMidAndLastByteRange.Ranges.Add(new RangeItemHeaderValue(12, 15));
            firstMidAndLastByteRange.Ranges.Add(new RangeItemHeaderValue(null, 1));
            firstMidAndLastByteRequest.Headers.Range = firstMidAndLastByteRange;
            using (HttpResponseMessage response = client.SendAsync(firstMidAndLastByteRequest).Result)
            {
                response.EnsureSuccessStatusCode();
                string content = response.Content.ReadAsStringAsync().Result;
                Console.WriteLine("Range '{0}' requesting first, mid four, and last byte:\n{1}\n", firstMidAndLastByteRange, content);
            }

            // Ask for a non-matching range (byte 100 and up)
            HttpRequestMessage nonMatchingByteRequest = new HttpRequestMessage();
            nonMatchingByteRequest.Headers.Range = new RangeHeaderValue(100, null);
            using (HttpResponseMessage response = client.SendAsync(nonMatchingByteRequest).Result)
            {
                Console.WriteLine("Range '{0}' resulted in status code '{1}' with Content-Range header '{2}'",
                    nonMatchingByteRequest.Headers.Range, response.StatusCode, response.Content.Headers.ContentRange);
            }
        }
Пример #30
0
			/// <summary>
			/// <see cref="HttpContent"/> implementation which provides a byte range view over a stream used to generate HTTP
			/// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend 
			/// of the selected resource represented by the <paramref name="content"/> parameter then an 
			/// <see cref="InvalidByteRangeException"/> is thrown indicating the valid Content-Range of the content. 
			/// </summary>
			/// <param name="content">The stream over which to generate a byte range view.</param>
			/// <param name="range">The range or ranges, typically obtained from the Range HTTP request header field.</param>
			/// <param name="mediaType">The media type of the content stream.</param>
			/// <param name="bufferSize">The buffer size used when copying the content stream.</param>
			public ByteRangeStreamContent(Stream content, RangeHeaderValue range, MediaTypeHeaderValue mediaType, int bufferSize)
			{

				try
				{
					// If we have more than one range then we use a multipart/byteranges content type as wrapper.
					// Otherwise we use a non-multipart response.
					if (range.Ranges.Count > 1)
					{
						// Create Multipart content and copy headers to this content
						MultipartContent rangeContent = new MultipartContent(ByteRangesContentSubtype);
						_byteRangeContent = rangeContent;

						foreach (RangeItemHeaderValue rangeValue in range.Ranges)
						{
							try
							{
								ByteRangeStream rangeStream = new ByteRangeStream(content, rangeValue);
								HttpContent rangeBodyPart = new StreamContent(rangeStream, bufferSize);
								rangeBodyPart.Headers.ContentType = mediaType;
								rangeBodyPart.Headers.ContentRange = rangeStream.ContentRange;
								rangeContent.Add(rangeBodyPart);
							}
							catch (ArgumentOutOfRangeException)
							{
								// We ignore range errors until we check that we have at least one valid range
							}
						}

						// If no overlapping ranges were found then stop
						if (!rangeContent.Any())
						{
							ContentRangeHeaderValue actualContentRange = new ContentRangeHeaderValue(content.Length);
							string msg = "ByteRangeStreamNoneOverlap";
							throw new InvalidByteRangeException(actualContentRange, msg);
						}
					}
					else if (range.Ranges.Count == 1)
					{
						try
						{
							ByteRangeStream rangeStream = new ByteRangeStream(content, range.Ranges.First());
							_byteRangeContent = new StreamContent(rangeStream, bufferSize);
							_byteRangeContent.Headers.ContentType = mediaType;
							_byteRangeContent.Headers.ContentRange = rangeStream.ContentRange;
						}
						catch (ArgumentOutOfRangeException)
						{
							ContentRangeHeaderValue actualContentRange = new ContentRangeHeaderValue(content.Length);
							string msg = "ByteRangeStreamNoOverlap";
							throw new InvalidByteRangeException(actualContentRange, msg);
						}
					}
					else
					{
						throw new ArgumentException("range");
					}

					// Copy headers from byte range content so that we get the right content type etc.
					_byteRangeContent.Headers.CopyTo(Headers);

					_content = content;
					_start = content.Position;
				}
				catch
				{
					if (_byteRangeContent != null)
					{
						_byteRangeContent.Dispose();
					}
					throw;
				}
			}
Пример #31
0
			/// <summary>
			/// <see cref="HttpContent"/> implementation which provides a byte range view over a stream used to generate HTTP
			/// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend 
			/// of the selected resource represented by the <paramref name="content"/> parameter then an 
			/// <see cref="InvalidByteRangeException"/> is thrown indicating the valid Content-Range of the content. 
			/// </summary>
			/// <param name="content">The stream over which to generate a byte range view.</param>
			/// <param name="range">The range or ranges, typically obtained from the Range HTTP request header field.</param>
			/// <param name="mediaType">The media type of the content stream.</param>
			public ByteRangeStreamContent(Stream content, RangeHeaderValue range, MediaTypeHeaderValue mediaType)
				: this(content, range, mediaType, DefaultBufferSize)
			{
			}
Пример #32
0
			/// <summary>
			/// <see cref="HttpContent"/> implementation which provides a byte range view over a stream used to generate HTTP
			/// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend 
			/// of the selected resource represented by the <paramref name="content"/> parameter then an 
			/// <see cref="InvalidByteRangeException"/> is thrown indicating the valid Content-Range of the content. 
			/// </summary>
			/// <param name="content">The stream over which to generate a byte range view.</param>
			/// <param name="range">The range or ranges, typically obtained from the Range HTTP request header field.</param>
			/// <param name="mediaType">The media type of the content stream.</param>
			/// <param name="bufferSize">The buffer size used when copying the content stream.</param>
			public ByteRangeStreamContent(Stream content, RangeHeaderValue range, string mediaType, int bufferSize)
				: this(content, range, new MediaTypeHeaderValue(mediaType), bufferSize)
			{
			}
Пример #33
0
 private void CheckValidTryParse(string input, RangeHeaderValue expectedResult)
 {
     RangeHeaderValue result = null;
     Assert.True(RangeHeaderValue.TryParse(input, out result));
     Assert.Equal(expectedResult, result);
 }
Пример #34
0
 public static bool TryParse(string input, out RangeHeaderValue parsedValue)
 {
     throw new NotImplementedException();
 }
Пример #35
0
 private RangeItemHeaderValue GetRange(string rangeHeader)
 {
     return(RangeHeaderValue.Parse(rangeHeader).Ranges.FirstOrDefault());
 }
Пример #36
0
 public static bool TryParse(string input, out RangeHeaderValue parsedValue)
 {
 }
Пример #37
0
 private void CheckValidParse(string input, RangeHeaderValue expectedResult)
 {
     RangeHeaderValue result = RangeHeaderValue.Parse(input);
     Assert.Equal(expectedResult, result);
 }
Пример #38
0
        public void Range_UseAddMethod_AddedValueCanBeRetrievedUsingProperty()
        {
            headers.TryAddWithoutValidation("Range", "custom= , ,1-2, -4 , ");

            RangeHeaderValue value = new RangeHeaderValue();
            value.Unit = "custom";
            value.Ranges.Add(new RangeItemHeaderValue(1, 2));
            value.Ranges.Add(new RangeItemHeaderValue(null, 4));

            Assert.Equal(value, headers.Range);
        }
        /// <summary>
        /// 依傳入的標頭回傳一個ResponseMessage
        /// 正常來說直接回應給瀏覽器就可以了
        /// this will return a ResponseMessage object
        /// and response to web browser general.
        /// </summary>
        /// <param name="rangeHeader">ApiController's property: Request.Headers.Range</param>
        /// <param name="fileName">video file name, it was getting from request's query string general</param>
        /// <returns>HttpResponseMessage</returns>
        public HttpResponseMessage CreateHttpResponseMessage(RangeHeaderValue rangeHeader, string fileName)
        {
            HttpResponseMessage response = new HttpResponseMessage();

            // This can prevent some unnecessary accesses.
            // These kind of file names won't be existing at all.
            if (string.IsNullOrWhiteSpace(fileName) || AnyInvalidFileNameChars(fileName))
                throw new HttpResponseException(HttpStatusCode.NotFound);

            FileInfo fileInfo = new FileInfo(Path.Combine(InitialDirectory, fileName));

            if (!fileInfo.Exists)
                throw new HttpResponseException(HttpStatusCode.NotFound);

            long totalLength = fileInfo.Length;

            response.Headers.AcceptRanges.Add("bytes");

            // The request will be treated as normal request if there is no Range header.
            if (rangeHeader == null || !rangeHeader.Ranges.Any())
            {
                response.StatusCode = HttpStatusCode.OK;
                response.Content = new PushStreamContent((outputStream, httpContent, transpContext)
                =>
                {
                    using (outputStream) // Copy the file to output stream straightforward.
                    using (Stream inputStream = fileInfo.OpenRead())
                    {
                        try
                        {
                            inputStream.CopyTo(outputStream, ReadStreamBufferSize);
                        }
                        catch (Exception error)
                        {
                            Console.WriteLine(error);
                        }
                    }
                }, GetMimeNameFromExt(fileInfo.Extension));

                response.Content.Headers.ContentLength = totalLength;
                return response;
            }

            long start = 0, end = 0;

            // 1. If the unit is not 'bytes'.
            // 2. If there are multiple ranges in header value.
            // 3. If start or end position is greater than file length.
            if (rangeHeader.Unit != "bytes" || rangeHeader.Ranges.Count > 1 ||
                !TryReadRangeItem(rangeHeader.Ranges.First(), totalLength, out start, out end))
            {
                response.StatusCode = HttpStatusCode.RequestedRangeNotSatisfiable;
                response.Content = new StreamContent(Stream.Null);  // No content for this status.
                response.Content.Headers.ContentRange = new ContentRangeHeaderValue(totalLength);
                response.Content.Headers.ContentType = GetMimeNameFromExt(fileInfo.Extension);

                return response;
            }

            var contentRange = new ContentRangeHeaderValue(start, end, totalLength);

            // We are now ready to produce partial content.
            response.StatusCode = HttpStatusCode.PartialContent;
            response.Content = new PushStreamContent((outputStream, httpContent, transpContext)
            =>
            {
                using (outputStream) // Copy the file to output stream in indicated range.
                using (Stream inputStream = fileInfo.OpenRead())
                    CreatePartialContent(inputStream, outputStream, start, end);

            }, GetMimeNameFromExt(fileInfo.Extension));

            response.Content.Headers.ContentLength = end - start + 1;
            response.Content.Headers.ContentRange = contentRange;

            return response;
        }
Пример #40
0
        internal static int GetRangeLength(string input, int startIndex, out object parsedValue)
        {
            Debug.Assert(startIndex >= 0);

            parsedValue = null;

            if (string.IsNullOrEmpty(input) || (startIndex >= input.Length))
            {
                return 0;
            }

            // Parse the unit string: <unit> in '<unit>=<from1>-<to1>, <from2>-<to2>'
            int unitLength = HttpRuleParser.GetTokenLength(input, startIndex);

            if (unitLength == 0)
            {
                return 0;
            }

            RangeHeaderValue result = new RangeHeaderValue();
            result._unit = input.Substring(startIndex, unitLength);
            int current = startIndex + unitLength;
            current = current + HttpRuleParser.GetWhitespaceLength(input, current);

            if ((current == input.Length) || (input[current] != '='))
            {
                return 0;
            }

            current++; // skip '=' separator
            current = current + HttpRuleParser.GetWhitespaceLength(input, current);

            int rangesLength = RangeItemHeaderValue.GetRangeItemListLength(input, current, result.Ranges);

            if (rangesLength == 0)
            {
                return 0;
            }

            current = current + rangesLength;
            Debug.Assert(current == input.Length, "GetRangeItemListLength() should consume the whole string or fail.");

            parsedValue = result;
            return current - startIndex;
        }
Пример #41
0
        /// <summary>
        /// <see cref="HttpContent"/> implementation which provides a byte range view over a stream used to generate HTTP
        /// 206 (Partial Content) byte range responses. If none of the requested ranges overlap with the current extend 
        /// of the selected resource represented by the <paramref name="content"/> parameter then an 
        /// <see cref="InvalidByteRangeException"/> is thrown indicating the valid Content-Range of the content. 
        /// </summary>
        /// <param name="content">The stream over which to generate a byte range view.</param>
        /// <param name="range">The range or ranges, typically obtained from the Range HTTP request header field.</param>
        /// <param name="mediaType">The media type of the content stream.</param>
        /// <param name="bufferSize">The buffer size used when copying the content stream.</param>
        public ByteRangeStreamContent(Stream content, RangeHeaderValue range, MediaTypeHeaderValue mediaType, int bufferSize)
        {
            if (content == null)
            {
                throw new ArgumentNullException("content");
            }
            if (!content.CanSeek)
            {
                throw new ArgumentException("content", RS.Format(Resources.ByteRangeStreamNotSeekable, typeof(ByteRangeStreamContent).Name));
            }
            if (range == null)
            {
                throw new ArgumentNullException("range");
            }
            if (mediaType == null)
            {
                throw new ArgumentNullException("mediaType");
            }
            if (bufferSize < MinBufferSize)
            {
                throw new ArgumentOutOfRangeException("bufferSize", bufferSize, RS.Format(Resources.ArgumentMustBeGreaterThanOrEqualTo, MinBufferSize));
            }
            if (!range.Unit.Equals(SupportedRangeUnit, StringComparison.OrdinalIgnoreCase))
            {
                throw new ArgumentException(RS.Format(Resources.ByteRangeStreamContentNotBytesRange, range.Unit, SupportedRangeUnit), "range");
            }

            try
            {
                // If we have more than one range then we use a multipart/byteranges content type as wrapper.
                // Otherwise we use a non-multipart response.
                if (range.Ranges.Count > 1)
                {
                    // Create Multipart content and copy headers to this content
                    MultipartContent rangeContent = new MultipartContent(ByteRangesContentSubtype);
                    _byteRangeContent = rangeContent;

                    foreach (RangeItemHeaderValue rangeValue in range.Ranges)
                    {
                        try
                        {
                            ByteRangeStream rangeStream = new ByteRangeStream(content, rangeValue);
                            HttpContent rangeBodyPart = new StreamContent(rangeStream, bufferSize);
                            rangeBodyPart.Headers.ContentType = mediaType;
                            rangeBodyPart.Headers.ContentRange = rangeStream.ContentRange;
                            rangeContent.Add(rangeBodyPart);
                        }
                        catch (ArgumentOutOfRangeException)
                        {
                            // We ignore range errors until we check that we have at least one valid range
                        }
                    }

                    // If no overlapping ranges were found then stop
                    if (!rangeContent.Any())
                    {
                        ContentRangeHeaderValue actualContentRange = new ContentRangeHeaderValue(content.Length);
                        string msg = RS.Format(Resources.ByteRangeStreamNoneOverlap, range.ToString());
                        throw new InvalidByteRangeException(actualContentRange, msg);
                    }
                }
                else if (range.Ranges.Count == 1)
                {
                    try
                    {
                        ByteRangeStream rangeStream = new ByteRangeStream(content, range.Ranges.First());
                        _byteRangeContent = new StreamContent(rangeStream, bufferSize);
                        _byteRangeContent.Headers.ContentType = mediaType;
                        _byteRangeContent.Headers.ContentRange = rangeStream.ContentRange;
                    }
                    catch (ArgumentOutOfRangeException)
                    {
                        ContentRangeHeaderValue actualContentRange = new ContentRangeHeaderValue(content.Length);
                        string msg = RS.Format(Resources.ByteRangeStreamNoOverlap, range.ToString());
                        throw new InvalidByteRangeException(actualContentRange, msg);
                    }
                }
                else
                {
                    throw new ArgumentException(Resources.ByteRangeStreamContentNoRanges, "range");
                }

                // Copy headers from byte range content so that we get the right content type etc.
                foreach (KeyValuePair<string, IEnumerable<string>> header in _byteRangeContent.Headers)
                {
                    Headers.TryAddWithoutValidation(header.Key, header.Value);
                }

                _content = content;
                _start = content.Position;
            }
            catch
            {
                if (_byteRangeContent != null)
                {
                    _byteRangeContent.Dispose();
                }
                throw;
            }
        }