syro 2.2.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +6 -0
  3. data/README.md +55 -2
  4. data/lib/syro.rb +36 -19
  5. data/syro.gemspec +2 -2
  6. data/test/all.rb +50 -14
  7. metadata +6 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0861a7a3ac07757e8fb462b0a61b5dc734cade04
4
- data.tar.gz: 3cba990483608d42a41c7b1f80e50dec57ef2945
3
+ metadata.gz: 26150785e6dd591e63f5e670b6dcc2a27dd01c08
4
+ data.tar.gz: ea5d9a93323838ee03e3ca140946cee52a8cf339
5
5
  SHA512:
6
- metadata.gz: 7f13c5c536db61588a19a5b45d49dcf9f48509e9b8a8deda5ccf95761b417523456f81f6d070518d0935ba2348cf5507d429f9437510f43d789ce2c07165c20a
7
- data.tar.gz: 9c0ef31436e67e67fa0def5e8b770bc838fb545cce5d636a1882216b4e6124a0206a707d5a9847f628861df9926dfcd3b4947be33bbdb4e0dd545c29d2107b53
6
+ metadata.gz: e07343b0890bf4820471ebe54a7947713956e506465b0b5eff37c42fbeb50b0bf0957f57693d34118b0dcbe40ccd669689d11d4f3263330f712bdb2a0eaf2739
7
+ data.tar.gz: 50a533a7933292c1b29fbcfd0bd8f8347128e7b6110ba97ce063939086cd86ffd52b2e4023e8800efee0aed43fa8f24a1a713a99317064140abbbdfc231acce6
data/CHANGELOG CHANGED
@@ -1,3 +1,9 @@
1
+ 3.0.0
2
+
3
+ * Change how status codes are set.
4
+ * Change how the Content-Type is set.
5
+ * Add Content-Type helpers to Syro::Response.
6
+
1
7
  2.2.0
2
8
 
3
9
  * Change gemspec to allow Rack 2.
data/README.md CHANGED
@@ -239,6 +239,61 @@ the command `run(Users)`, an inbox can be provided as the second
239
239
  argument: `run(Users, inbox)`. That allows apps to share previous
240
240
  captures.
241
241
 
242
+ Status code
243
+ -----------
244
+
245
+ By default the status code is set to `404`. If both path and request
246
+ method are matched, the status is automatically changed to `200`.
247
+ You can change the status code by assigning a number to `res.status`,
248
+ for example:
249
+
250
+ ```ruby
251
+ post do
252
+ ...
253
+ res.status = 201
254
+ end
255
+ ```
256
+
257
+ Content type
258
+ ------------
259
+
260
+ There's no default value for the content type header, but there's
261
+ a handy way of setting the desired value.
262
+
263
+ In order to write the body of the response, the `res.write` method
264
+ is used:
265
+
266
+ ```ruby
267
+ res.write "hello world"
268
+ ```
269
+
270
+ It has the drawback of leaving the `Content-Type` header empty.
271
+ Three alternative methods are provided, and more can be added by
272
+ using custom Decks.
273
+
274
+ Setting the Content-Type as `"text/plain"`:
275
+
276
+ ```ruby
277
+ res.text "hello world"
278
+ ```
279
+
280
+ Setting the Content-Type as `"text/html"`:
281
+
282
+ ```ruby
283
+ res.html "hello world"
284
+ ```
285
+
286
+ Setting the Content-Type as `"application/json"`:
287
+
288
+ ```ruby
289
+ res.json "hello world"
290
+ ```
291
+
292
+ Note that aside from writing the response body and setting the value
293
+ for the Content-Type header, no encoding or serialization takes
294
+ place. If you want to return a JSON encoded response, make sure to
295
+ encode the objects yourself (i.e., `res.json JSON.dump(...)`).
296
+
242
297
  Security
243
298
  --------
244
299
 
@@ -260,7 +315,6 @@ just use `Rack::Builder`:
260
315
 
261
316
  ```ruby
262
317
  App = Rack::Builder.new do
263
-
264
318
  use Rack::Session::Cookie, secret: "..."
265
319
 
266
320
  run Syro.new do
@@ -268,7 +322,6 @@ App = Rack::Builder.new do
268
322
  res.write("Hello, world")
269
323
  end
270
324
  end
271
-
272
325
  end
273
326
  ```
274
327
 
@@ -28,7 +28,12 @@ class Syro
28
28
 
29
29
  class Response
30
30
  LOCATION = "Location".freeze # :nodoc:
31
- DEFAULT = "text/html".freeze # :nodoc:
31
+
32
+ module ContentType
33
+ HTML = "text/html".freeze # :nodoc:
34
+ TEXT = "text/plain".freeze # :nodoc:
35
+ JSON = "application/json".freeze # :nodoc:
36
+ end
32
37
 
33
38
  # The status of the response.
34
39
  #
@@ -58,7 +63,7 @@ class Syro
58
63
  attr_reader :headers
59
64
 
60
65
  def initialize(headers = {})
61
- @status = nil
66
+ @status = 404
62
67
  @headers = headers
63
68
  @body = []
64
69
  @length = 0
@@ -103,6 +108,24 @@ class Syro
103
108
  @body << s
104
109
  end
105
110
 
111
+ # Write response body as text/plain
112
+ def text(str)
113
+ @headers[Rack::CONTENT_TYPE] = ContentType::TEXT
114
+ write(str)
115
+ end
116
+
117
+ # Write response body as text/html
118
+ def html(str)
119
+ @headers[Rack::CONTENT_TYPE] = ContentType::HTML
120
+ write(str)
121
+ end
122
+
123
+ # Write response body as application/json
124
+ def json(str)
125
+ @headers[Rack::CONTENT_TYPE] = ContentType::JSON
126
+ write(str)
127
+ end
128
+
106
129
  # Sets the `Location` header to `path` and updates the status to
107
130
  # `status`. By default, `status` is `302`.
108
131
  #
@@ -121,10 +144,10 @@ class Syro
121
144
  @status = status
122
145
  end
123
146
 
124
- # Returns an array with three elements: the status, headers and body.
125
- # If the status is not set, the status is set to 404 if empty body,
126
- # otherwise the status is set to 200 and updates the `Content-Type`
127
- # header to `text/html`.
147
+ # Returns an array with three elements: the status, headers and
148
+ # body. If the status is not set, the status is set to 404. If
149
+ # a match is found for both path and request method, the status
150
+ # is changed to 200.
128
151
  #
129
152
  # res.status = 200
130
153
  # res.finish
@@ -140,12 +163,6 @@ class Syro
140
163
  # # => [200, { "Content-Type" => "text/html" }, ["syro"]]
141
164
  #
142
165
  def finish
143
- @status ||= (@body.empty?) ? 404 : 200
144
-
145
- if @body.any?
146
- @headers[Rack::CONTENT_TYPE] ||= DEFAULT
147
- end
148
-
149
166
  [@status, @headers, @body]
150
167
  end
151
168
 
@@ -314,31 +331,31 @@ class Syro
314
331
  end
315
332
 
316
333
  def get
317
- root { yield } if req.get?
334
+ root { res.status = 200; yield } if req.get?
318
335
  end
319
336
 
320
337
  def put
321
- root { yield } if req.put?
338
+ root { res.status = 200; yield } if req.put?
322
339
  end
323
340
 
324
341
  def head
325
- root { yield } if req.head?
342
+ root { res.status = 200; yield } if req.head?
326
343
  end
327
344
 
328
345
  def post
329
- root { yield } if req.post?
346
+ root { res.status = 200; yield } if req.post?
330
347
  end
331
348
 
332
349
  def patch
333
- root { yield } if req.patch?
350
+ root { res.status = 200; yield } if req.patch?
334
351
  end
335
352
 
336
353
  def delete
337
- root { yield } if req.delete?
354
+ root { res.status = 200; yield } if req.delete?
338
355
  end
339
356
 
340
357
  def options
341
- root { yield } if req.options?
358
+ root { res.status = 200; yield } if req.options?
342
359
  end
343
360
  end
344
361
 
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "syro"
3
- s.version = "2.2.0"
3
+ s.version = "3.0.0"
4
4
  s.summary = "Simple router"
5
5
  s.description = "Simple router for web applications"
6
6
  s.authors = ["Michel Martens"]
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.files = `git ls-files`.split("\n")
12
12
 
13
13
  s.add_dependency "seg"
14
- s.add_dependency "rack", ">= 1.6.0"
14
+ s.add_dependency "rack", "~> 2"
15
15
  s.add_development_dependency "cutest"
16
16
  s.add_development_dependency "rack-test"
17
17
  end
@@ -6,9 +6,9 @@ class RackApp
6
6
  end
7
7
  end
8
8
 
9
- class TextualDeck < Syro::Deck
10
- def text(str)
11
- res[Rack::CONTENT_TYPE] = "text/plain"
9
+ class MarkdownDeck < Syro::Deck
10
+ def markdown(str)
11
+ res[Rack::CONTENT_TYPE] = "text/markdown"
12
12
  res.write(str)
13
13
  end
14
14
  end
@@ -41,9 +41,9 @@ class CustomRequestAndResponse < Syro::Deck
41
41
  end
42
42
  end
43
43
 
44
- textual = Syro.new(TextualDeck) do
44
+ markdown = Syro.new(MarkdownDeck) do
45
45
  get do
46
- text("GET /textual")
46
+ markdown("GET /markdown")
47
47
  end
48
48
  end
49
49
 
@@ -182,15 +182,15 @@ app = Syro.new do
182
182
  end
183
183
  end
184
184
 
185
- on "textual" do
186
- run(textual)
185
+ on "markdown" do
186
+ run(markdown)
187
187
  end
188
188
 
189
189
  on "headers" do
190
190
  run(default_headers)
191
191
  end
192
192
 
193
- on "json" do
193
+ on "custom" do
194
194
  run(json)
195
195
  end
196
196
 
@@ -198,6 +198,22 @@ app = Syro.new do
198
198
  res.status = 401
199
199
  res.write("Unauthorized")
200
200
  end
201
+
202
+ on "write" do
203
+ res.write "nil!"
204
+ end
205
+
206
+ on "text" do
207
+ res.text "plain!"
208
+ end
209
+
210
+ on "html" do
211
+ res.html "html!"
212
+ end
213
+
214
+ on "json" do
215
+ res.json "json!"
216
+ end
201
217
  end
202
218
 
203
219
  setup do
@@ -209,6 +225,10 @@ test "path + verb" do |f|
209
225
  assert_equal 200, f.last_response.status
210
226
  assert_equal "GET /foo/bar", f.last_response.body
211
227
 
228
+ f.get("/bar/baz")
229
+ assert_equal 404, f.last_response.status
230
+ assert_equal "", f.last_response.body
231
+
212
232
  f.put("/foo/bar")
213
233
  assert_equal 200, f.last_response.status
214
234
  assert_equal "PUT /foo/bar", f.last_response.body
@@ -267,7 +287,9 @@ end
267
287
  test "captures" do |f|
268
288
  f.get("/users/42")
269
289
  assert_equal "GET /users/42", f.last_response.body
270
- assert_equal 200, f.last_response.status
290
+
291
+ # As the verb was not mached, the status is 404.
292
+ assert_equal 404, f.last_response.status
271
293
  end
272
294
 
273
295
  test "post values" do |f|
@@ -306,9 +328,9 @@ test "redirect" do |f|
306
328
  end
307
329
 
308
330
  test "custom deck" do |f|
309
- f.get("/textual")
310
- assert_equal "GET /textual", f.last_response.body
311
- assert_equal "text/plain", f.last_response.headers["Content-Type"]
331
+ f.get("/markdown")
332
+ assert_equal "GET /markdown", f.last_response.body
333
+ assert_equal "text/markdown", f.last_response.headers["Content-Type"]
312
334
  assert_equal 200, f.last_response.status
313
335
  end
314
336
 
@@ -321,15 +343,29 @@ end
321
343
  test "custom request and response class" do |f|
322
344
  params = JSON.generate(foo: "foo")
323
345
 
324
- f.post("/json", params)
346
+ f.post("/custom", params)
325
347
 
326
348
  assert_equal params, f.last_response.body
327
349
  end
328
350
 
329
- test "set content type if body is set" do |f|
351
+ test "don't set content type by default" do |f|
330
352
  f.get("/private")
331
353
 
332
354
  assert_equal 401, f.last_response.status
333
355
  assert_equal "Unauthorized", f.last_response.body
356
+ assert_equal nil, f.last_response.headers["Content-Type"]
357
+ end
358
+
359
+ test "content type" do |f|
360
+ f.get("/write")
361
+ assert_equal nil, f.last_response.headers["Content-Type"]
362
+
363
+ f.get("/text")
364
+ assert_equal "text/plain", f.last_response.headers["Content-Type"]
365
+
366
+ f.get("/html")
334
367
  assert_equal "text/html", f.last_response.headers["Content-Type"]
368
+
369
+ f.get("/json")
370
+ assert_equal "application/json", f.last_response.headers["Content-Type"]
335
371
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: syro
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michel Martens
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-01 00:00:00.000000000 Z
11
+ date: 2017-02-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: seg
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: rack
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 1.6.0
33
+ version: '2'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 1.6.0
40
+ version: '2'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: cutest
43
43
  requirement: !ruby/object:Gem::Requirement