jellyfish 1.3.1 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e3fc2a04dd1e7b37c37958f0b25b2d6191832cc366709d041e1300ef1af439f
4
- data.tar.gz: 1d8b6a8eba52d898fe154e66953185bf54df5cf0b8de447ae1d6642b7c01a0e6
3
+ metadata.gz: a2ac4c1c5b9beff9266516aa120e637e7c1b3d09010e0f0cf0df7b8728e26646
4
+ data.tar.gz: 8cd5fff611eea7b8fc454aa8a4d2a844225cf2904d6fcf46dacfc118f9090d84
5
5
  SHA512:
6
- metadata.gz: 78344e08eb017faf0215752156b32049ff28f400c7056da95b2956258c3fa4f6295042c8063dab78e3ca67b6948f5eccbf69905b24deb72bd09c96d25fa8c542
7
- data.tar.gz: e1d4b4abd422e3b77d23e60b4a8ddf3484bcfc394b90530101f046676f63eb83b0629f2a21323c27a563a97d2ab77c057456939194c68916eca7bfae52b3169d
6
+ metadata.gz: 87587d0f02f1896aa15fb8b72daf2e1cd22b129a89f277680f56ada903778ff2d23c86765273a6199e97c85563e458225a8079bd97e660b4085103b548d99a78
7
+ data.tar.gz: 35071bfc020d030e952c2023a3bfb7c8cdcf9723194bb8f70212e4cb01b0dc74105a9ccfd93e4c7921f94b37c10049e74e42322cc0532447b87c8e90ceacfd38
data/.gitlab-ci.yml ADDED
@@ -0,0 +1,41 @@
1
+
2
+ stages:
3
+ - test
4
+
5
+ .test:
6
+ stage: test
7
+ image: ruby:${RUBY_VERSION}-bullseye
8
+ variables:
9
+ GIT_DEPTH: "1"
10
+ GIT_SUBMODULE_STRATEGY: recursive
11
+ GIT_SUBMODULE_PATHS: task
12
+ # websocket_parser does not work with frozen string literal
13
+ # RUBYOPT: --enable-frozen-string-literal
14
+ before_script:
15
+ - bundle install --retry=3
16
+ - unset CI # Coverage doesn't work well with frozen literal
17
+ script:
18
+ - ruby -vr bundler/setup -S rake test
19
+
20
+ ruby:3.0:
21
+ extends:
22
+ - .test
23
+ variables:
24
+ RUBY_VERSION: '3.0'
25
+
26
+ ruby:3.1:
27
+ extends:
28
+ - .test
29
+ variables:
30
+ RUBY_VERSION: '3.1'
31
+
32
+ ruby:3.2:
33
+ extends:
34
+ - .test
35
+ variables:
36
+ RUBY_VERSION: '3.2'
37
+
38
+ jruby:latest:
39
+ extends:
40
+ - .test
41
+ image: jruby:latest
data/.gitmodules CHANGED
@@ -1,3 +1,3 @@
1
1
  [submodule "task"]
2
2
  path = task
3
- url = git://github.com/godfat/gemgem.git
3
+ url = https://github.com/godfat/gemgem.git
data/CHANGES.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # CHANGES
2
2
 
3
+ ## Jellyfish 1.4.0 -- 2023-02-22
4
+
5
+ ### Incompatible changes
6
+
7
+ * Adopted Rack 3. Technically, just lower the cases for headers.
8
+ * Internal strings are all frozen now.
9
+ * `log` and `log_error` now takes the `env` for the second argument,
10
+ rather than the error stream.
11
+ * `handle` now takes the `env` for the third argument,
12
+ rather than the error stream.
13
+
14
+ ### Enhancements
15
+
16
+ * The default error logging will now also show `env['PATH_INFO']`.
17
+
3
18
  ## Jellyfish 1.3.1 -- 2018-11-11
4
19
 
5
20
  ### Bugs fixed
data/Gemfile CHANGED
@@ -11,7 +11,3 @@ gem 'websocket_parser'
11
11
 
12
12
  gem 'simplecov', :require => false if ENV['COV']
13
13
  gem 'coveralls', :require => false if ENV['CI']
14
-
15
- platform :rbx do
16
- gem 'rubysl-singleton' # used in rake
17
- end
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Jellyfish [![Build Status](https://secure.travis-ci.org/godfat/jellyfish.png?branch=master)](http://travis-ci.org/godfat/jellyfish) [![Coverage Status](https://coveralls.io/repos/github/godfat/jellyfish/badge.png)](https://coveralls.io/github/godfat/jellyfish) [![Join the chat at https://gitter.im/godfat/jellyfish](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/godfat/jellyfish)
1
+ # Jellyfish [![Pipeline status](https://gitlab.com/godfat/jellyfish/badges/master/pipeline.svg)](https://gitlab.com/godfat/jellyfish/-/pipelines)
2
2
 
3
- by Lin Jen-Shin ([godfat](http://godfat.org))
3
+ by Lin Jen-Shin ([godfat](https://godfat.org))
4
4
 
5
5
  ![logo](https://github.com/godfat/jellyfish/raw/master/jellyfish.png)
6
6
 
@@ -8,7 +8,7 @@ by Lin Jen-Shin ([godfat](http://godfat.org))
8
8
 
9
9
  * [github](https://github.com/godfat/jellyfish)
10
10
  * [rubygems](https://rubygems.org/gems/jellyfish)
11
- * [rdoc](http://rdoc.info/github/godfat/jellyfish)
11
+ * [rdoc](https://rubydoc.info/github/godfat/jellyfish)
12
12
  * [issues](https://github.com/godfat/jellyfish/issues) (feel free to ask for support)
13
13
 
14
14
  ## DESCRIPTION:
@@ -42,7 +42,7 @@ Check [jellyfish-contrib][] for extra extensions.
42
42
  * Simple
43
43
  * Modular
44
44
  * No templates (You could use [tilt](https://github.com/rtomayko/tilt))
45
- * No ORM (You could use [sequel](http://sequel.jeremyevans.net/))
45
+ * No ORM (You could use [sequel](https://sequel.jeremyevans.net))
46
46
  * No `dup` in `call`
47
47
  * Regular expression routes, e.g. `get %r{^/(?<id>\d+)$}`
48
48
  * String routes, e.g. `get '/'`
@@ -56,7 +56,7 @@ Because Sinatra is too complex and inconsistent for me.
56
56
 
57
57
  ## REQUIREMENTS:
58
58
 
59
- * Tested with MRI (official CRuby), Rubinius and JRuby.
59
+ * Tested with MRI (official CRuby) and JRuby.
60
60
 
61
61
  ## INSTALLATION:
62
62
 
@@ -84,7 +84,7 @@ run Tank.new
84
84
  <!---
85
85
  GET /
86
86
  [200,
87
- {'Content-Length' => '12', 'Content-Type' => 'text/plain'},
87
+ {'content-length' => '12', 'content-type' => 'text/plain'},
88
88
  ["Jelly Kelly\n"]]
89
89
  -->
90
90
 
@@ -106,7 +106,7 @@ run Tank.new
106
106
  <!---
107
107
  GET /123
108
108
  [200,
109
- {'Content-Length' => '11', 'Content-Type' => 'text/plain'},
109
+ {'content-length' => '11', 'content-type' => 'text/plain'},
110
110
  ["Jelly #123\n"]]
111
111
  -->
112
112
 
@@ -133,7 +133,7 @@ run Tank.new
133
133
  <!---
134
134
  GET /hctam
135
135
  [200,
136
- {'Content-Length' => '5', 'Content-Type' => 'text/plain'},
136
+ {'content-length' => '5', 'content-type' => 'text/plain'},
137
137
  ["true\n"]]
138
138
  -->
139
139
 
@@ -159,7 +159,7 @@ run Tank.new
159
159
  <!---
160
160
  POST /
161
161
  [201,
162
- {'Content-Length' => '18', 'Content-Type' => 'text/plain',
162
+ {'content-length' => '18', 'content-type' => 'text/plain',
163
163
  'X-Jellyfish-Life' => '100', 'X-Jellyfish-Mana' => '200'},
164
164
  ["Jellyfish 100/200\n"]]
165
165
  -->
@@ -185,8 +185,8 @@ body = File.read("#{File.dirname(
185
185
  File.expand_path(__FILE__))}/../lib/jellyfish/public/302.html").
186
186
  gsub('VAR_URL', 'http://host/')
187
187
  [302,
188
- {'Content-Length' => body.bytesize.to_s, 'Content-Type' => 'text/html',
189
- 'Location' => 'http://host/'},
188
+ {'content-length' => body.bytesize.to_s, 'content-type' => 'text/html',
189
+ 'location' => 'http://host/'},
190
190
  [body]]
191
191
  -->
192
192
 
@@ -210,7 +210,7 @@ GET /crash
210
210
  body = File.read("#{File.dirname(
211
211
  File.expand_path(__FILE__))}/../lib/jellyfish/public/500.html")
212
212
  [500,
213
- {'Content-Length' => body.bytesize.to_s, 'Content-Type' => 'text/html'},
213
+ {'content-length' => body.bytesize.to_s, 'content-type' => 'text/html'},
214
214
  [body]]
215
215
  -->
216
216
 
@@ -244,7 +244,7 @@ body = case RUBY_ENGINE
244
244
  "No one hears you: (eval):9:in `block in <class:Tank>'\n"
245
245
  end
246
246
  [403,
247
- {'Content-Length' => body.bytesize.to_s, 'Content-Type' => 'text/plain'},
247
+ {'content-length' => body.bytesize.to_s, 'content-type' => 'text/plain'},
248
248
  [body]]
249
249
  -->
250
250
 
@@ -267,7 +267,7 @@ run Tank.new
267
267
  <!---
268
268
  GET /
269
269
  [404,
270
- {'Content-Length' => '18', 'Content-Type' => 'text/plain'},
270
+ {'content-length' => '18', 'content-type' => 'text/plain'},
271
271
  ["You found nothing."]]
272
272
  -->
273
273
 
@@ -293,7 +293,7 @@ run Tank.new
293
293
  <!---
294
294
  GET /
295
295
  [404,
296
- {'Content-Length' => '18', 'Content-Type' => 'text/plain'},
296
+ {'content-length' => '18', 'content-type' => 'text/plain'},
297
297
  ["You found nothing."]]
298
298
  -->
299
299
 
@@ -315,7 +315,7 @@ run Tank.new
315
315
  <!---
316
316
  GET /report?name=godfat
317
317
  [200,
318
- {'Content-Length' => '20', 'Content-Type' => 'text/plain'},
318
+ {'content-length' => '20', 'content-type' => 'text/plain'},
319
319
  ["Your name is godfat\n"]]
320
320
  -->
321
321
 
@@ -341,7 +341,7 @@ run Tank.new
341
341
  <!---
342
342
  GET /report
343
343
  [200,
344
- {'Content-Length' => '3', 'Content-Type' => 'text/plain'},
344
+ {'content-length' => '3', 'content-type' => 'text/plain'},
345
345
  ["OK\n"]]
346
346
  -->
347
347
 
@@ -374,7 +374,7 @@ run Heater.new
374
374
  <!---
375
375
  GET /status
376
376
  [200,
377
- {'Content-Length' => '6', 'Content-Type' => 'text/plain'},
377
+ {'content-length' => '6', 'content-type' => 'text/plain'},
378
378
  ["30\u{2103}\n"]]
379
379
  -->
380
380
 
@@ -406,7 +406,7 @@ run Heater.new
406
406
  <!---
407
407
  GET /status
408
408
  [200,
409
- {'Content-Length' => '6', 'Content-Type' => 'text/plain'},
409
+ {'content-length' => '6', 'content-type' => 'text/plain'},
410
410
  ["30\u{2103}\n"]]
411
411
  -->
412
412
 
@@ -438,7 +438,7 @@ run Tank.new
438
438
  <!---
439
439
  GET /123
440
440
  [200,
441
- {'Content-Length' => '13', 'Content-Type' => 'text/plain'},
441
+ {'content-length' => '13', 'content-type' => 'text/plain'},
442
442
  ["Jelly jumps.\n"]]
443
443
  -->
444
444
 
@@ -554,13 +554,13 @@ GET /m/x
554
554
  [200, {}, ["m\n"]]
555
555
 
556
556
  GET /
557
- [200, {'Content-Length' => '2'}, ["/\n"]]
557
+ [200, {'content-length' => '2'}, ["/\n"]]
558
558
 
559
559
  GET /x
560
- [200, {'Content-Length' => '2'}, ["/\n"]]
560
+ [200, {'content-length' => '2'}, ["/\n"]]
561
561
 
562
562
  GET /ab
563
- [200, {'Content-Length' => '2'}, ["/\n"]]
563
+ [200, {'content-length' => '2'}, ["/\n"]]
564
564
  -->
565
565
 
566
566
  You could try a stupid benchmark yourself:
@@ -807,7 +807,7 @@ run Tank.new
807
807
  <!---
808
808
  GET /123
809
809
  [200,
810
- {'Content-Length' => '11', 'Content-Type' => 'text/plain'},
810
+ {'content-length' => '11', 'content-type' => 'text/plain'},
811
811
  ["Jelly #123\n"]]
812
812
  -->
813
813
 
@@ -831,7 +831,7 @@ run Tank.new
831
831
  <!---
832
832
  GET /%E5%9B%A7
833
833
  [200,
834
- {'Content-Length' => '16', 'Content-Type' => 'text/plain'},
834
+ {'content-length' => '16', 'content-type' => 'text/plain'},
835
835
  ["/%E5%9B%A7=/\u{56e7}\n"]]
836
836
  -->
837
837
 
@@ -862,7 +862,7 @@ run Tank.new
862
862
  <!---
863
863
  GET /123
864
864
  [200,
865
- {'Content-Length' => '18', 'Content-Type' => 'text/plain'},
865
+ {'content-length' => '18', 'content-type' => 'text/plain'},
866
866
  ["Jelly #123 jumps.\n"]]
867
867
  -->
868
868
 
@@ -896,7 +896,7 @@ run Tank.new
896
896
  <!---
897
897
  GET /
898
898
  [200,
899
- {'Content-Length' => '12', 'Content-Type' => 'text/plain'},
899
+ {'content-length' => '12', 'content-type' => 'text/plain'},
900
900
  ["Jelly Kelly\n"]]
901
901
  -->
902
902
 
@@ -934,7 +934,7 @@ run Tank.new
934
934
  <!---
935
935
  GET /status
936
936
  [200,
937
- {'Content-Length' => '25', 'Content-Type' => 'text/plain',
937
+ {'content-length' => '25', 'content-type' => 'text/plain',
938
938
  'X-Temperature' => "30\u{2103}"},
939
939
  ["See header X-Temperature\n"]]
940
940
  -->
@@ -980,7 +980,7 @@ run Tank.new
980
980
  <!---
981
981
  GET /status
982
982
  [200,
983
- {'Content-Length' => '1', 'Content-Type' => 'text/plain',
983
+ {'content-length' => '1', 'content-type' => 'text/plain',
984
984
  'X-Temperature' => "35\u{2103}"},
985
985
  ["\n"]]
986
986
  -->
@@ -1013,7 +1013,7 @@ run Tank.new
1013
1013
  <!---
1014
1014
  GET /status
1015
1015
  [200,
1016
- {'Content-Length' => '6', 'Content-Type' => 'text/plain'},
1016
+ {'content-length' => '6', 'content-type' => 'text/plain'},
1017
1017
  ["30\u{2103}\n"]]
1018
1018
  -->
1019
1019
 
@@ -1048,7 +1048,7 @@ run HugeTank
1048
1048
  <!---
1049
1049
  GET /status
1050
1050
  [200,
1051
- {'Content-Length' => '6', 'Content-Type' => 'text/plain'},
1051
+ {'content-length' => '6', 'content-type' => 'text/plain'},
1052
1052
  ["30\u{2103}\n"]]
1053
1053
  -->
1054
1054
 
@@ -1081,7 +1081,7 @@ run Tank.new
1081
1081
  <!---
1082
1082
  GET /
1083
1083
  [200,
1084
- {'Content-Length' => '29', 'Content-Type' => 'text/plain'},
1084
+ {'content-length' => '29', 'content-type' => 'text/plain'},
1085
1085
  ["Protected: Oops, tank broken\n"]]
1086
1086
  -->
1087
1087
 
@@ -1099,7 +1099,6 @@ class Tank
1099
1099
  }
1100
1100
  end
1101
1101
  end
1102
- use Rack::Chunked
1103
1102
  use Rack::ContentType, 'text/plain'
1104
1103
  run Tank.new
1105
1104
  ```
@@ -1107,9 +1106,8 @@ run Tank.new
1107
1106
  <!---
1108
1107
  GET /chunked
1109
1108
  [200,
1110
- {'Content-Type' => 'text/plain', 'Transfer-Encoding' => 'chunked'},
1111
- ["2\r\n0\n\r\n", "2\r\n1\n\r\n", "2\r\n2\n\r\n",
1112
- "2\r\n3\n\r\n", "2\r\n4\n\r\n", "0\r\n\r\n"]]
1109
+ {'content-type' => 'text/plain'},
1110
+ ["0\n", "1\n", "2\n", "3\n", "4\n"]]
1113
1111
  -->
1114
1112
 
1115
1113
  ### Chunked transfer encoding (streaming) with custom body
@@ -1126,7 +1124,6 @@ class Tank
1126
1124
  Body.new
1127
1125
  end
1128
1126
  end
1129
- use Rack::Chunked
1130
1127
  use Rack::ContentType, 'text/plain'
1131
1128
  run Tank.new
1132
1129
  ```
@@ -1134,9 +1131,8 @@ run Tank.new
1134
1131
  <!---
1135
1132
  GET /chunked
1136
1133
  [200,
1137
- {'Content-Type' => 'text/plain', 'Transfer-Encoding' => 'chunked'},
1138
- ["2\r\n0\n\r\n", "2\r\n1\n\r\n", "2\r\n2\n\r\n",
1139
- "2\r\n3\n\r\n", "2\r\n4\n\r\n", "0\r\n\r\n"]]
1134
+ {'content-type' => 'text/plain'},
1135
+ ["0\n", "1\n", "2\n", "3\n", "4\n"]]
1140
1136
  -->
1141
1137
 
1142
1138
  ### Server Sent Event (SSE)
@@ -1150,7 +1146,7 @@ class Tank
1150
1146
  end
1151
1147
  end
1152
1148
  get '/sse' do
1153
- headers_merge('Content-Type' => 'text/event-stream')
1149
+ headers_merge('content-type' => 'text/event-stream')
1154
1150
  Body.new
1155
1151
  end
1156
1152
  end
@@ -1160,7 +1156,7 @@ run Tank.new
1160
1156
  <!---
1161
1157
  GET /sse
1162
1158
  [200,
1163
- {'Content-Type' => 'text/event-stream'},
1159
+ {'content-type' => 'text/event-stream'},
1164
1160
  ["data: 0\n\n", "data: 1\n\n", "data: 2\n\n", "data: 3\n\n", "data: 4\n\n"]]
1165
1161
  -->
1166
1162
 
@@ -1171,7 +1167,7 @@ class Tank
1171
1167
  include Jellyfish
1172
1168
  get '/sse' do
1173
1169
  headers_merge(
1174
- 'Content-Type' => 'text/event-stream',
1170
+ 'content-type' => 'text/event-stream',
1175
1171
  'rack.hijack' => lambda do |sock|
1176
1172
  (0..4).each do |i|
1177
1173
  sock.write("data: #{i}\n\n")
@@ -1186,7 +1182,7 @@ run Tank.new
1186
1182
  <!---
1187
1183
  GET /sse
1188
1184
  [200,
1189
- {'Content-Type' => 'text/event-stream'},
1185
+ {'content-type' => 'text/event-stream'},
1190
1186
  ["data: 0\n\n", "data: 1\n\n", "data: 2\n\n", "data: 3\n\n", "data: 4\n\n"]]
1191
1187
  -->
1192
1188
 
@@ -1201,9 +1197,9 @@ EventMachine is basically dead, we could see if there would be a
1201
1197
  [Celluloid-IO][] based web server production ready in the future,
1202
1198
  so that we could take the advantage of event based approach.
1203
1199
 
1204
- [hijack]: http://www.rubydoc.info/github/rack/rack/file/SPEC#Hijacking
1205
- [Rainbows!]: http://rainbows.bogomips.org/
1206
- [Puma]: http://puma.io/
1200
+ [hijack]: https://github.com/rack/rack/blob/main/SPEC.rdoc#label-Hijacking
1201
+ [Rainbows!]: https://yhbt.net/rainbows/
1202
+ [Puma]: https://puma.io
1207
1203
  [Celluloid-IO]: https://github.com/celluloid/celluloid-io
1208
1204
 
1209
1205
  ``` ruby
@@ -1244,13 +1240,13 @@ HTTP
1244
1240
 
1245
1241
  Apache License 2.0 (Apache-2.0)
1246
1242
 
1247
- Copyright (c) 2012-2018, Lin Jen-Shin (godfat)
1243
+ Copyright (c) 2012-2023, Lin Jen-Shin (godfat)
1248
1244
 
1249
1245
  Licensed under the Apache License, Version 2.0 (the "License");
1250
1246
  you may not use this file except in compliance with the License.
1251
1247
  You may obtain a copy of the License at
1252
1248
 
1253
- <http://www.apache.org/licenses/LICENSE-2.0>
1249
+ <https://www.apache.org/licenses/LICENSE-2.0>
1254
1250
 
1255
1251
  Unless required by applicable law or agreed to in writing, software
1256
1252
  distributed under the License is distributed on an "AS IS" BASIS,
data/config.ru CHANGED
@@ -7,7 +7,7 @@ class Jelly
7
7
 
8
8
  controller_include Module.new{
9
9
  def dispatch
10
- headers_merge 'Content-Type' => 'application/json; charset=utf-8',
10
+ headers_merge 'content-type' => 'application/json; charset=utf-8',
11
11
  'Access-Control-Allow-Origin' => '*'
12
12
  super
13
13
  end
@@ -59,7 +59,6 @@ end
59
59
 
60
60
  App = Jellyfish::Builder.app do
61
61
  use Rack::CommonLogger
62
- use Rack::Chunked
63
62
  use Rack::ContentLength
64
63
  use Rack::Deflater
65
64
 
data/jellyfish.gemspec CHANGED
@@ -1,20 +1,20 @@
1
1
  # -*- encoding: utf-8 -*-
2
- # stub: jellyfish 1.3.1 ruby lib
2
+ # stub: jellyfish 1.4.0 ruby lib
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "jellyfish".freeze
6
- s.version = "1.3.1"
6
+ s.version = "1.4.0"
7
7
 
8
8
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
9
  s.require_paths = ["lib".freeze]
10
10
  s.authors = ["Lin Jen-Shin (godfat)".freeze]
11
- s.date = "2018-11-11"
11
+ s.date = "2023-02-22"
12
12
  s.description = "Pico web framework for building API-centric web applications.\nFor Rack applications or Rack middleware. Around 250 lines of code.\n\nCheck [jellyfish-contrib][] for extra extensions.\n\n[jellyfish-contrib]: https://github.com/godfat/jellyfish-contrib".freeze
13
13
  s.email = ["godfat (XD) godfat.org".freeze]
14
14
  s.files = [
15
15
  ".gitignore".freeze,
16
+ ".gitlab-ci.yml".freeze,
16
17
  ".gitmodules".freeze,
17
- ".travis.yml".freeze,
18
18
  "CHANGES.md".freeze,
19
19
  "Gemfile".freeze,
20
20
  "LICENSE".freeze,
@@ -56,7 +56,7 @@ Gem::Specification.new do |s|
56
56
  "test/test_websocket.rb".freeze]
57
57
  s.homepage = "https://github.com/godfat/jellyfish".freeze
58
58
  s.licenses = ["Apache-2.0".freeze]
59
- s.rubygems_version = "2.7.8".freeze
59
+ s.rubygems_version = "3.4.3".freeze
60
60
  s.summary = "Pico web framework for building API-centric web applications.".freeze
61
61
  s.test_files = [
62
62
  "test/rack/test_builder.rb".freeze,
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Jellyfish
4
- VERSION = '1.3.1'
4
+ VERSION = '1.4.0'
5
5
  end
data/lib/jellyfish.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
 
2
3
  module Jellyfish
3
4
  autoload :VERSION , 'jellyfish/version'
@@ -15,7 +16,7 @@ module Jellyfish
15
16
 
16
17
  class Response < RuntimeError
17
18
  def headers
18
- @headers ||= {'Content-Type' => 'text/html'}
19
+ @headers ||= {'content-type' => 'text/html'}
19
20
  end
20
21
 
21
22
  def body
@@ -29,7 +30,7 @@ module Jellyfish
29
30
  attr_reader :url
30
31
  def initialize url; @url = url ; end
31
32
  def status ; 302 ; end
32
- def headers ; super.merge('Location' => url) ; end
33
+ def headers ; super.merge('location' => url) ; end
33
34
  def body ; super.map{ |b| b.gsub('VAR_URL', url) }; end
34
35
  end
35
36
 
@@ -55,8 +56,8 @@ module Jellyfish
55
56
  raise
56
57
  end
57
58
 
58
- def log message; jellyfish.log( message, env['rack.errors']); end
59
- def log_error error; jellyfish.log_error(error, env['rack.errors']); end
59
+ def log message; jellyfish.log( message, env); end
60
+ def log_error error; jellyfish.log_error(error, env); end
60
61
  def request ; @request ||= Rack::Request.new(env); end
61
62
  def halt *args; throw(:halt, *args) ; end
62
63
  def cascade ; halt(Jellyfish::Cascade) ; end
@@ -190,7 +191,7 @@ module Jellyfish
190
191
  when Cascade
191
192
  cascade(ctrl, env)
192
193
  when Response
193
- handle(ctrl, res, env['rack.errors'])
194
+ handle(ctrl, res, env)
194
195
  when Array
195
196
  res
196
197
  when NilClass # make sure we return rack triple
@@ -199,47 +200,48 @@ module Jellyfish
199
200
  raise TypeError.new("Expect the response to be a Jellyfish::Response" \
200
201
  " or Rack triple (Array), but got: #{res.inspect}")
201
202
  end
202
- rescue => e
203
- handle(ctrl, e, env['rack.errors'])
203
+ rescue => error
204
+ handle(ctrl, error, env)
204
205
  end
205
206
 
206
- def log_error e, stderr
207
- return unless stderr
208
- stderr.puts("[#{self.class.name}] #{e.inspect} #{e.backtrace}")
207
+ def log_error error, env
208
+ env['rack.errors']&.
209
+ puts("[#{self.class.name}] #{error.inspect}" \
210
+ " for #{env['PATH_INFO'] || '/'} #{error.backtrace}")
209
211
  end
210
212
 
211
- def log msg, stderr
212
- return unless stderr
213
- stderr.puts("[#{self.class.name}] #{msg}")
213
+ def log msg, env
214
+ env['rack.errors']&.
215
+ puts("[#{self.class.name}] #{msg}")
214
216
  end
215
217
 
216
218
  private
217
219
  def cascade ctrl, env
218
220
  app.call(env)
219
- rescue => e
220
- handle(ctrl, e, env['rack.errors'])
221
+ rescue => error
222
+ handle(ctrl, error, env)
221
223
  end
222
224
 
223
- def handle ctrl, e, stderr=nil
224
- if handler = best_handler(e)
225
- ctrl.block_call(e, handler)
225
+ def handle ctrl, error, env
226
+ if handler = best_handler(error)
227
+ ctrl.block_call(error, handler)
226
228
  elsif !self.class.handle_exceptions
227
- raise e
228
- elsif e.kind_of?(Response) # InternalError ends up here if no handlers
229
- [e.status, e.headers, e.body]
229
+ raise error
230
+ elsif error.kind_of?(Response) # InternalError ends up here if no handlers
231
+ [error.status, error.headers, error.body]
230
232
  else # fallback and see if there's any InternalError handler
231
- log_error(e, stderr)
232
- handle(ctrl, InternalError.new)
233
+ log_error(error, env)
234
+ handle(ctrl, InternalError.new, env)
233
235
  end
234
236
  end
235
237
 
236
- def best_handler e
238
+ def best_handler error
237
239
  handlers = self.class.handlers
238
- if handlers.key?(e.class)
239
- handlers[e.class]
240
+ if handlers.key?(error.class)
241
+ handlers[error.class]
240
242
  else # or find the nearest match and cache it
241
- ancestors = e.class.ancestors
242
- handlers[e.class] = handlers.dup. # thread safe iteration
243
+ ancestors = error.class.ancestors
244
+ handlers[error.class] = handlers.dup. # thread safe iteration
243
245
  inject([nil, Float::INFINITY]){ |(handler, val), (klass, block)|
244
246
  idx = ancestors.index(klass) || Float::INFINITY # lower is better
245
247
  if idx < val then [block, idx] else [handler, val] end }.first
data/task/README.md CHANGED
@@ -13,11 +13,11 @@ Provided tasks:
13
13
 
14
14
  ## REQUIREMENTS:
15
15
 
16
- * Tested with MRI (official CRuby), Rubinius and JRuby.
16
+ * Tested with MRI (official CRuby) and JRuby.
17
17
 
18
18
  ## INSTALLATION:
19
19
 
20
- git submodule add git://github.com/godfat/gemgem.git task
20
+ git submodule add https://github.com/godfat/gemgem.git task
21
21
 
22
22
  And in Rakefile:
23
23
 
@@ -39,13 +39,13 @@ end
39
39
 
40
40
  Apache License 2.0 (Apache-2.0)
41
41
 
42
- Copyright (c) 2011-2017, Lin Jen-Shin (godfat)
42
+ Copyright (c) 2011-2023, Lin Jen-Shin (godfat)
43
43
 
44
44
  Licensed under the Apache License, Version 2.0 (the "License");
45
45
  you may not use this file except in compliance with the License.
46
46
  You may obtain a copy of the License at
47
47
 
48
- <http://www.apache.org/licenses/LICENSE-2.0>
48
+ <https://www.apache.org/licenses/LICENSE-2.0>
49
49
 
50
50
  Unless required by applicable law or agreed to in writing, software
51
51
  distributed under the License is distributed on an "AS IS" BASIS,
data/task/gemgem.rb CHANGED
@@ -42,6 +42,7 @@ module Gemgem
42
42
 
43
43
  def gem_install
44
44
  require 'rubygems/commands/install_command'
45
+ require 'rubygems/package'
45
46
  # read ~/.gemrc
46
47
  Gem.use_paths(Gem.configuration[:gemhome], Gem.configuration[:gempath])
47
48
  Gem::Command.extra_args = Gem.configuration[:gem]
@@ -51,7 +52,8 @@ module Gemgem
51
52
  cmd.handle_options([])
52
53
 
53
54
  # install
54
- install = Gem::Installer.new(gem_path, cmd.options)
55
+ gem_package = Gem::Package.new(gem_path)
56
+ install = Gem::Installer.new(gem_package, cmd.options)
55
57
  install.install
56
58
  puts "\e[35mGem installed: \e[33m#{strip_path(install.gem_dir)}\e[0m"
57
59
  end
@@ -28,10 +28,10 @@ describe Jellyfish::Builder do
28
28
  would "supports mapping" do
29
29
  app = builder_to_app do
30
30
  map '/' do |outer_env|
31
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['root']] }
31
+ run lambda { |inner_env| [200, {"content-type" => "text/plain"}, ['root']] }
32
32
  end
33
33
  map '/sub' do
34
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['sub']] }
34
+ run lambda { |inner_env| [200, {"content-type" => "text/plain"}, ['sub']] }
35
35
  end
36
36
  end
37
37
  Rack::MockRequest.new(app).get("/").body.to_s.should.eq 'root'
@@ -56,7 +56,7 @@ describe Jellyfish::Builder do
56
56
  'secret' == password
57
57
  end
58
58
 
59
- run lambda { |env| [200, {"Content-Type" => "text/plain"}, ['Hi Boss']] }
59
+ run lambda { |env| [200, {"content-type" => "text/plain"}, ['Hi Boss']] }
60
60
  end
61
61
 
62
62
  response = Rack::MockRequest.new(app).get("/")
@@ -84,9 +84,9 @@ describe Jellyfish::Builder do
84
84
  would "can mix map and run for endpoints" do
85
85
  app = builder_to_app do
86
86
  map '/sub' do
87
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['sub']] }
87
+ run lambda { |inner_env| [200, {"content-type" => "text/plain"}, ['sub']] }
88
88
  end
89
- run lambda { |inner_env| [200, {"Content-Type" => "text/plain"}, ['root']] }
89
+ run lambda { |inner_env| [200, {"content-type" => "text/plain"}, ['root']] }
90
90
  end
91
91
 
92
92
  Rack::MockRequest.new(app).get("/").body.to_s.should.eq 'root'
@@ -123,7 +123,7 @@ describe Jellyfish::Builder do
123
123
  def call(env)
124
124
  raise "bzzzt" if @called > 0
125
125
  @called += 1
126
- [200, {'Content-Type' => 'text/plain'}, ['OK']]
126
+ [200, {'content-type' => 'text/plain'}, ['OK']]
127
127
  end
128
128
  end
129
129
 
@@ -8,9 +8,9 @@ describe Jellyfish::URLMap do
8
8
  would "dispatches paths correctly" do
9
9
  app = lambda { |env|
10
10
  [200, {
11
- 'X-ScriptName' => env['SCRIPT_NAME'],
12
- 'X-PathInfo' => env['PATH_INFO'],
13
- 'Content-Type' => 'text/plain'
11
+ 'x-scriptname' => env['SCRIPT_NAME'],
12
+ 'x-pathinfo' => env['PATH_INFO'],
13
+ 'content-type' => 'text/plain'
14
14
  }, [""]]
15
15
  }
16
16
  map = Rack::Lint.new(Jellyfish::URLMap.new({
@@ -27,102 +27,102 @@ describe Jellyfish::URLMap do
27
27
 
28
28
  res = Rack::MockRequest.new(map).get("/foo")
29
29
  res.should.ok?
30
- res["X-ScriptName"].should.eq "/foo"
31
- res["X-PathInfo"].should.eq ""
30
+ res["x-scriptname"].should.eq "/foo"
31
+ res["x-pathinfo"].should.eq ""
32
32
 
33
33
  res = Rack::MockRequest.new(map).get("/foo/")
34
34
  res.should.ok?
35
- res["X-ScriptName"].should.eq "/foo"
36
- res["X-PathInfo"].should.eq "/"
35
+ res["x-scriptname"].should.eq "/foo"
36
+ res["x-pathinfo"].should.eq "/"
37
37
 
38
38
  res = Rack::MockRequest.new(map).get("/foo/bar")
39
39
  res.should.ok?
40
- res["X-ScriptName"].should.eq "/foo/bar"
41
- res["X-PathInfo"].should.eq ""
40
+ res["x-scriptname"].should.eq "/foo/bar"
41
+ res["x-pathinfo"].should.eq ""
42
42
 
43
43
  res = Rack::MockRequest.new(map).get("/foo/bar/")
44
44
  res.should.ok?
45
- res["X-ScriptName"].should.eq "/foo/bar"
46
- res["X-PathInfo"].should.eq "/"
45
+ res["x-scriptname"].should.eq "/foo/bar"
46
+ res["x-pathinfo"].should.eq "/"
47
47
 
48
48
  res = Rack::MockRequest.new(map).get("/foo///bar//quux")
49
49
  res.status.should.eq 200
50
50
  res.should.ok?
51
- res["X-ScriptName"].should.eq "/foo/bar"
52
- res["X-PathInfo"].should.eq "//quux"
51
+ res["x-scriptname"].should.eq "/foo/bar"
52
+ res["x-pathinfo"].should.eq "//quux"
53
53
 
54
54
  res = Rack::MockRequest.new(map).get("/foo/quux", "SCRIPT_NAME" => "/bleh")
55
55
  res.should.ok?
56
- res["X-ScriptName"].should.eq "/bleh/foo"
57
- res["X-PathInfo"].should.eq "/quux"
56
+ res["x-scriptname"].should.eq "/bleh/foo"
57
+ res["x-pathinfo"].should.eq "/quux"
58
58
 
59
59
  res = Rack::MockRequest.new(map).get("/bar", 'HTTP_HOST' => 'foo.org')
60
60
  res.should.ok?
61
- res["X-ScriptName"].should.eq "/bar"
62
- res["X-PathInfo"].should.empty?
61
+ res["x-scriptname"].should.eq "/bar"
62
+ res["x-pathinfo"].should.empty?
63
63
 
64
64
  res = Rack::MockRequest.new(map).get("/bar/", 'HTTP_HOST' => 'foo.org')
65
65
  res.should.ok?
66
- res["X-ScriptName"].should.eq "/bar"
67
- res["X-PathInfo"].should.eq '/'
66
+ res["x-scriptname"].should.eq "/bar"
67
+ res["x-pathinfo"].should.eq '/'
68
68
  end
69
69
 
70
70
  would "dispatches hosts correctly" do
71
71
  map = Rack::Lint.new(Jellyfish::URLMap.new("http://foo.org/" => lambda { |env|
72
72
  [200,
73
- { "Content-Type" => "text/plain",
74
- "X-Position" => "foo.org",
75
- "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
73
+ { "content-type" => "text/plain",
74
+ "x-position" => "foo.org",
75
+ "x-host" => env["HTTP_HOST"] || env["SERVER_NAME"],
76
76
  }, [""]]},
77
77
  "http://subdomain.foo.org/" => lambda { |env|
78
78
  [200,
79
- { "Content-Type" => "text/plain",
80
- "X-Position" => "subdomain.foo.org",
81
- "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
79
+ { "content-type" => "text/plain",
80
+ "x-position" => "subdomain.foo.org",
81
+ "x-host" => env["HTTP_HOST"] || env["SERVER_NAME"],
82
82
  }, [""]]},
83
83
  "http://bar.org/" => lambda { |env|
84
84
  [200,
85
- { "Content-Type" => "text/plain",
86
- "X-Position" => "bar.org",
87
- "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
85
+ { "content-type" => "text/plain",
86
+ "x-position" => "bar.org",
87
+ "x-host" => env["HTTP_HOST"] || env["SERVER_NAME"],
88
88
  }, [""]]},
89
89
  "/" => lambda { |env|
90
90
  [200,
91
- { "Content-Type" => "text/plain",
92
- "X-Position" => "default.org",
93
- "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
91
+ { "content-type" => "text/plain",
92
+ "x-position" => "default.org",
93
+ "x-host" => env["HTTP_HOST"] || env["SERVER_NAME"],
94
94
  }, [""]]}
95
95
  ))
96
96
 
97
97
  res = Rack::MockRequest.new(map).get("/")
98
98
  res.should.ok?
99
- res["X-Position"].should.eq "default.org"
99
+ res["x-position"].should.eq "default.org"
100
100
 
101
101
  res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "bar.org")
102
102
  res.should.ok?
103
- res["X-Position"].should.eq "bar.org"
103
+ res["x-position"].should.eq "bar.org"
104
104
 
105
105
  res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "foo.org")
106
106
  res.should.ok?
107
- res["X-Position"].should.eq "foo.org"
107
+ res["x-position"].should.eq "foo.org"
108
108
 
109
109
  res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "subdomain.foo.org", "SERVER_NAME" => "foo.org")
110
110
  res.should.ok?
111
- res["X-Position"].should.eq "subdomain.foo.org"
111
+ res["x-position"].should.eq "subdomain.foo.org"
112
112
 
113
113
  res = Rack::MockRequest.new(map).get("http://foo.org/")
114
114
  res.should.ok?
115
- res["X-Position"].should.eq "foo.org"
115
+ res["x-position"].should.eq "foo.org"
116
116
 
117
117
  res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "example.org")
118
118
  res.should.ok?
119
- res["X-Position"].should.eq "default.org"
119
+ res["x-position"].should.eq "default.org"
120
120
 
121
121
  res = Rack::MockRequest.new(map).get("/",
122
122
  "HTTP_HOST" => "example.org:9292",
123
123
  "SERVER_PORT" => "9292")
124
124
  res.should.ok?
125
- res["X-Position"].should.eq "default.org"
125
+ res["x-position"].should.eq "default.org"
126
126
  end
127
127
 
128
128
  would "be nestable" do
@@ -130,10 +130,10 @@ describe Jellyfish::URLMap do
130
130
  Jellyfish::URLMap.new("/bar" =>
131
131
  Jellyfish::URLMap.new("/quux" => lambda { |env|
132
132
  [200,
133
- { "Content-Type" => "text/plain",
134
- "X-Position" => "/foo/bar/quux",
135
- "X-PathInfo" => env["PATH_INFO"],
136
- "X-ScriptName" => env["SCRIPT_NAME"],
133
+ { "content-type" => "text/plain",
134
+ "x-position" => "/foo/bar/quux",
135
+ "x-pathinfo" => env["PATH_INFO"],
136
+ "x-scriptname" => env["SCRIPT_NAME"],
137
137
  }, [""]]}
138
138
  ))))
139
139
 
@@ -142,97 +142,97 @@ describe Jellyfish::URLMap do
142
142
 
143
143
  res = Rack::MockRequest.new(map).get("/foo/bar/quux")
144
144
  res.should.ok?
145
- res["X-Position"].should.eq "/foo/bar/quux"
146
- res["X-PathInfo"].should.eq ""
147
- res["X-ScriptName"].should.eq "/foo/bar/quux"
145
+ res["x-position"].should.eq "/foo/bar/quux"
146
+ res["x-pathinfo"].should.eq ""
147
+ res["x-scriptname"].should.eq "/foo/bar/quux"
148
148
  end
149
149
 
150
150
  would "route root apps correctly" do
151
151
  map = Rack::Lint.new(Jellyfish::URLMap.new("/" => lambda { |env|
152
152
  [200,
153
- { "Content-Type" => "text/plain",
154
- "X-Position" => "root",
155
- "X-PathInfo" => env["PATH_INFO"],
156
- "X-ScriptName" => env["SCRIPT_NAME"]
153
+ { "content-type" => "text/plain",
154
+ "x-position" => "root",
155
+ "x-pathinfo" => env["PATH_INFO"],
156
+ "x-scriptname" => env["SCRIPT_NAME"]
157
157
  }, [""]]},
158
158
  "/foo" => lambda { |env|
159
159
  [200,
160
- { "Content-Type" => "text/plain",
161
- "X-Position" => "foo",
162
- "X-PathInfo" => env["PATH_INFO"],
163
- "X-ScriptName" => env["SCRIPT_NAME"]
160
+ { "content-type" => "text/plain",
161
+ "x-position" => "foo",
162
+ "x-pathinfo" => env["PATH_INFO"],
163
+ "x-scriptname" => env["SCRIPT_NAME"]
164
164
  }, [""]]}
165
165
  ))
166
166
 
167
167
  res = Rack::MockRequest.new(map).get("/foo/bar")
168
168
  res.should.ok?
169
- res["X-Position"].should.eq "foo"
170
- res["X-PathInfo"].should.eq "/bar"
171
- res["X-ScriptName"].should.eq "/foo"
169
+ res["x-position"].should.eq "foo"
170
+ res["x-pathinfo"].should.eq "/bar"
171
+ res["x-scriptname"].should.eq "/foo"
172
172
 
173
173
  res = Rack::MockRequest.new(map).get("/foo")
174
174
  res.should.ok?
175
- res["X-Position"].should.eq "foo"
176
- res["X-PathInfo"].should.eq ""
177
- res["X-ScriptName"].should.eq "/foo"
175
+ res["x-position"].should.eq "foo"
176
+ res["x-pathinfo"].should.eq ""
177
+ res["x-scriptname"].should.eq "/foo"
178
178
 
179
179
  res = Rack::MockRequest.new(map).get("/bar")
180
180
  res.should.ok?
181
- res["X-Position"].should.eq "root"
182
- res["X-PathInfo"].should.eq "/bar"
183
- res["X-ScriptName"].should.eq ""
181
+ res["x-position"].should.eq "root"
182
+ res["x-pathinfo"].should.eq "/bar"
183
+ res["x-scriptname"].should.eq ""
184
184
 
185
185
  res = Rack::MockRequest.new(map).get("")
186
186
  res.should.ok?
187
- res["X-Position"].should.eq "root"
188
- res["X-PathInfo"].should.eq "/"
189
- res["X-ScriptName"].should.eq ""
187
+ res["x-position"].should.eq "root"
188
+ res["x-pathinfo"].should.eq "/"
189
+ res["x-scriptname"].should.eq ""
190
190
  end
191
191
 
192
192
  would "not squeeze slashes" do
193
193
  map = Rack::Lint.new(Jellyfish::URLMap.new("/" => lambda { |env|
194
194
  [200,
195
- { "Content-Type" => "text/plain",
196
- "X-Position" => "root",
197
- "X-PathInfo" => env["PATH_INFO"],
198
- "X-ScriptName" => env["SCRIPT_NAME"]
195
+ { "content-type" => "text/plain",
196
+ "x-position" => "root",
197
+ "x-pathinfo" => env["PATH_INFO"],
198
+ "x-scriptname" => env["SCRIPT_NAME"]
199
199
  }, [""]]},
200
200
  "/foo" => lambda { |env|
201
201
  [200,
202
- { "Content-Type" => "text/plain",
203
- "X-Position" => "foo",
204
- "X-PathInfo" => env["PATH_INFO"],
205
- "X-ScriptName" => env["SCRIPT_NAME"]
202
+ { "content-type" => "text/plain",
203
+ "x-position" => "foo",
204
+ "x-pathinfo" => env["PATH_INFO"],
205
+ "x-scriptname" => env["SCRIPT_NAME"]
206
206
  }, [""]]}
207
207
  ))
208
208
 
209
209
  res = Rack::MockRequest.new(map).get("/http://example.org/bar")
210
210
  res.should.ok?
211
- res["X-Position"].should.eq "root"
212
- res["X-PathInfo"].should.eq "/http://example.org/bar"
213
- res["X-ScriptName"].should.eq ""
211
+ res["x-position"].should.eq "root"
212
+ res["x-pathinfo"].should.eq "/http://example.org/bar"
213
+ res["x-scriptname"].should.eq ""
214
214
  end
215
215
 
216
216
  would "not be case sensitive with hosts" do
217
217
  map = Rack::Lint.new(Jellyfish::URLMap.new("http://example.org/" => lambda { |env|
218
218
  [200,
219
- { "Content-Type" => "text/plain",
220
- "X-Position" => "root",
221
- "X-PathInfo" => env["PATH_INFO"],
222
- "X-ScriptName" => env["SCRIPT_NAME"]
219
+ { "content-type" => "text/plain",
220
+ "x-position" => "root",
221
+ "x-pathinfo" => env["PATH_INFO"],
222
+ "x-scriptname" => env["SCRIPT_NAME"]
223
223
  }, [""]]}
224
224
  ))
225
225
 
226
226
  res = Rack::MockRequest.new(map).get("http://example.org/")
227
227
  res.should.ok?
228
- res["X-Position"].should.eq "root"
229
- res["X-PathInfo"].should.eq "/"
230
- res["X-ScriptName"].should.eq ""
228
+ res["x-position"].should.eq "root"
229
+ res["x-pathinfo"].should.eq "/"
230
+ res["x-scriptname"].should.eq ""
231
231
 
232
232
  res = Rack::MockRequest.new(map).get("http://EXAMPLE.ORG/")
233
233
  res.should.ok?
234
- res["X-Position"].should.eq "root"
235
- res["X-PathInfo"].should.eq "/"
236
- res["X-ScriptName"].should.eq ""
234
+ res["x-position"].should.eq "root"
235
+ res["x-pathinfo"].should.eq "/"
236
+ res["x-scriptname"].should.eq ""
237
237
  end
238
238
  end
@@ -38,7 +38,7 @@ describe 'Sinatra base_test.rb' do
38
38
 
39
39
  describe 'Jellyfish as a Rack middleware' do
40
40
  inner_app ||= lambda{ |env|
41
- [210, {'X-Downstream' => 'true'}, ['Hello from downstream']]
41
+ [210, {'x-downstream' => 'true'}, ['Hello from downstream']]
42
42
  }
43
43
 
44
44
  app = Class.new{
@@ -55,7 +55,7 @@ describe 'Sinatra base_test.rb' do
55
55
  end
56
56
 
57
57
  get '/explicit-forward' do
58
- headers_merge 'X-Middleware' => 'true'
58
+ headers_merge 'x-middleware' => 'true'
59
59
  status, headers, _ = jellyfish.app.call(env)
60
60
  self.status status
61
61
  self.headers headers
@@ -80,14 +80,14 @@ describe 'Sinatra base_test.rb' do
80
80
  would 'forward requests downstream when no matching route found' do
81
81
  status, headers, body = get('/missing', app)
82
82
  status .should.eq 210
83
- headers['X-Downstream'].should.eq 'true'
83
+ headers['x-downstream'].should.eq 'true'
84
84
  body .should.eq ['Hello from downstream']
85
85
  end
86
86
 
87
87
  would 'call the downstream app directly and return result' do
88
88
  status, headers, body = get('/low-level-forward', app)
89
89
  status .should.eq 210
90
- headers['X-Downstream'].should.eq 'true'
90
+ headers['x-downstream'].should.eq 'true'
91
91
  body .should.eq ['Hello from downstream']
92
92
  end
93
93
 
@@ -96,8 +96,8 @@ describe 'Sinatra base_test.rb' do
96
96
  get('/explicit-forward', Rack::ContentLength.new(app))
97
97
 
98
98
  status .should.eq 210
99
- headers['X-Downstream'] .should.eq 'true'
100
- headers['Content-Length'].should.eq '28'
99
+ headers['x-downstream'] .should.eq 'true'
100
+ headers['content-length'].should.eq '28'
101
101
  body.to_a .should.eq ['Hello after explicit forward']
102
102
  end
103
103
  end
@@ -70,7 +70,7 @@ describe 'Sinatra routing_test.rb' do
70
70
  app = Class.new{
71
71
  include Jellyfish
72
72
  get{
73
- self.headers 'Content-Type' => 'text/plain'
73
+ self.headers 'content-type' => 'text/plain'
74
74
  status, headers, body = jellyfish.app.call(env)
75
75
  self.status status
76
76
  self.body body
@@ -79,7 +79,7 @@ describe 'Sinatra routing_test.rb' do
79
79
  }.new(Class.new{
80
80
  include Jellyfish
81
81
  handle Jellyfish::NotFound do
82
- headers_merge 'Content-Type' => 'text/html'
82
+ headers_merge 'content-type' => 'text/html'
83
83
  status 404
84
84
  '<h1>Not Found</h1>'
85
85
  end
@@ -87,7 +87,7 @@ describe 'Sinatra routing_test.rb' do
87
87
 
88
88
  status, headers, body = get('/foo', app)
89
89
  status .should.eq 404
90
- headers['Content-Type'].should.eq 'text/html'
90
+ headers['content-type'].should.eq 'text/html'
91
91
  body .should.eq ['<h1>Not Found</h1>']
92
92
  end
93
93
 
@@ -30,7 +30,7 @@ describe 'from README.md' do
30
30
  sock = nil
31
31
  status, headers, body = File.open(File::NULL) do |input|
32
32
  app.call(
33
- 'HTTP_VERSION' => 'HTTP/1.1',
33
+ 'SERVER_PROTOCOL'=> 'HTTP/1.1',
34
34
  'REQUEST_METHOD' => method,
35
35
  'HTTP_HOST' => host,
36
36
  'PATH_INFO' => pinfo,
data/test/test_log.rb CHANGED
@@ -22,6 +22,7 @@ describe Jellyfish do
22
22
 
23
23
  def mock_log
24
24
  log = []
25
+ log.singleton_class.send(:public, :puts)
25
26
  mock(log).puts(is_a(String)){ |msg| log << msg }
26
27
  log
27
28
  end
@@ -35,6 +36,6 @@ describe Jellyfish do
35
36
  would "log_error to env['rack.errors']" do
36
37
  log = mock_log
37
38
  get('/log_error', app, 'rack.errors' => log)
38
- log.should.eq ['[Name] #<RuntimeError: RuntimeError> ["backtrace"]']
39
+ log.should.eq ['[Name] #<RuntimeError: RuntimeError> for /log_error ["backtrace"]']
39
40
  end
40
41
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jellyfish
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lin Jen-Shin (godfat)
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-11 00:00:00.000000000 Z
11
+ date: 2023-02-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |-
14
14
  Pico web framework for building API-centric web applications.
@@ -24,8 +24,8 @@ extensions: []
24
24
  extra_rdoc_files: []
25
25
  files:
26
26
  - ".gitignore"
27
+ - ".gitlab-ci.yml"
27
28
  - ".gitmodules"
28
- - ".travis.yml"
29
29
  - CHANGES.md
30
30
  - Gemfile
31
31
  - LICENSE
@@ -69,7 +69,7 @@ homepage: https://github.com/godfat/jellyfish
69
69
  licenses:
70
70
  - Apache-2.0
71
71
  metadata: {}
72
- post_install_message:
72
+ post_install_message:
73
73
  rdoc_options: []
74
74
  require_paths:
75
75
  - lib
@@ -84,9 +84,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
84
84
  - !ruby/object:Gem::Version
85
85
  version: '0'
86
86
  requirements: []
87
- rubyforge_project:
88
- rubygems_version: 2.7.8
89
- signing_key:
87
+ rubygems_version: 3.4.3
88
+ signing_key:
90
89
  specification_version: 4
91
90
  summary: Pico web framework for building API-centric web applications.
92
91
  test_files:
data/.travis.yml DELETED
@@ -1,18 +0,0 @@
1
- sudo: false
2
- language: ruby
3
-
4
- install: 'gem install bundler; bundle install --retry=3'
5
- script: 'ruby -vr bundler/setup -S rake test'
6
-
7
- matrix:
8
- include:
9
- - rvm: 2.3
10
- - rvm: 2.4
11
- - rvm: 2.5
12
- - rvm: ruby-head
13
- - rvm: jruby
14
- env: JRUBY_OPTS=--debug
15
- - rvm: rbx
16
-
17
- allow_failures:
18
- - rvm: rbx