web_package 0.0.0 → 0.1.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 +5 -5
- data/.rubocop.yml +24 -21
- data/README.md +109 -0
- data/lib/web_package/cbor.rb +3 -1
- data/lib/web_package/helpers.rb +3 -0
- data/lib/web_package/inner_response.rb +24 -0
- data/lib/web_package/mice.rb +4 -1
- data/lib/web_package/middleware.rb +48 -0
- data/lib/web_package/signed_http_exchange.rb +22 -25
- data/lib/web_package/signer.rb +6 -4
- data/lib/web_package/version.rb +1 -1
- data/lib/web_package.rb +6 -3
- data/web_package.gemspec +2 -1
- metadata +20 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3480112115fbe00503b06c0f2348ce71540476a2
|
4
|
+
data.tar.gz: 302a745b6299ed41ce24477ea0e97e2028f36f1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f246d62cead117fbd4e8f8da7ccba8efaa29ee22baeebf1d7aadcbf73fe26131d58640876810ee1c6676591538c07a23f8d2894daba08348b01ef9c10293efcc
|
7
|
+
data.tar.gz: 1e5f467edfb293b83b166bc1ce03d2bda57db2af45fdfd9d98ddcecff65aafb21edd879e38ef43999a5a9b81b0e8ae3959fbbc32eb8bfa7086cec5b0380b164f
|
data/.rubocop.yml
CHANGED
@@ -1,19 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
Naming/UncommunicativeMethodParamName:
|
6
|
-
AllowedNames:
|
7
|
-
- s
|
1
|
+
Layout/EmptyLineAfterGuardClause:
|
2
|
+
Exclude:
|
3
|
+
- lib/web_package/signed_http_exchange.rb
|
8
4
|
|
9
|
-
|
10
|
-
|
5
|
+
Layout/SpaceInsideRangeLiteral:
|
6
|
+
Exclude:
|
7
|
+
- lib/web_package/cbor.rb
|
11
8
|
|
12
|
-
|
9
|
+
Layout/ExtraSpacing:
|
13
10
|
Exclude:
|
14
11
|
- lib/web_package/cbor.rb
|
15
|
-
- lib/web_package/mice.rb
|
16
|
-
- lib/web_package/signed_http_exchange.rb
|
17
12
|
|
18
13
|
Metrics/AbcSize:
|
19
14
|
Max: 20
|
@@ -22,21 +17,29 @@ Metrics/AbcSize:
|
|
22
17
|
- lib/web_package/mice.rb
|
23
18
|
- lib/web_package/signed_http_exchange.rb
|
24
19
|
|
25
|
-
|
20
|
+
Metrics/ClassLength:
|
26
21
|
Exclude:
|
27
22
|
- lib/web_package/signed_http_exchange.rb
|
28
23
|
|
29
|
-
Metrics/
|
24
|
+
Metrics/LineLength:
|
25
|
+
Max: 100
|
26
|
+
IgnoreCopDirectives: true
|
27
|
+
|
28
|
+
Metrics/MethodLength:
|
30
29
|
Exclude:
|
30
|
+
- lib/web_package/cbor.rb
|
31
|
+
- lib/web_package/mice.rb
|
31
32
|
- lib/web_package/signed_http_exchange.rb
|
32
33
|
|
33
|
-
|
34
|
+
Naming/UncommunicativeMethodParamName:
|
35
|
+
AllowedNames:
|
36
|
+
- s
|
37
|
+
|
38
|
+
Style/CharacterLiteral:
|
34
39
|
Enabled: false
|
35
40
|
|
36
|
-
|
37
|
-
|
38
|
-
- lib/web_package/cbor.rb
|
41
|
+
Style/FrozenStringLiteralComment:
|
42
|
+
Enabled: false
|
39
43
|
|
40
|
-
|
41
|
-
|
42
|
-
- lib/web_package/cbor.rb
|
44
|
+
Style/RedundantReturn:
|
45
|
+
Enabled: false
|
data/README.md
CHANGED
@@ -1,2 +1,111 @@
|
|
1
1
|
# web_package
|
2
2
|
Ruby implementation of Signed HTTP Exchange format, allowing a browser to trust that a HTTP request-response pair was generated by the origin it claims.
|
3
|
+
|
4
|
+
|
5
|
+
## Ever thought of saving the Internet on a flash?
|
6
|
+
|
7
|
+
Easily-peasily.
|
8
|
+
|
9
|
+
Let's sign a pair of request/response and serve the bundle as `application/signed-exchange` - Chromium browsers understand what it means and unpack them smoothly.
|
10
|
+
|
11
|
+
For that we need a certificate with a special "CanSignHttpExchanges" extension, but for the purpose of this guide we will use just a self-signed one. Please refer [here](https://github.com/WICG/webpackage/tree/master/go/signedexchange#creating-our-first-signed-exchange) to create such.
|
12
|
+
|
13
|
+
Also we need an `https` cdn serving static certificate in `application/cert-chain+cbor` format. We can use `gen-certurl` tool from [here](https://github.com/WICG/webpackage/tree/master/go/signedexchange#creating-our-first-signed-exchange) to convert PEM certificate into this format, so we could than serve it from a cdn.
|
14
|
+
|
15
|
+
### Required environment variables
|
16
|
+
Having done the above-said we are now ready to assign required env vars:
|
17
|
+
```bash
|
18
|
+
export SXG_CERT_URL='https://my.cdn.com/cert.cbor' \
|
19
|
+
SXG_CERT_PATH='/local/path/to/cert.pem' \
|
20
|
+
SXG_PRIV_PATH='/local/path/to/priv.key'
|
21
|
+
```
|
22
|
+
Please note, that the variables are fetched during class initialization. And failing to provide valid paths will result in an exception.
|
23
|
+
|
24
|
+
### Use it as a middleware
|
25
|
+
|
26
|
+
`WebPackage::Middleware` can handle `.sxg`-format requests by wrapping the respective HTML contents into signed exchange response. For example the route `https://my.app.com/abc.sxg` will respond with signed contents for `https://my.app.com/abc`.
|
27
|
+
|
28
|
+
If you already have a Rack-based application (like Rails or Sinatra), than it is easy incorporate an SXG proxy into its middleware stack.
|
29
|
+
|
30
|
+
#### Rails
|
31
|
+
Add the gem to your `Gemfile`:
|
32
|
+
```ruby
|
33
|
+
gem 'web_package'
|
34
|
+
```
|
35
|
+
And then add the middleware:
|
36
|
+
```ruby
|
37
|
+
# config/application.rb
|
38
|
+
config.middleware.insert 0, 'WebPackage::Middleware'
|
39
|
+
```
|
40
|
+
|
41
|
+
That is it. Now all successful `.sxg` requests will be wrapped into signed exchanges.
|
42
|
+
|
43
|
+
#### Pure Rack app
|
44
|
+
Imagine we have a simple web app:
|
45
|
+
```ruby
|
46
|
+
# config.ru
|
47
|
+
run ->(env) { [200, {}, ['<h1>Hello world!</h1>']] }
|
48
|
+
```
|
49
|
+
Add the gem and the middleware:
|
50
|
+
```ruby
|
51
|
+
# Gemfile
|
52
|
+
gem 'web_package'
|
53
|
+
|
54
|
+
# config.ru
|
55
|
+
use WebPackage::Middleware
|
56
|
+
```
|
57
|
+
|
58
|
+
We are done. Start your app by running a command `rackup config.ru`. Now all supplimentary `.sxg` routes will be available just out of the box.<br>
|
59
|
+
As expected, visiting `http://localhost:9292/hello` will produce:
|
60
|
+
```html
|
61
|
+
<h1>Hello world!</h1>
|
62
|
+
```
|
63
|
+
What's more, visiting `http://localhost:9292/hello.sxg` will spit signed http exchange, containing original `<h1>Hello world!</h1>` HTML:
|
64
|
+
```text
|
65
|
+
sxg1-b3\x00\x00\x1Chttps://localhost:9292/hello\x00\x019\x00\x00?label;cert-sha256=*+DoXYlCX+bFRyW65R3bFA2ICIz8Tyu54MLFUFo5tziA=*;cert-url=\"https://my.cdn.com/cert.cbor\";date=1557657274;expires=1558262074;integrity=\"digest/mi-sha256-03\";sig=*MEUCIAKKz+KSuhlzywfU12h3SkEq5ZuYYMxDZIgEDGYMd9sAAiEAj66Il48eb0CXFAnuZhnS+j6dqZVLJ6IwUVGWShhQu9g=*;validity-url=\"https://localhost/hello\"?FdigestX9mi-sha256-03=4QeUScOpSoJl7KJ47F11rSDHUTHZhDVwLiSLOWMcvqg=G:statusC200Pcontent-encodingLmi-sha256-03Vx-content-type-optionsGnosniff\x00\x00\x00\x00\x00\x00@\x00<h1>Hello world!</h1>
|
66
|
+
```
|
67
|
+
|
68
|
+
### Use it as it is
|
69
|
+
```ruby
|
70
|
+
require 'web_package'
|
71
|
+
|
72
|
+
# this is the request/response pair
|
73
|
+
request_url = 'https://my.app.com/abc'
|
74
|
+
response = [200, {}, ['<h1>Hello world!</h1>']]
|
75
|
+
|
76
|
+
exchange = WebPackage::SignedHttpExchange.new(request_url, response)
|
77
|
+
|
78
|
+
exchange.headers
|
79
|
+
# => {"Content-Type"=>"application/signed-exchange;v=b3", "Cache-Control"=>"no-transform", "X-Content-Type-Options"=>"nosniff"}
|
80
|
+
|
81
|
+
exchange.body
|
82
|
+
# => "sxg1-b3\x00\x00\x16https://my.app.com/abc\x00\x018\x00\x00\x8Clabel;cert-sha256=*+DoXYlCX+bFRyW65R3bFA2ICIz8Tyu54MLFUFo5tziA=*;cert-url=\"https://my.cdn.com/cert.cbor\";date=1557648268;expires=1558253068;integrity=\"digest/mi-sha256-03\";sig=*MEYCIQDSH2F6E/naM/ul1iIMZMBd9VHnrbsxp+dKhYcxy9u1ewIhAIRIuHcTVPLS73q2ETLLGwY5Y7nR52bDG251uBBHxsBZ*;validity-url=\"https://my.app.com/abc\"\xA4FdigestX9mi-sha256-03=4QeUScOpSoJl7KJ47F11rSDHUTHZhDVwLiSLOWMcvqg=G:statusC200Pcontent-encodingLmi-sha256-03Vx-content-type-optionsGnosniff\x00\x00\x00\x00\x00\x00@\x00<h1>Hello world!</h1>"
|
83
|
+
```
|
84
|
+
|
85
|
+
The body can be stored on disk and served from any other server. That is, visiting e.g. `https://other.cdn.com/foo/bar.sxg` will result in <b>"Hello world!"</b> HTML with `https://my.app.com/abc` in a browser's address bar - with no requests sent to `https://my.app.com/abc` (until the page expired).
|
86
|
+
|
87
|
+
Successive reloads will force browser to factually send requests to `https://my.app.com/abc`.
|
88
|
+
|
89
|
+
Note also, that SXG is only supported by the anchor tag (`<a>`) and `link rel=prefetch`, so actually typing `https://other.cdn.com/foo/bar.sxg` into browser's address bar and hitting enter will just download an SXG file.
|
90
|
+
|
91
|
+
This all could be helpful to preload content or serve it from closer location. For details please refer to hands-on description of [Signed Http Exchanges](https://developers.google.com/web/updates/2018/11/signed-exchanges).
|
92
|
+
|
93
|
+
### Self-signed certificates in Chrome
|
94
|
+
Chrome will not proceed with a self-signed certificate - at least as long as its cbor representation is generated with dummy data for OCSP. To accomodate this, please launch the browser with the following flags:
|
95
|
+
```bash
|
96
|
+
chrome --user-data-dir=/tmp/udd\
|
97
|
+
--ignore-certificate-errors-spki-list=`openssl x509 -noout -pubkey -in cert.pem | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64`
|
98
|
+
```
|
99
|
+
|
100
|
+
Note, that the browser might spit a warning `You are using unsupported command-line flag: --ignore-certificate-errors-spki-list` - just ignore it - the browser does support this flag (tested in versions 73 and 74).
|
101
|
+
|
102
|
+
## Contributing
|
103
|
+
- Fork it
|
104
|
+
- Create your feature branch (git checkout -b my-new-feature)
|
105
|
+
- Commit your changes (git commit -am 'Add some feature')
|
106
|
+
- Push to the branch (git push origin my-new-feature)
|
107
|
+
- Create new Pull Request
|
108
|
+
|
109
|
+
## License
|
110
|
+
|
111
|
+
Web package is released under the [MIT License](../master/LICENSE).
|
data/lib/web_package/cbor.rb
CHANGED
@@ -24,7 +24,9 @@ module WebPackage
|
|
24
24
|
def generate_bytes(input)
|
25
25
|
case input
|
26
26
|
when Hash
|
27
|
-
input = input.
|
27
|
+
input = input.dup.tap do |hsh|
|
28
|
+
hsh.keys.each { |key| hsh[bin(key)] = hsh.delete(key) }
|
29
|
+
end
|
28
30
|
|
29
31
|
bytes = hsh_size(input)
|
30
32
|
bytes[0] |= major_type(5)
|
data/lib/web_package/helpers.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
module WebPackage
|
2
|
+
# This class is a convenience to represent an original response, later to be signed and packed.
|
3
|
+
class InnerResponse
|
4
|
+
attr_reader :status, :headers, :body, :payload
|
5
|
+
|
6
|
+
def initialize(status, headers, body)
|
7
|
+
@status = status
|
8
|
+
@headers = headers
|
9
|
+
@body = body
|
10
|
+
@payload = unrack_body
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def unrack_body
|
16
|
+
payload = nil
|
17
|
+
|
18
|
+
# Rack's body yields strings
|
19
|
+
@body.each { |str| payload ? (payload << str) : (payload = str) }
|
20
|
+
|
21
|
+
payload
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/web_package/mice.rb
CHANGED
@@ -10,7 +10,10 @@ module WebPackage
|
|
10
10
|
|
11
11
|
def initialize(headers, body)
|
12
12
|
@body = body.dup
|
13
|
-
@headers = headers.
|
13
|
+
@headers = headers.dup.tap do |hsh|
|
14
|
+
# only lowercase keys allowed
|
15
|
+
hsh.keys.each { |key| hsh[key.to_s.downcase] = hsh.delete(key) }
|
16
|
+
end
|
14
17
|
|
15
18
|
@encoded = false
|
16
19
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module WebPackage
|
2
|
+
SXG_EXT = '.sxg'.freeze
|
3
|
+
SXG_FLAG = 'web_package.sxg'.freeze
|
4
|
+
|
5
|
+
# A Rack-compatible middleware.
|
6
|
+
class Middleware
|
7
|
+
def initialize(app)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
env[SXG_FLAG] = true if sxg_delete!(env['PATH_INFO'])
|
13
|
+
|
14
|
+
response = @app.call(env)
|
15
|
+
return response unless response[0] == 200 && env[SXG_FLAG]
|
16
|
+
|
17
|
+
# the original body must be closed first
|
18
|
+
response[2].close if response[2].respond_to? :close
|
19
|
+
|
20
|
+
# substituting the original response with SXG
|
21
|
+
SignedHttpExchange.new(url(env), response).to_rack_response
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def sxg_delete!(path)
|
27
|
+
return unless path.is_a?(String) && (i = path.rindex(SXG_EXT))
|
28
|
+
|
29
|
+
# check that extension is either the last char or followed by a slash
|
30
|
+
ch = path[i + SXG_EXT.size]
|
31
|
+
return if ch && ch != ?/
|
32
|
+
|
33
|
+
path.slice! i, SXG_EXT.size
|
34
|
+
end
|
35
|
+
|
36
|
+
def url(env)
|
37
|
+
URI("https://#{env['HTTP_HOST'] || env['SERVER_NAME']}").tap do |u|
|
38
|
+
path = env['PATH_INFO']
|
39
|
+
port = env['SERVER_PORT']
|
40
|
+
query = env['QUERY_STRING']
|
41
|
+
|
42
|
+
u.path = path
|
43
|
+
u.port = port if !u.port && port != '80'
|
44
|
+
u.query = query if query && !query.empty?
|
45
|
+
end.to_s
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -5,8 +5,6 @@ module WebPackage
|
|
5
5
|
# SXG format allows a browser to trust that a single HTTP request/response pair was
|
6
6
|
# generated by the origin it claims.
|
7
7
|
#
|
8
|
-
# Accetps two arguments: response url and response object (with body, headers and status).
|
9
|
-
# Provides two public methods to build HTTP response in SXG format: headers and body.
|
10
8
|
# Current implementation is lazy, meaning that signing is performed upon the
|
11
9
|
# invocation of the `body` method.
|
12
10
|
class SignedHttpExchange
|
@@ -17,25 +15,25 @@ module WebPackage
|
|
17
15
|
'Cache-Control' => 'no-transform',
|
18
16
|
'X-Content-Type-Options' => 'nosniff'
|
19
17
|
}.freeze
|
20
|
-
CERT_URL = ENV
|
21
|
-
CERT_PATH = ENV
|
22
|
-
PRIV_PATH = ENV
|
18
|
+
CERT_URL = ENV.fetch 'SXG_CERT_URL'
|
19
|
+
CERT_PATH = ENV.fetch 'SXG_CERT_PATH'
|
20
|
+
PRIV_PATH = ENV.fetch 'SXG_PRIV_PATH'
|
23
21
|
INTEGRITY = 'digest/mi-sha256-03'.freeze
|
24
22
|
|
25
23
|
# Mock request-response pair just in case:
|
26
24
|
MOCK_URL = 'https://example.com/wow-fake-path'.freeze
|
27
|
-
|
28
|
-
MOCK_RESP = Response['<h1>Hello!</h1>', { 'Content-Type' => 'text/html; charset=utf-8' }, 200]
|
25
|
+
MOCK_RESP = [200, { 'Content-Type' => 'text/html; charset=utf-8' }, ['<h1>Hello!</h1>']].freeze
|
29
26
|
|
30
|
-
|
31
|
-
|
32
|
-
#
|
27
|
+
# Accepts two args representing a request-response pair:
|
28
|
+
# url - request url (string)
|
29
|
+
# response - an array, equivalent to Rack's one: [status_code, headers, body]
|
33
30
|
def initialize(url = MOCK_URL, response = MOCK_RESP)
|
34
31
|
@uri = build_uri_from url
|
35
|
-
@
|
32
|
+
@url = @uri.to_s
|
33
|
+
@inner = InnerResponse.new(*response)
|
36
34
|
|
37
35
|
@cbor = CBOR.new
|
38
|
-
@mice = MICE.new(@
|
36
|
+
@mice = MICE.new(@inner.headers, @inner.payload).tap(&:encode!)
|
39
37
|
@signer = Signer.new CERT_PATH, PRIV_PATH
|
40
38
|
end
|
41
39
|
|
@@ -57,11 +55,11 @@ module WebPackage
|
|
57
55
|
@body << "sxg1-b3\x00"
|
58
56
|
|
59
57
|
# 2. 2 bytes storing a big-endian integer "fallbackUrlLength".
|
60
|
-
@body << [
|
58
|
+
@body << [@url.bytesize].pack('S>')
|
61
59
|
|
62
60
|
# 3. "fallbackUrlLength" bytes holding a "fallbackUrl", which MUST be
|
63
61
|
# an absolute URL with a scheme of "https".
|
64
|
-
@body <<
|
62
|
+
@body << @url
|
65
63
|
|
66
64
|
# 4. 3 bytes storing a big-endian integer "sigLength". If this is
|
67
65
|
# larger than 16384 (16*1024), parsing MUST fail.
|
@@ -100,6 +98,10 @@ module WebPackage
|
|
100
98
|
@body << @mice.body
|
101
99
|
end
|
102
100
|
|
101
|
+
def to_rack_response
|
102
|
+
[200, headers, [body]]
|
103
|
+
end
|
104
|
+
|
103
105
|
private
|
104
106
|
|
105
107
|
def message
|
@@ -152,8 +154,8 @@ module WebPackage
|
|
152
154
|
|
153
155
|
# 8. The 8-byte big-endian encoding of the length in bytes of
|
154
156
|
# "requestUrl", followed by the bytes of "requestUrl".
|
155
|
-
@message << [url.bytesize].pack('Q>')
|
156
|
-
@message << url
|
157
|
+
@message << [@url.bytesize].pack('Q>')
|
158
|
+
@message << @url
|
157
159
|
|
158
160
|
# 9. The 8-byte big-endian encoding of the length in bytes of
|
159
161
|
# "responseHeaders", followed by the bytes of
|
@@ -164,12 +166,12 @@ module WebPackage
|
|
164
166
|
|
165
167
|
def encoded_mice_headers
|
166
168
|
@encoded_mice_headers ||=
|
167
|
-
@cbor.generate @mice.headers.merge(':status' => bin(
|
169
|
+
@cbor.generate @mice.headers.merge(':status' => bin(@inner.status))
|
168
170
|
end
|
169
171
|
|
170
172
|
# returns a string representing serialized label + params
|
171
173
|
def structured_header_for(label, params)
|
172
|
-
if params['cert-url'].
|
174
|
+
if params[:'cert-url'].to_s.empty?
|
173
175
|
raise '[SignedHttpExchange] No certificate url provided - please use `SXG_CERT_URL` '\
|
174
176
|
'env var. Endpoint should respond with `application/cert-chain+cbor` content type.'
|
175
177
|
end
|
@@ -207,23 +209,18 @@ module WebPackage
|
|
207
209
|
|
208
210
|
def build_uri_from(url)
|
209
211
|
u = url.is_a?(URI) ? url : URI(url)
|
210
|
-
raise
|
211
|
-
raise '[SignedHttpExchange] Request host is required' if u.host.blank?
|
212
|
+
raise '[SignedHttpExchange] Request host is required' if u.host.nil?
|
212
213
|
|
213
214
|
u
|
214
215
|
end
|
215
216
|
|
216
|
-
def fallback_url
|
217
|
-
@fallback_url ||= @uri.to_s
|
218
|
-
end
|
219
|
-
|
220
217
|
def validity_url
|
221
218
|
@validity_url ||= begin
|
222
219
|
path = @uri.path
|
223
220
|
fi = path.index(?.)
|
224
221
|
no_format_path = fi ? path[0...fi] : path # path without format, i.e. default :html
|
225
222
|
|
226
|
-
URI::HTTPS.build(host: @uri.host, path: no_format_path).to_s
|
223
|
+
URI::HTTPS.build(host: @uri.host, path: no_format_path, query: @uri.query).to_s
|
227
224
|
end
|
228
225
|
end
|
229
226
|
|
data/lib/web_package/signer.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
1
3
|
module WebPackage
|
2
4
|
# Performs signing of a message with ECDSA.
|
3
5
|
class Signer
|
@@ -5,11 +7,11 @@ module WebPackage
|
|
5
7
|
attr_reader :signed_at, :expires_at, :cert, :integrity, :cert_url
|
6
8
|
|
7
9
|
def initialize(path_to_cert, path_to_key)
|
8
|
-
@alg
|
9
|
-
@cert
|
10
|
+
@alg = OpenSSL::PKey::EC.new(File.read(path_to_key))
|
11
|
+
@cert = OpenSSL::X509::Certificate.new(File.read(path_to_cert))
|
10
12
|
|
11
|
-
@signed_at = Time.
|
12
|
-
@expires_at = @signed_at + 7
|
13
|
+
@signed_at = Time.now
|
14
|
+
@expires_at = @signed_at + 60 * 60 * 24 * 7
|
13
15
|
end
|
14
16
|
|
15
17
|
def sign(message)
|
data/lib/web_package/version.rb
CHANGED
data/lib/web_package.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
-
require '
|
2
|
-
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
require 'web_package/errors/body_encoding_error'
|
3
4
|
require 'web_package/version'
|
4
5
|
require 'web_package/helpers'
|
5
6
|
require 'web_package/mice'
|
6
7
|
require 'web_package/cbor'
|
7
|
-
require 'web_package/
|
8
|
+
require 'web_package/inner_response'
|
8
9
|
require 'web_package/signer'
|
10
|
+
require 'web_package/signed_http_exchange'
|
11
|
+
require 'web_package/middleware'
|
data/web_package.gemspec
CHANGED
@@ -16,7 +16,8 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.files = `git ls-files`.split("\n")
|
17
17
|
s.require_paths = ['lib']
|
18
18
|
|
19
|
-
s.required_ruby_version = '>=2.
|
19
|
+
s.required_ruby_version = '>=2.2.0'
|
20
20
|
|
21
|
+
s.add_development_dependency 'byebug'
|
21
22
|
s.add_development_dependency 'rubocop', '~> 0.67'
|
22
23
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: web_package
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oleg Afanasyev
|
@@ -9,8 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-
|
12
|
+
date: 2019-05-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: byebug
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
14
28
|
- !ruby/object:Gem::Dependency
|
15
29
|
name: rubocop
|
16
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -41,7 +55,9 @@ files:
|
|
41
55
|
- lib/web_package/cbor.rb
|
42
56
|
- lib/web_package/errors/body_encoding_error.rb
|
43
57
|
- lib/web_package/helpers.rb
|
58
|
+
- lib/web_package/inner_response.rb
|
44
59
|
- lib/web_package/mice.rb
|
60
|
+
- lib/web_package/middleware.rb
|
45
61
|
- lib/web_package/signed_http_exchange.rb
|
46
62
|
- lib/web_package/signer.rb
|
47
63
|
- lib/web_package/version.rb
|
@@ -58,7 +74,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
58
74
|
requirements:
|
59
75
|
- - ">="
|
60
76
|
- !ruby/object:Gem::Version
|
61
|
-
version: 2.
|
77
|
+
version: 2.2.0
|
62
78
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
63
79
|
requirements:
|
64
80
|
- - ">="
|
@@ -66,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
66
82
|
version: '0'
|
67
83
|
requirements: []
|
68
84
|
rubyforge_project:
|
69
|
-
rubygems_version: 2.
|
85
|
+
rubygems_version: 2.6.13
|
70
86
|
signing_key:
|
71
87
|
specification_version: 4
|
72
88
|
summary: Packaging Websites with Ruby.
|