I am trying to create a controller method that serves a video file supported by some database record similar to CMS. My controller method is as follows:
def getVideo(id: Int) = DBAction { request => implicit dbSession => { for { dbFile <- fetchDBFile(id) fsFile <- fetchFilesystemFile(dbFile) rangeOpt <- request.headers.get(RANGE).map(_.replaceAll("bytes=", "").split("-").toList match { case rangeStart :: rangeEnd :: Nil => Some(rangeStart.toLong, rangeEnd.toLong) case rangeStart :: Nil => Some(rangeStart.toLong, fsFile.length()) case _ => None }) (rangeStart, rangeEnd) <- rangeOpt } yield SimpleResult( header = ResponseHeader( status = PARTIAL_CONTENT, headers = Map( CONTENT_TYPE -> MimeTypes.forExtension("mp4").get, ACCEPT_RANGES -> "bytes", DATE -> new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz").format(new Date()), CONTENT_LENGTH -> fsFile.length.toString, CONTENT_RANGE -> s"bytes $rangeStart-$rangeEnd/${fsFile.length}", CONNECTION -> "keep-alive" ) ), body = Enumerator.fromStream(new FileInputStream(fsFile)) ) } getOrElse { NotFound } }
It is mainly based on two sources for implementing logic to handle a specific request for the range of bytes needed to serve the video.
When using Chrome or Safari on OS X to access this controller method, the developer tools report that the request is canceled - no response was received, be it 200 or 404. I confirmed that SimpleResponse actually returns this controller action for requests that I expect that he will give a good answer, but either Play will not complete the answer, or my browsers will not confirm it. Am I doing something wrong here in response, or am I stumbled upon a mistake in the framework?
My version of the game is 2.1.3.
source share