rstreamor 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b2917bc3f4ceb7e49d8bf2ce9a8a8a784800261e
4
+ data.tar.gz: bdaab2583015a8f27ccf380153131fd63292e19c
5
+ SHA512:
6
+ metadata.gz: 68af7208404956aa3790a5b348b2b1c64cb3110e8b1c4c0b56f3777b08166a1fb135a091669d87215b1e48b55fb8229c24fce12552a997d4decb7c7836bf9d61
7
+ data.tar.gz: 125a769788b7ce6018e6088aca988dc83df98d3a3045c4aca94f08aed404b9751ef7f7d3651af02f0fa9eae89f3c61873cf4a9750f462c7f7d95d3eeaba1e4ac
data/.gitignore ADDED
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ .idea
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2.0
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rstreamor.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # Rstreamor
2
+ Development in progress...
3
+
4
+ # Get Rstreamor
5
+ ###### Directly from GitHub
6
+ ```ruby
7
+ gem 'regressor', git: 'https://github.com/ndea/rstreamor.git', branch: 'master'
8
+ ```
9
+ ###### Rubygems
10
+ # Install
11
+ ```ruby
12
+ bundle install
13
+ ```
14
+ # Usage
15
+ Given you have a controller with a streaming action (here it's the show action) simply use following code:
16
+ ```ruby
17
+ class VideosController < ApplicationController
18
+ include Rstreamor
19
+ def show
20
+ stream @resource.file
21
+ end
22
+ end
23
+ ```
24
+ Please note that the file method of @resource is a mounted uploader of carrierwave.
25
+
26
+ Rstreamor takes care of the rest.
27
+ If you dont use Carrierwave as a file make sure your file has the following methods:
28
+ - #data
29
+ - #content_type
30
+
31
+ # What is a range request?
32
+ Byte serving is the process of sending only a portion of an HTTP/1.1 message from a server to a client. Byte serving begins when an HTTP server advertises its willingness to serve partial requests using the Accept-Ranges response header. A client then requests a specific part of a file from the server using the Range request header. If the range is valid, the server sends it to the client with a 206 Partial Content status code and a Content-Range header listing the range sent. Clients which request byte-serving might do so in cases in which a large file has been only partially delivered and a limited portion of the file is needed in a particular range. Byte Serving is therefore a method of bandwidth optimization. [Wikipedia](https://en.wikipedia.org/wiki/Byte_serving)
33
+
34
+ ### HTML5 video / audio streaming
35
+ Consider you have a large video or audio file on your server which needs to be served partially to your client. You don't want to send the whole file in one response (unless you want to download the file). Instead the client needs only partial content which he can view and request other partial content if needed. Rstreamor provides this byte serving mechanism defined in HTTP/1.1.
36
+
37
+ ###### Example
38
+ ###### Limitations
39
+ # Contributing
40
+
41
+ 1. Fork it ( https://github.com/ndea/regressor/fork )
42
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
43
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
44
+ 4. Push to the branch (`git push origin my-new-feature`)
45
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "rstreamor"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
data/bin/setup ADDED
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
data/lib/rstreamor.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'rstreamor/version'
2
+ require 'rstreamor/file'
3
+ require 'rstreamor/request'
4
+ require 'rstreamor/response'
5
+ require 'rstreamor/stream'
6
+ module Rstreamor
7
+ include Rstreamor::Stream
8
+ end
@@ -0,0 +1,22 @@
1
+ module Rstreamor
2
+ class File
3
+ attr_accessor :file
4
+
5
+ def initialize(file)
6
+ self.file = file
7
+ end
8
+
9
+ def data
10
+ self.file.data
11
+ end
12
+
13
+ def content_type
14
+ self.file.content_type
15
+ end
16
+
17
+ def size
18
+ data.size
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,39 @@
1
+ module Rstreamor
2
+ class Request
3
+ attr_accessor :request, :file
4
+
5
+ def initialize(request, file)
6
+ self.request = request
7
+ self.file = file
8
+ end
9
+
10
+ def ranges
11
+ self.request.headers['HTTP_RANGE'].gsub('bytes=', '').split('-')
12
+ end
13
+
14
+ def upper_bound
15
+ ranges[1] ? ranges[1].to_i : self.file.data.size
16
+ end
17
+
18
+ def lower_bound
19
+ ranges[0] ? ranges[0].to_i : 0
20
+ end
21
+
22
+ def range_header?
23
+ self.request.headers['HTTP_RANGE'].present?
24
+ end
25
+
26
+ def file_content_type
27
+ self.file.content_type
28
+ end
29
+
30
+ def slice_file
31
+ self.file.data.byteslice(lower_bound, upper_bound)
32
+ end
33
+
34
+ def file_size
35
+ self.file.size
36
+ end
37
+
38
+ end
39
+ end
@@ -0,0 +1,34 @@
1
+ module Rstreamor
2
+ class Response
3
+ attr_accessor :request
4
+
5
+ def initialize(request)
6
+ self.request = request
7
+ end
8
+
9
+ def response_code
10
+ self.request.range_header? ? 206 : 200
11
+ end
12
+
13
+ def content_length
14
+ if self.request.range_header?
15
+ (self.request.upper_bound - self.request.lower_bound).to_s
16
+ else
17
+ self.request.file.data.size
18
+ end
19
+ end
20
+
21
+ def content_range
22
+ "bytes #{self.request.lower_bound}-#{self.request.upper_bound - 1}/#{self.request.file.data.size}"
23
+ end
24
+
25
+ def accept_ranges
26
+ 'bytes'
27
+ end
28
+
29
+ def cache_control
30
+ 'no-cache'
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,27 @@
1
+ module Rstreamor
2
+ module Stream
3
+ def stream(file)
4
+ request_builder = Rstreamor::Request.new(request, file)
5
+ response_builder = Rstreamor::Response.new(request_builder)
6
+ set_response_header(request_builder, response_builder)
7
+ stream_file(request_builder, response_builder)
8
+ end
9
+
10
+ private
11
+
12
+ def stream_file(request_builder, response_builder)
13
+ content = request_builder.slice_file
14
+ send_data content, type: request_builder.file_content_type, disposition: 'inline', status: response_builder.response_code
15
+ end
16
+
17
+ def set_response_header(request_builder, response_builder)
18
+ response.headers['Content-Type'] = request_builder.file_content_type
19
+ response.headers['Content-Length'] = response_builder.content_length
20
+ if request_builder.range_header?
21
+ response.headers['Accept-Ranges'] = 'bytes'
22
+ response.headers['Cache-Control'] = 'no-cache'
23
+ response.headers['Content-Range'] = response_builder.content_range
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,3 @@
1
+ module Rstreamor
2
+ VERSION = "0.2.0"
3
+ end
data/rstreamor.gemspec ADDED
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rstreamor/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'rstreamor'
8
+ spec.version = Rstreamor::VERSION
9
+ spec.authors = ['Erwin Schens']
10
+ spec.email = ['erwinschens@uni-koblenz.de']
11
+
12
+ spec.summary = %q{Stream files using HTTP range requests.}
13
+ spec.description = %q{
14
+ Rstreamor gives you the power to stream your files using the HTTP range requests defined in the HTTP/1.1.
15
+ Range requests are an optional feature of HTTP,
16
+ designed so that recipients not implementing this feature
17
+ (or not supporting it for the target resource) can respond as if
18
+ it is a normal GET request without impacting interoperability.
19
+ Partial responses are indicated by a distinct status code to not be mistaken for full responses by caches that might not implement the feature.
20
+ }
21
+ spec.homepage = 'https://github.com/ndea/rstreamor'
22
+ spec.license = 'MIT'
23
+
24
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ spec.bindir = 'exe'
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ['lib']
28
+
29
+ spec.add_development_dependency 'bundler', '~> 1.8'
30
+ spec.add_development_dependency 'rake', '~> 10.0'
31
+ spec.add_development_dependency 'rspec', '~> 3.3.0'
32
+ end
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rstreamor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Erwin Schens
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-08-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.8'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.8'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 3.3.0
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 3.3.0
55
+ description: "\n Rstreamor gives you the power to stream your
56
+ files using the HTTP range requests defined in the HTTP/1.1.\n Range
57
+ requests are an optional feature of HTTP,\n designed so that
58
+ recipients not implementing this feature\n (or not supporting
59
+ it for the target resource) can respond as if\n it is a normal
60
+ GET request without impacting interoperability.\n Partial
61
+ responses are indicated by a distinct status code to not be mistaken for full responses
62
+ by caches that might not implement the feature.\n "
63
+ email:
64
+ - erwinschens@uni-koblenz.de
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - ".gitignore"
70
+ - ".rspec"
71
+ - ".travis.yml"
72
+ - Gemfile
73
+ - README.md
74
+ - Rakefile
75
+ - bin/console
76
+ - bin/setup
77
+ - lib/rstreamor.rb
78
+ - lib/rstreamor/file.rb
79
+ - lib/rstreamor/request.rb
80
+ - lib/rstreamor/response.rb
81
+ - lib/rstreamor/stream.rb
82
+ - lib/rstreamor/version.rb
83
+ - rstreamor.gemspec
84
+ homepage: https://github.com/ndea/rstreamor
85
+ licenses:
86
+ - MIT
87
+ metadata: {}
88
+ post_install_message:
89
+ rdoc_options: []
90
+ require_paths:
91
+ - lib
92
+ required_ruby_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ requirements: []
103
+ rubyforge_project:
104
+ rubygems_version: 2.4.6
105
+ signing_key:
106
+ specification_version: 4
107
+ summary: Stream files using HTTP range requests.
108
+ test_files: []