| 
									
										
										
										
											2019-03-11 13:41:55 +05:30
										 |  |  | import { Logger } from "./Logger"; | 
					
						
							|  |  |  | import { RangeParserError } from "./RangeParserError"; | 
					
						
							| 
									
										
										
										
											2019-03-11 13:49:38 +05:30
										 |  |  | import { Range } from "./Range"; | 
					
						
							| 
									
										
										
										
											2019-03-08 18:43:22 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | const rangeRegEx = /bytes=([0-9]*)-([0-9]*)/; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 13:41:55 +05:30
										 |  |  | export function parseRangeHeader(range: string, totalSize: number, logger: Logger): Range | null { | 
					
						
							|  |  |  |   logger.debug("Un-parsed range is: ", range); | 
					
						
							| 
									
										
										
										
											2019-03-08 18:43:22 +05:30
										 |  |  |   // 1. If range is not specified or the file is empty, return null.
 | 
					
						
							| 
									
										
										
										
											2019-03-11 13:41:55 +05:30
										 |  |  |   if (!range || range === null || range.length === 0 || totalSize === 0) { | 
					
						
							| 
									
										
										
										
											2019-03-08 18:43:22 +05:30
										 |  |  |     return null; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 13:41:55 +05:30
										 |  |  |   const splitRange = range.split(rangeRegEx); | 
					
						
							|  |  |  |   const [, startValue, endValue] = splitRange; | 
					
						
							| 
									
										
										
										
											2019-03-08 18:43:22 +05:30
										 |  |  |   let start = Number.parseInt(startValue); | 
					
						
							|  |  |  |   let end = Number.parseInt(endValue); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // 2. Parse start and end values and ensure they are within limits.
 | 
					
						
							|  |  |  |   // 2.1. start: >= 0.
 | 
					
						
							|  |  |  |   // 2.2. end: >= 0, <= totalSize - 1
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   let result = { | 
					
						
							|  |  |  |     start: Number.isNaN(start) ? 0 : Math.max(start, 0), | 
					
						
							|  |  |  |     end: Number.isNaN(end) ? totalSize - 1 : Math.min(Math.max(end, 0), totalSize - 1) | 
					
						
							|  |  |  |   }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // 3.1. If end is not provided, set end to the last byte (totalSize - 1).
 | 
					
						
							|  |  |  |   if (!Number.isNaN(start) && Number.isNaN(end)) { | 
					
						
							| 
									
										
										
										
											2019-03-11 13:41:55 +05:30
										 |  |  |     logger.debug("End is not provided."); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-08 18:43:22 +05:30
										 |  |  |     result.start = start; | 
					
						
							|  |  |  |     result.end = totalSize - 1; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // 3.2. If start is not provided, set it to the offset of last "end" bytes from the end of the file.
 | 
					
						
							|  |  |  |   //      And set end to the last byte.
 | 
					
						
							|  |  |  |   //      This way we return the last "end" bytes.
 | 
					
						
							|  |  |  |   if (Number.isNaN(start) && !Number.isNaN(end)) { | 
					
						
							| 
									
										
										
										
											2019-03-11 13:41:55 +05:30
										 |  |  |     logger.debug(`Start is not provided, "end" will be treated as last "end" bytes of the content.`); | 
					
						
							| 
									
										
										
										
											2019-03-08 18:43:22 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 13:41:55 +05:30
										 |  |  |     result.start = Math.max(totalSize - end, 0); | 
					
						
							|  |  |  |     result.end = totalSize - 1; | 
					
						
							| 
									
										
										
										
											2019-03-08 18:43:22 +05:30
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // 4. Handle invalid ranges.
 | 
					
						
							| 
									
										
										
										
											2019-03-11 13:41:55 +05:30
										 |  |  |   if (start < 0 || start > end || end > totalSize) { | 
					
						
							| 
									
										
										
										
											2019-03-08 18:43:22 +05:30
										 |  |  |     throw new RangeParserError(start, end); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 13:41:55 +05:30
										 |  |  |   logRange(logger, result); | 
					
						
							| 
									
										
										
										
											2019-03-08 18:43:22 +05:30
										 |  |  |   return result; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-03-11 13:41:55 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | function logRange(logger: Logger, range: Range) { | 
					
						
							|  |  |  |   logger.debug("Range is: ", JSON.stringify(range)); | 
					
						
							|  |  |  | } |