tynn 2.0.0.beta3 → 2.0.0.beta4

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
  SHA1:
3
- metadata.gz: 1f568dca09bcd12ce698740d952349f3fd5b8384
4
- data.tar.gz: bf36f7702d0a0eb6c0684a67429cac3c98b8595c
3
+ metadata.gz: 4098115e1a01a01f10ae4209a2ffa63d9296cee4
4
+ data.tar.gz: f7f7fa51ec9c4ac2202f68f2f6425b33454ff46a
5
5
  SHA512:
6
- metadata.gz: 5791a202646ee5e484d2606da3aa0fec2f9f9c547092fbe3df39e748997b966f3348ad4055654924988967c1af4c5e35f8f4ce07caa57c322595a694e0240b26
7
- data.tar.gz: 4c983c263c8c4c0f87317cf3ceda25fbfe63a3cd3dbcb4250d9986d9dad3f52984e971d3ded76d5ef4b0b76fa148c2a6c1bb8020d0476c045ad4374afa3cb478
6
+ metadata.gz: 28661462ba5afd767a7da093852c67093e18449b63bee21bca0d302c3c632f0c1fe3f709847a12bcb46bcb4a1652babe5f64080e32131f3d0fcd03a09232d4ce
7
+ data.tar.gz: 3c01a710785c25eceba0af49791c3b265daff653d4107b8bd6029bafcdc45f16a9945eb0ae5430cb0ccce4669e257b92f0f9ddebfaa8c897a04acc98368ae349
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015-2016 Francesco Rodríguez and contributors
3
+ Copyright (c) 2015-2016 Francesco Rodriguez
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,96 +1,29 @@
1
1
  # Tynn
2
2
 
3
3
  [![Build Status](https://travis-ci.org/frodsan/tynn.svg?branch=master)](https://travis-ci.org/frodsan/tynn)
4
+ [![Documentation Status](https://readthedocs.org/projects/tynn/badge/?version=latest)](http://tynn.xyz/en/latest/?badge=latest)
4
5
  [![Dependency Status](https://gemnasium.com/badges/github.com/frodsan/tynn.svg)](https://gemnasium.com/github.com/frodsan/tynn)
5
- [![Code Climate](https://codeclimate.com/github/frodsan/tynn/badges/gpa.svg)](https://codeclimate.com/github/frodsan/tynn)
6
-
7
- A thin library for web development in Ruby.
8
-
9
- * [Getting Started](#getting-started)
10
- * [Assumptions](#assumptions)
11
- * [Installation](#installation)
12
- * [Hello World!](#hello-world)
13
- * [Under the Hood](#under-the-hood)
14
- * [Tynn on Rack](#tynn-on-rack)
15
- * [Routing Basics](#routing-basics)
16
- * [HTTP Verbs](#http-verbs)
17
- * [Matching path segments](#matching-path-segments)
18
- * [Capturing path segments](#capturing-path-segments)
19
- * [Matching more than paths](#matching-more-than-paths)
20
- * [Routing rules](#routing-rules)
21
- * [Composing Applications](#composing-applications)
22
- * [Managing Request and Response](#managing-request-and-response)
23
- * [Accessing Request Parameters](#accessing-request-parameters)
24
- * [Setting a Status Code](#setting-a-status-code)
25
- * [Writting to the Response Body](#writting-to-the-response-body)
26
- * [Setting HTTP Headers](#setting-http-headers)
27
- * [Redirecting a Request](#redirecting-a-request)
28
- * [Halting a Request](#halting-a-request)
29
- * [Extending Tynn](#extending-tynn)
30
- * [Middleware](#middleware)
31
- * [Plugins](#plugins)
32
- * [Settings](#settings)
33
- * [Default Plugins](#default-plugins)
34
- * [Environments](#environments)
35
- * [Method Override](#method-override)
36
- * [JSON](#json)
37
- * [Rendering Templates](#rendering-templates)
38
- * [Static Files](#static-files)
39
- * [Sessions](#sessions)
40
- * [Security](#security)
41
- * [Secure Headers](#secure-headers)
42
- * [HTTPS](#https)
43
- * [Testing](#testing)
44
- * [API Reference](http://api.tynn.xyz/2.0.0)
45
- * [Troubleshooting](#troubleshooting)
46
- * [Application handler is missing](#missing_handler)
47
- * [Application middleware is frozen](#frozen_middleware)
48
- * [Secret key is required](#no_secret_key)
49
- * [Secret key is shorter than 30 characters](#short_secret_key)
50
- * [Changelog](#changelog)
51
- * [Development](#development)
52
- * [Contributing](#contributing)
53
- * [Build History](#build-history)
54
- * [License](#license)
55
-
56
- **NOTE. There is an online version of this README at http://tynn.xyz/.**
57
6
 
58
- ## Getting Started
59
-
60
- Tynn is a minimal and flexible library for building JSON web services and web applications in Ruby. It's designed with two main goals: simplicity and extensibility.
61
-
62
- Tynn offers the essentials to handle HTTP requests and also includes mechanisms to easily extend its functionality through [plugins](#plugins) and [middleware][middleware]. Tynn ships with a set of [default plugins](#default-plugins) that you can combine to meet your needs.
63
-
64
- Tynn is not a framework. There is no built-in support for connecting to databases or a common application architecture. This gives you the freedom to choose the appropiate tools for the job at hand.
65
-
66
- Like most web libraries in Ruby, Tynn is built on top of [Rack], a Ruby webserver interface. Because of this, it has the benefits of using existing libraries and a variety of web servers for free.
7
+ Tynn is a simple and flexible library for building JSON web services and web applications in Ruby.
67
8
 
68
- Tynn takes design cues from other web libraries like [Rails], [Sinatra], and [Cuba].
9
+ ## Installation
69
10
 
70
- ### Assumptions
71
-
72
- This section serves as a high-level introduction to the core features of Tynn. It also covers installation and walks through the creation of a simple application. To get the most out of it, it's recommended to have a basic knowledge about Ruby and HTTP.
73
-
74
- ### Installation
75
-
76
- Installing Tynn is pretty straightforward. From the command line, use the `gem` command:
11
+ Installing Tynn is pretty straightforward:
77
12
 
78
13
  ```
79
14
  $ gem install tynn
80
15
  ```
81
16
 
82
- If you prefer to use [Bundler] instead, set up the environment with:
17
+ If you prefer to use [Bundler](http://bundler.io/) instead, set up the environment with:
83
18
 
84
- ```
19
+ ```ruby
85
20
  $ bundle init
86
21
  ```
87
22
 
88
- Then, update the contents of the generated Gemfile to:
23
+ Then, add this line to the generated Gemfile:
89
24
 
90
25
  ```ruby
91
- source "https://rubygems.org"
92
-
93
- gem "tynn", "~> 2.0"
26
+ gem "tynn"
94
27
  ```
95
28
 
96
29
  Finally, install the dependencies with:
@@ -99,673 +32,163 @@ Finally, install the dependencies with:
99
32
  $ bundle install
100
33
  ```
101
34
 
102
- Now you can create your first Tynn app!
103
-
104
- ### Hello World!
35
+ ## Hello World!
105
36
 
106
- Let's start with a minimal application. Open your preferred text editor and enter the following code:
37
+ Here's a minimal application:
107
38
 
108
39
  ```ruby
40
+ # config.ru
109
41
  require "tynn"
110
42
 
111
- Tynn.define do
112
- on root? do
43
+ class MyApp < Tynn
44
+ define do
113
45
  on get do
114
46
  res.write("Hello World!")
115
47
  end
116
48
  end
117
49
  end
118
- ```
119
50
 
120
- Save this file as `app.rb`. Once you've done so, create another file called `config.ru` with the contents shown below:
121
-
122
- ```ruby
123
- require File.expand_path("app", __dir__)
124
-
125
- run(Tynn)
51
+ run(MyApp)
126
52
  ```
127
53
 
128
- You already have a functional application! The syntax is very readable, but we'll discuss the details in a moment. To see it in action, you need to start a web server. You can do this by typing `rackup` in the command line.
129
-
130
- ![Starting a Web Server](https://raw.githubusercontent.com/frodsan/tynn/master/docs/images/rackup.png)
131
-
132
- > **NOTE:** To stop the web server, hit `Ctrl+C` in the terminal window where it's running. To verify that the server has stopped you should see your command prompt cursor again.
133
-
134
- Now open a browser window and navigate to http://localhost:9292 to see the greeting message.
54
+ Start the application with:
135
55
 
136
- ![Hello World!](https://raw.githubusercontent.com/frodsan/tynn/master/docs/images/hello-world.png)
137
-
138
- ### Under the hood
139
-
140
- Tynn is all about routing. Routing determines how an application should respond to a client request to a URI (or path) and a specific HTTP request method. In our previous example, that would be the root path (`/`) and the HTTP GET method.
141
-
142
- To get a look on what's happening under the hood, let's see line 4:
143
-
144
- ```ruby
145
- on root? do
146
- # ...
147
- end
148
56
  ```
149
-
150
- That's a little taste of what we call routing matchers in Tynn. The purpose of the `on` matcher is to execute the given block only if the given argument returns `true`. In our case, `root?` returns `true` because we are accessing the root path (`/`) from our browser.
151
-
152
- One line below there is another type of matcher:
153
-
154
- ```ruby
155
- on get do
156
- res.write("Hello World!")
157
- end
57
+ $ rackup config.ru
158
58
  ```
159
59
 
160
- Tynn also includes methods for matching all the HTTP verbs (GET, POST, etc.). By default, if there are no other matchers before a verb matcher, it automatically checks that the current request is for the root path. The above example can be written as:
161
-
162
- ```ruby
163
- Tynn.define do
164
- on get do
165
- res.write("Hello World!")
166
- end
167
- end
168
- ```
169
-
170
- > **Note.** If you're not familiar with the HTTP methods, check out this [Wikipedia page](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods).
171
-
172
- ### Tynn on Rack
173
-
174
- The last part of the puzzle is the `config.ru` file. As we mentioned earlier, Tynn is built on top of Rack ... but what is Rack?
175
-
176
- Rack deals with HTTP requests. It provides a minimal interface between web servers supporting Ruby and Ruby web frameworks. Without Rack, Tynn would have to implement its own handler for each Ruby web server.
177
-
178
- To run the hello world application you used `rackup`, one of the tools that comes with Rack. To use `rackup`, you need to supply a `config.ru` file. This file connects the Rack interface with our Tynn application through the `run` method.
179
-
180
- ```ruby
181
- run(Tynn)
182
- ```
183
-
184
- Rack also figures out which server you have available in your system. When we used `rackup`, it fired up WEBrick, a web server built into Ruby by default.
185
-
186
- ```
187
- $ rackup
188
- [2016-05-14 00:25:11] INFO WEBrick 1.3.1
189
- ```
190
-
191
- Most popular web servers, like [Puma], [Unicorn] or [Thin], have built-in support for Rack, and thus support Tynn too. You can read more about Rack visiting their home page: http://rack.github.io/.
192
-
193
- ## Routing basics
194
-
195
- This section covers the routing features of Tynn, such as route definitions, composing applications, and so on.
196
-
197
- ### HTTP Verbs
198
-
199
- TODO.
200
-
201
- ### Matching path segments
202
-
203
- TODO.
204
-
205
- ### Capturing path segments
206
-
207
- TODO.
208
-
209
- ### Matching more than paths
210
-
211
- TODO.
212
-
213
- ### Routing rules
214
-
215
- TODO.
216
-
217
- ### Composing Applications
218
-
219
- TODO.
220
-
221
- ## Managing Request and Response
222
-
223
- This section covers the many features Tynn provides to handle requests and responses.
224
-
225
- ### Accessing Request Parameters
226
-
227
- TODO.
228
-
229
- ### Setting a Status Code
230
-
231
- TODO.
232
-
233
- ### Writting to the Response Body
234
-
235
- TODO.
60
+ Open a browser window and navigate to <http://localhost:9292> to see the greeting message:
236
61
 
237
- ### Setting HTTP Headers
62
+ ![Hello World!](https://raw.githubusercontent.com/frodsan/tynn/master/docs/images/hello-world.png)
238
63
 
239
- To set HTTP headers in the response, use the `res.headers` hash.
64
+ ## Features
240
65
 
241
- ```ruby
242
- Tynn.define do
243
- on get do
244
- res.headers["Content-Type"] = "application/json"
245
-
246
- res.write(JSON.generate(status: "ok"))
247
- end
248
- end
249
- ```
66
+ ### Routing
250
67
 
251
- Default headers for the application can be set through the `:default_headers` setting.
68
+ Tynn is all about routing. Routing determines how an application should respond to a client request to a URI (or path) and a specific HTTP request method.
252
69
 
253
70
  ```ruby
254
- Tynn.set(:default_headers, "Content-Type" => "application/json")
255
-
256
- Tynn.define do
71
+ MyApp.define do
257
72
  on get do
258
- res.write(JSON.generate(status: "ok"))
73
+ res.write("GET /")
259
74
  end
260
- end
261
- ```
262
-
263
- ### Redirecting a Request
264
-
265
- To redirect a request to a different location, use `res.redirect`.
266
-
267
- ```ruby
268
- res.redirect("/pricing")
269
- ```
270
-
271
- To redirect to a different site, use a fully-qualified URL.
272
-
273
- ```ruby
274
- res.redirect("https://google.com")
275
- ```
276
-
277
- By default, the status code is set to `302` (Found). To set a different status code, pass an integer as a second parameter.
278
-
279
- ```ruby
280
- res.redirect("/projects/1", 301)
281
- ```
282
-
283
- ### Halting a Request
284
-
285
- To immediately stop a request within a route, you can use the `halt` method.
286
-
287
- ```ruby
288
- halt([status, headers, body])
289
- ```
290
-
291
- Use `res.finish` to return a response as per Rack's specification.
292
-
293
- ```ruby
294
- if current_user.nil?
295
- res.redirect("/login")
296
-
297
- halt(res.finish)
298
- end
299
-
300
- # This won't be reached if current_user is nil
301
- ```
302
-
303
- ## Extending Tynn
304
-
305
- TODO.
306
75
 
307
- ### Middleware
308
-
309
- Tynn runs on [Rack](https://github.com/rack/rack). Therefore it is possible
310
- to use Rack middleware in Tynn. This is how you add a middleware (for example
311
- `YourMiddleware`) to your app:
312
-
313
- ```ruby
314
- Tynn.use(YourMiddleware)
315
- ```
316
-
317
- You can use any Rack middleware to your app, it is not specific to Tynn. You
318
- can find a list of Rack middleware [here][middleware].
319
-
320
- [middleware]: https://github.com/rack/rack/wiki/list-of-middleware
321
-
322
- ### Plugins
323
-
324
- A way to extend Tynn is to use the plugin API. A plugin is just a module which can contain any of the following rules:
325
-
326
- - If a `ClassMethods` module is defined, it extends the application class.
327
-
328
- - If a `InstanceMethods` module is defined, it's included in the application.
329
-
330
- - If a `setup` method is defined, it will be called last. This method can be used to configure the plugin.
331
-
332
- The following is a complete example of the plugin API.
333
-
334
- ```ruby
335
- require "valuta"
336
-
337
- module CurrencyHelper
338
- def self.setup(app, currency: "$")
339
- self.currency = currency
340
- end
341
-
342
- module ClassMethods
343
- def currency
344
- @currency
345
- end
346
-
347
- def currency=(currency)
348
- @currency = currency
76
+ on "posts" do
77
+ on get do
78
+ res.write("GET /posts")
349
79
  end
350
- end
351
80
 
352
- module InstanceMethods
353
- def to_currency(value)
354
- Valuta.convert(value, prefix: self.class.currency)
81
+ on post do
82
+ res.write("POST /posts")
355
83
  end
356
- end
357
- end
358
- ```
359
-
360
- To load the plugin into the application, use the `plugin` method.
361
-
362
- ```ruby
363
- App.plugin(CurrencyHelper, currency: "$")
364
- ```
365
-
366
- Here is the plugin in action:
367
-
368
- ```ruby
369
- App.currency # => "$"
370
-
371
- App.define do
372
- on get do
373
- res.write(to_currency(4567))
374
- end
375
- end
376
- # GET / => 200 $4,567
377
- ```
378
84
 
379
- ### Settings
85
+ on :id do |id|
86
+ @post = Post[id]
380
87
 
381
- Each application has a `settings` hash where configuration can be stored. By default, settings are inherited.
88
+ on post.nil? do
89
+ res.status = 404
90
+ res.write("Not found")
91
+ end
382
92
 
383
- ```ruby
384
- Tynn.set(:layout, "layout")
385
-
386
- class Guests < Tynn; end
387
- class Users < Tynn; end
388
- class Adminds < Tynn; end
389
-
390
- Users.set(:layout, "users/layout")
391
- Admins.set(:layout, "admins/layout")
392
-
393
- Guests.settings[:layout] # => "layout"
394
- Users.settings[:layout] # => "users/layout"
395
- Admins.settings[:layout] # => "admins/layout"
396
- ```
93
+ on get do
94
+ res.write("GET /posts/#{ @post.id }")
95
+ end
397
96
 
398
- This features comes in handy when authoring plugins.
97
+ on put do
98
+ res.write("PUT /posts/#{ @post.id }")
99
+ end
399
100
 
400
- ```ruby
401
- module CurrencyHelper
402
- module ClassMethods
403
- def currency=(currency)
404
- set(:currency, currency)
405
- end
101
+ on patch do
102
+ res.write("PATCH /posts/#{ @post.id }")
103
+ end
406
104
 
407
- def currency
408
- settings.fetch(:currency, "$")
105
+ on delete do
106
+ res.write("DELETE /posts/#{ @post.id }")
107
+ end
409
108
  end
410
109
  end
411
110
  end
412
111
  ```
413
112
 
414
- ## Default Plugins
415
-
416
- Tynn ships with a set of default plugins. The following sections cover the default plugins and extensions shipped with Tynn.
113
+ ### Composition
417
114
 
418
- ### Environments
419
-
420
- Tynn ships with [Tynn::Environment] to set and check the current environment for the application.
115
+ You can mount an application inside another. This adds the possibility to run modular applications.
421
116
 
422
117
  ```ruby
423
- require "tynn"
424
- require "tynn/environment"
425
-
426
- Tynn.plugin(Tynn::Environment)
427
- ```
428
-
429
- The default environment is based on the `RACK_ENV` environment variable.
430
-
431
- ```ruby
432
- ENV["RACK_ENV"]
433
- # => "test"
434
-
435
- Tynn.environment
436
- # => :test
437
- ```
438
-
439
- If `ENV["RACK_ENV"]` is `nil`, the default value is `:development`.
440
-
441
- ```ruby
442
- Tynn.environment
443
- # => :development
444
- ```
445
-
446
- To change the current environment, use the `environment=` method.
447
-
448
- ```ruby
449
- Tynn.environment = :development
450
-
451
- Tynn.environment
452
- # => :development
453
- ```
454
-
455
- To check the current environment, use: `development?`, `test?`,
456
- `production?` or `staging?`.
457
-
458
- ```ruby
459
- Tynn.plugin(Tynn::SSL) if Tynn.production?
460
- ```
461
-
462
- Perform operations on specific environments with the `configure` method.
463
-
464
- ```ruby
465
- Tynn.configure(:development) do |app|
466
- app.use(Tynn::Static, %w(/js /css /images))
118
+ class Posts < MyApp
467
119
  end
468
120
 
469
- Tynn.configure(:production) do |app|
470
- app.use(Tynn::SSL)
471
- end
472
- ```
473
-
474
- ### JSON
475
-
476
- Tynn ships with [Tynn::JSON] to serve JSON resources. It adds a helper method, called `json`, that generates a JSON document and writes it to the response body. This also automatically sets the content type header to `application/json`.
477
-
478
- ```ruby
479
- require "tynn"
480
- require "tynn/json"
481
-
482
- Tynn.define do
483
- on "array" do
484
- on get do
485
- json(["foo", "bar", "baz"])
486
- end
121
+ Posts.define do
122
+ on get do
123
+ res.write("GET /posts")
487
124
  end
488
125
 
489
- on "object" do
490
- on get do
491
- json(foo: "bar")
492
- end
493
- end
126
+ # ...
494
127
  end
495
- ```
496
-
497
- ### Rendering Templates
498
-
499
- TODO.
500
-
501
- ### Method Override
502
-
503
- HTML Forms only support GET and POST requests. To perform other actions such as PUT, PATCH or DELETE, use the [Rack::MethodOverride] middleware. Note that there is no need to add any new dependencies to the application as it's included in Rack already.
504
128
 
505
- ```ruby
506
- Tynn.use(Rack::MethodOverride)
507
- ```
508
-
509
- This uses a POST form to simulate a request with a non-supported method. In order to succeed, a hidden input field, with the name `_method` and the method name as the value, needs to be included. The following example simulates a PUT
510
- request.
511
-
512
- ```html
513
- <form method="POST" action="/posts/1">
514
- <input type="hidden" name="_method" value="PUT">
515
- <!-- ... -->
516
- </form>
517
- ```
518
-
519
- Now, this will trigger the `put` matcher in the application.
520
-
521
- ```ruby
522
- Posts.define do
523
- on put do
524
- post.update(req.params["post"])
129
+ MyApp.define do
130
+ on "posts" do
131
+ run(Posts)
525
132
  end
526
133
  end
527
134
  ```
528
135
 
529
- ### Static Files
530
-
531
- Tynn ships with [Tynn::Static] to serve static files such as images, CSS, JavaScript and others.
532
-
533
- ```ruby
534
- require "tynn"
535
- require "tynn/static"
536
-
537
- Tynn.plugin(Tynn::Static, %w(/js /css /images))
538
- ```
539
-
540
- By default, static files are served from the folder `public` in the current directory. You can specify a different location by passing the `:root` option:
541
-
542
- ```ruby
543
- Tynn.plugin(Tynn::Static, %w(/js /css /images), root: "assets")
544
- ```
545
-
546
- As you can see in the table below, the name of static directory is not included in the URL because the files are looked up relative to that directory.
547
-
136
+ Settings and extensions are inherited by the subclasses.
548
137
 
549
- | File | URL |
550
- | ---------------------------- | -------------------------------------- |
551
- | ./public/js/application.js | http://example.org/js/application.js |
552
- | ./public/css/application.css | http://example.org/css/application.css |
553
- | ./public/images/logo.png | http://example.org/images/logo.png |
138
+ ### Plugins & Middleware
554
139
 
555
- It's important to mention that the path of the static directory path is relative to the directory where you run the application. If you run the application from another directory, it's safer to use an absolute path:
556
-
557
- ```ruby
558
- Tynn.plugin(
559
- Tynn::Static,
560
- %w(/js /css /images),
561
- root: File.expand_path("public", __dir__)
562
- )
563
- ```
564
-
565
- ### Sessions
566
-
567
- TODO.
568
-
569
- ## Security
570
-
571
- Many of the default plugins include secure default options. Here are some plugins that can improve the security of your web application.
572
-
573
- ### Secure Headers
574
-
575
- Tynn ships with the [Tynn::SecureHeaders] plugin.
140
+ Tynn includes mechanisms to easily extend its functionality through plugins and middleware. It also ships with a set of [default plugins][documentation] that you can combine to meet your needs:
576
141
 
577
142
  ```ruby
578
143
  require "tynn"
144
+ require "tynn/environments"
145
+ require "tynn/json"
579
146
  require "tynn/secure_headers"
147
+ require "tynn/ssl"
580
148
 
581
- Tynn.plugin(Tynn::SecureHeaders)
582
- ```
583
-
584
- This plugins adds the following security related HTTP headers to each response.
585
-
586
- - **X-Content-Type-Options:** Prevents IE and Chrome from [Content Type Sniffing][sniffing]. Defaults to `"nosniff"`.
587
-
588
- - **X-Frame-Options:** Provides [Clickjacking] protection. Defaults to `"deny"`.
589
-
590
- - **X-XSS-Protection:** Enables the XSS protection filter built into IE, Chrome and Safari. This filter is usually enabled by default, the use of this header is to re-enable it if it was turned off by the user. Defaults to `"1; mode=block"</tt`.
591
-
592
- You can configure the default headers through the `:default_headers` setting.
593
-
594
- ```ruby
595
- Tynn.set(:default_headers, {
596
- "X-Frame-Options" => "sameorigin"
597
- })
598
- ```
599
-
600
- ### HTTTPS
601
-
602
- TODO.
603
-
604
- ## Testing
605
-
606
- Tynn ships with [Tynn::Test], a simple helper class to simulate requests to your application.
607
-
608
- ```ruby
609
- require "tynn"
610
- require "tynn/test"
611
-
612
- Tynn.define do
613
- on get do
614
- res.write("hei")
615
- end
149
+ class MyApp < Tynn
150
+ plugin(Tynn::Environments)
151
+ plugin(Tynn::JSON)
152
+ plugin(Tynn::SecureHeaders)
153
+ plugin(Tynn::SSL, Tynn.production?)
616
154
  end
617
155
 
618
- ts = Tynn::Test.new
619
- ts.get("/")
620
-
621
- 200 == ts.res.status # => true
622
- "hei" == ts.res.body.join # => true
623
- ```
624
-
625
- [Tynn::Test] is test-framework agnostic. The following example uses [Minitest]:
626
-
627
- ```ruby
628
- require "minitest/autorun"
629
- require "tynn/test"
630
-
631
- class GuestsRouteTest < Minitest::Test
632
- def setup
633
- @ts = Tynn::Test.new
634
- end
635
-
636
- def test_home
637
- @ts.get("/")
638
-
639
- assert_equal 200, @ts.res.status
640
- assert_equal "Hello World!", @ts.res.body.join
641
- assert_equal "text/html", @ts.res.headers["Content-Type"]
156
+ MyApp.define do
157
+ on get do
158
+ json(message: "Hello World!")
642
159
  end
643
160
  end
644
161
  ```
645
162
 
646
- If this is not of your flavor, you can use any Rack-based testing library or framework, like: [Rack::Test] or [Capybara].
647
-
648
- ## Troubleshooting
649
-
650
- If you have problems with running Tynn, see below or [ask in GitHub Issues](https://github.com/frodsan/tynn/issues/new).
651
-
652
- * <a name="missing_handler"></a>
653
- **Application handler is missing**
654
- <sup>[[link](#missing_handler)]</sup>
655
-
656
- Application handler is probably not set. Try `#define`:
657
-
658
- ```ruby
659
- MyApp.define do
660
- # ...
661
- end
662
-
663
- run(MyApp)
664
- ```
665
-
666
- * <a name="frozen_middleware"></a>
667
- **Application middleware is frozen**
668
- <sup>[[link](#frozen_middleware)]</sup>
669
-
670
- Application middleware is frozen when application handler is set. Please, set the middleware before setting the application handler.
671
-
672
- ```ruby
673
- # bad
674
- MyApp.define do
675
- # ...
676
- end
677
-
678
- MyApp.use(Middleware)
679
-
680
- # good
681
- MyApp.use(Middleware)
163
+ Tynn includes plugins to manage sessions, serve static files, render view templates, and so on.
682
164
 
683
- MyApp.define do
684
- # ...
685
- end
686
- ```
687
-
688
- * <a name="no_secret_key"></a>
689
- **Secret key is required**
690
- <sup>[[link](#no_secret_key)]</sup>
691
-
692
- [Tynn::Session] uses a secret key to sign the cookie's data, thus unauthorized means can't alter it. Please, add the secret option to your code:
693
-
694
- ```ruby
695
- MyApp.plugin(Tynn::Session, secret: "__change_me__", ...)
696
- ```
697
-
698
- If you're sharing your code publicly, make sure the secret key is kept private. Knowing the secret allows an attacker to tamper the data. You can use environment variables to store the secret key:
699
-
700
- ```ruby
701
- MyApp.plugin(Tynn::Session, secret: ENV.fetch("SESSION_SECRET"), ...)
702
- ```
703
-
704
- * <a name="short_secret_key"></a>
705
- **Secret key is shorter than 30 characters**
706
- <sup>[[link](#short_secret_key)]</sup>
707
-
708
- The secret provided is shorter than the minimum length. Make sure the secret is long and all random. You can generate a secure secret key with:
709
-
710
- ```
711
- $ ruby -r securerandom -e "puts SecureRandom.hex(64)"
712
- 929234f24e8c7450166a88142a...
713
- ```
165
+ ### Rack Ecosystem
714
166
 
715
- ## Changelog
167
+ Like most web libraries in Ruby, Tynn is built on top of [Rack](http://rack.github.io/), a Ruby webserver interface. Because of this, it has the benefits of using existing libraries and a variety of web servers for free, like [Puma](http://puma.io/) or [Unicorn](https://unicorn.bogomips.org/).
716
168
 
717
- To learn about new features, bug fixes, and changes, please refer to the [CHANGELOG](https://github.com/frodsan/tynn/blob/master/CHANGELOG.md).
169
+ ### Security by default
718
170
 
719
- ## Development
171
+ In addition to the security-related plugins shipped with Tynn, all the plugins provide secure options by default, like escaping HTML unsafe characters, CSRF protection, preventing session tampering, etc.
720
172
 
721
- Fork the project with:
722
173
 
723
- ```
724
- $ git clone git@github.com:frodsan/tynn.git
725
- ```
174
+ ## Getting Started
726
175
 
727
- To install dependencies, use:
176
+ You can read more about Tynn in the [official documentation][documentation].
728
177
 
729
- ```
730
- $ bundle install
731
- ```
732
-
733
- To run the test suite, do:
178
+ ## Compatibility
734
179
 
735
- ```
736
- $ rake test
737
- ```
180
+ Tynn supports Ruby 2.3+ and Rack 2.0+.
738
181
 
739
182
  ## Contributing
740
183
 
741
- Use [GitHub Issues](https://github.com/frodsan/tynn/issues) for reporting bugs, discussing features and general feedback. If you've found a problem in Tynn, be sure to check the [past issues](https://github.com/frodsan/tynn/issues?state=closed) before open a new one.
184
+ If you'd like to contribute to Tynn, check the [contribution guidelines](https://github.com/frodsan/tynn/blob/master/docs/contributing.md).
742
185
 
743
- ## Build History
186
+ ## Inspiration
744
187
 
745
- [![Build History](https://buildstats.info/travisci/chart/frodsan/tynn?branch=master)](https://travis-ci.org/frodsan/tynn/builds)
188
+ Tynn takes design cues from other web libraries like [Rails](http://rubyonrails.org/), [Sinatra](http://www.sinatrarb.com/), and [Cuba](http://cuba.is/).
746
189
 
747
190
  ## License
748
191
 
749
192
  Tynn is released under the [MIT License](http://www.opensource.org/licenses/MIT).
750
193
 
751
- [bundler]: http://bundler.io/
752
- [capybara]: https://github.com/jnicklas/capybara
753
- [clickjacking]: https://www.owasp.org/index.php/Clickjacking
754
- [cuba]: http://cuba.is/
755
- [minitest]: https://github.com/seattlerb/minitest
756
- [puma]: http://puma.io/
757
- [rack]: http://rack.github.io/
758
- [rack::test]: https://github.com/brynary/rack-test
759
- [rack::methodoverride]: http://www.rubydoc.info/github/rack/rack/Rack/MethodOverride
760
- [rails]: http://rubyonrails.org/
761
- [sinatra]: http://www.sinatrarb.com/
762
- [sniffing]: https://msdn.microsoft.com/library/gg622941(v=vs.85).aspx
763
- [thin]: http://code.macournoyer.com/thin/
764
- [tynn::environment]: http://api.tynn.xyz/2.0.0/Tynn/Environment.html
765
- [tynn::json]: http://api.tynn.xyz/2.0.0/Tynn/JSON.html
766
- [tynn::render]: http://api.tynn.xyz/2.0.0/Tynn/Render.html
767
- [tynn::secureheaders]: http://api.tynn.xyz/2.0.0/Tynn/SecureHeaders.html
768
- [tynn::session]: http://api.tynn.xyz/2.0.0/Tynn/Session.html
769
- [tynn::static]: http://api.tynn.xyz/2.0.0/Tynn/Static.html
770
- [tynn::test]: http://api.tynn.xyz/2.0.0/Tynn/Test.html
771
- [unicorn]: https://unicorn.bogomips.org/
194
+ [documentation]: http://tynn.readthedocs.io/en/latest/