jellyfish 1.3.0 → 1.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8f9e1adde462fe63f752d02b74395426c74022f9e8fb920ecf089a4b3bb20624
4
- data.tar.gz: 2c4fea5a52568b9bd153c95f67c02a722634ad32177733be4c7941686eb9bfed
3
+ metadata.gz: a2ac4c1c5b9beff9266516aa120e637e7c1b3d09010e0f0cf0df7b8728e26646
4
+ data.tar.gz: 8cd5fff611eea7b8fc454aa8a4d2a844225cf2904d6fcf46dacfc118f9090d84
5
5
  SHA512:
6
- metadata.gz: 428fb54496fb53eb2efc363f37d0ad2b7b889edb23c3a40a22cd1acc52f20348015b8193a8d92967a9f8da1716903b68ff672ff581e4e68411d8b017b6a6a3ca
7
- data.tar.gz: 20db48c00b68b9cb4bb3499e3a0bf8bee223f71f0f48312c16a1eeb21481cb5cb2865a2ec2331412ffcf4e88e9bfa4da4a5bc81e6a2ca206b6df4d8b211b61be
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,26 @@
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
+
18
+ ## Jellyfish 1.3.1 -- 2018-11-11
19
+
20
+ ### Bugs fixed
21
+
22
+ * Fixed `Jellyfish::Rewrite` for SCRIPT_NAME when host is also used.
23
+
3
24
  ## Jellyfish 1.3.0 -- 2018-11-11
4
25
 
5
26
  ### Incompatible changes
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.0 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.0"
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,
@@ -31,7 +31,7 @@ module Jellyfish
31
31
 
32
32
  def map path, to: nil, host: nil, &block
33
33
  key = if host then "http://#{File.join(host, path)}" else path end
34
- (@map ||= {})[key] = [block, to]
34
+ (@map ||= {})[key] = [block, path, to]
35
35
  end
36
36
 
37
37
  def listen host, &block
@@ -56,8 +56,8 @@ module Jellyfish
56
56
  private
57
57
  def generate_map current_map, app
58
58
  mapped = if app then {'' => app} else {} end
59
- current_map.each do |path, (block, to)|
60
- mapped[path] = self.class.app(app, path, to, &block)
59
+ current_map.each do |path, (block, from, to)|
60
+ mapped[path] = self.class.app(app, from, to, &block)
61
61
  end
62
62
  URLMap.new(mapped)
63
63
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Jellyfish
4
- VERSION = '1.3.0'
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
data/test/test_rewrite.rb CHANGED
@@ -41,4 +41,18 @@ describe Jellyfish::Rewrite do
41
41
  expect(call(app, '/top/from/inner')).eq '/top!/to/inner'
42
42
  expect(call(app, '/top/from/outer')).eq '/top!/to/outer'
43
43
  end
44
+
45
+ would 'map to with host and handle SCRIPT_NAME properly' do
46
+ app = Jellyfish::Builder.app do
47
+ map '/path', to: '/path', host: 'host' do
48
+ run lambda{ |env|
49
+ [200, {},
50
+ ["#{env['HTTP_HOST']} #{env['SCRIPT_NAME']} #{env['PATH_INFO']}"]]
51
+ }
52
+ end
53
+ end
54
+
55
+ expect(get('/path', app, 'HTTP_HOST' => 'host').dig(-1, -1)).
56
+ eq 'host /path'
57
+ end
44
58
  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.0
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