iodine 0.7.56 → 0.7.58
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +10 -10
- data/examples/bates/README.md +3 -0
- data/examples/bates/config.ru +342 -0
- data/examples/bates/david+bold.pdf +0 -0
- data/examples/bates/public/drop-pdf.png +0 -0
- data/examples/bates/public/index.html +600 -0
- data/ext/iodine/extconf.rb +1 -1
- data/ext/iodine/fio_tls_openssl.c +140 -90
- data/ext/iodine/iodine.c +1 -1
- data/ext/iodine/iodine_caller.c +25 -13
- data/lib/iodine/version.rb +1 -1
- data/lib/iodine.rb +1 -1
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 322c256e46337fbbb04715a5076984dda9e00ffa35e75bac7882fb8e95b17dea
|
4
|
+
data.tar.gz: 91390ce111e21fbf39f40e010bc059acab48d13a92b90f04d0a1a4b5738b87f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78c783b0457ff798146af5c3040ccf86e3449dc33c53677986d58b7cd585745288bffcbf19f2427b8353c51507140b307209f33df2b4598d21d875c5203ab3a5
|
7
|
+
data.tar.gz: 257bbacb1c902bfa2202cd649b0d842f366963a528a00e115bc923a381d47bbe93e7c38c42cc21976f839d7a042873b107dc2fa8dd7ecc3703a61cecbe65e301
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,16 @@ Please notice that this change log contains changes for upcoming releases as wel
|
|
6
6
|
|
7
7
|
## Changes:
|
8
8
|
|
9
|
+
#### Change log v.0.7.58 (2024-04-28)
|
10
|
+
|
11
|
+
**Fix**: possible fix for compilation issues on Fedora. Credit to @garytaylor for opening issue #155.
|
12
|
+
|
13
|
+
**Fix**: possible fix for an OpenSSL certificate chain import issue that would cause certificate chains to be imported incorrectly. Credit to @dwolrdcojp for opening the facil.io repo PR #151.
|
14
|
+
|
15
|
+
#### Change log v.0.7.57 (2023-09-04)
|
16
|
+
|
17
|
+
**Fix**: Fixes possible name collision when loading gem (`.rb` vs. `.so` loading). Credit to @noraj (Alexandre ZANNI) for opening issue #148. Credit to @janbiedermann (Jan Biedermann) for discovering the root cause and offering a solution.
|
18
|
+
|
9
19
|
#### Change log v.0.7.56 (2023-07-07)
|
10
20
|
|
11
21
|
**Support**: Adds teapot support (HTTP code 418). Credit to Aleksandar N. Kostadinov (@akostadinov) for issue #144 and PR #145.
|
data/README.md
CHANGED
@@ -10,28 +10,28 @@
|
|
10
10
|
|
11
11
|
Iodine is a fast concurrent web application server for real-time Ruby applications, with native support for WebSockets and Pub/Sub services - but it's also so much more.
|
12
12
|
|
13
|
-
Iodine is a Ruby wrapper for
|
13
|
+
Iodine is a Ruby wrapper for much of the [facil.io](https://facil.io) C framework, leveraging the speed of C for many common web application tasks. In addition, iodine abstracts away all network concerns, so you never need to worry about the transport layer, leaving you free to concentrate on your application logic.
|
14
14
|
|
15
15
|
Iodine includes native support for:
|
16
16
|
|
17
17
|
* HTTP, WebSockets and EventSource (SSE) Services (server);
|
18
18
|
* WebSocket connections (server / client);
|
19
19
|
* Pub/Sub (with optional Redis Pub/Sub scaling);
|
20
|
-
* Fast(!) builtin Mustache
|
20
|
+
* Fast(!) builtin Mustache templating;
|
21
21
|
* Static file service (with automatic `gzip` support for pre-compressed assets);
|
22
|
-
* Optimized Logging to `stderr
|
22
|
+
* Optimized Logging to `stderr`;
|
23
23
|
* Asynchronous event scheduling and timers;
|
24
24
|
* HTTP/1.1 keep-alive and pipelining;
|
25
|
-
* Heap Fragmentation Protection
|
26
|
-
* TLS 1.2 and above (
|
25
|
+
* Heap Fragmentation Protection;
|
26
|
+
* TLS 1.2 and above (Requiring OpenSSL >= 1.1.0);
|
27
27
|
* TCP/IP server and client connectivity;
|
28
28
|
* Unix Socket server and client connectivity;
|
29
|
-
* Hot
|
29
|
+
* Hot Restarts (using the USR1 signal and without hot deployment);
|
30
30
|
* Custom protocol authoring;
|
31
|
-
* [Sequel](https://github.com/jeremyevans/sequel) and ActiveRecord forking protection
|
31
|
+
* [Sequel](https://github.com/jeremyevans/sequel) and ActiveRecord forking protection;
|
32
32
|
* and more!
|
33
33
|
|
34
|
-
Since iodine wraps much of the [C facil.io framework](https://github.com/boazsegev/facil.io)
|
34
|
+
Since iodine wraps much of the [C facil.io framework](https://github.com/boazsegev/facil.io) for Ruby:
|
35
35
|
|
36
36
|
* Iodine can handle **thousands of concurrent connections** (tested with more then 20K connections on Linux)!
|
37
37
|
|
@@ -39,13 +39,13 @@ Since iodine wraps much of the [C facil.io framework](https://github.com/boazseg
|
|
39
39
|
|
40
40
|
Iodine is a C extension for Ruby, developed and optimized for Ruby MRI 2.3 and up... it should support the whole Ruby 2.x and 3.x MRI family, but CI tests start at Ruby 2.3.
|
41
41
|
|
42
|
-
**Note**: iodine does **not** support streaming when using Rack. It's recommended to avoid blocking the server when using `body.each` since the `each` loop will block
|
42
|
+
**Note**: iodine does **not** support streaming when using Rack. It's recommended to avoid blocking the server when using `body.each` since the `each` loop will block iodine's thread until it's finished and iodine won't send any data before the loop is done.
|
43
43
|
|
44
44
|
## Iodine - a fast & powerful HTTP + WebSockets server with native Pub/Sub
|
45
45
|
|
46
46
|
Iodine includes a light and fast HTTP and Websocket server written in C that was written according to the [Rack interface specifications](http://www.rubydoc.info/github/rack/rack/master/file/SPEC) and the [Websocket draft extension](./SPEC-Websocket-Draft.md).
|
47
47
|
|
48
|
-
With `Iodine.listen service: :http` it's possible to run multiple HTTP applications (please remember not to set more than a single application on a single TCP/IP port).
|
48
|
+
With `Iodine.listen service: :http` it's possible to run multiple HTTP applications (but please remember not to set more than a single application on a single TCP/IP port).
|
49
49
|
|
50
50
|
Iodine also supports native process cluster Pub/Sub and a native RedisEngine to easily scale iodine's Pub/Sub horizontally.
|
51
51
|
|
@@ -0,0 +1,3 @@
|
|
1
|
+
# Bates numbering with CombinePDF and Rack
|
2
|
+
|
3
|
+
This folder holds a demo application combining Iodine's `X-Sendfile` support with the [`combine_pdf` gem](https://github.com/boazsegev/combine_pdf) to create a "bates numbering" tool that is common to the one used by some court systems (such as Israeli courts).
|
@@ -0,0 +1,342 @@
|
|
1
|
+
require 'combine_pdf'
|
2
|
+
require 'rack'
|
3
|
+
require 'base64'
|
4
|
+
# require_relative 'pdf_controller'
|
5
|
+
|
6
|
+
module BatesAPP
|
7
|
+
# This is the HTTP response object according to the Rack specification.
|
8
|
+
STATIC_RESPONSE = [200, { 'Content-Type' => 'text/html', 'X-Sendfile' => File.expand_path('./public/index.html') }.freeze, []].freeze
|
9
|
+
WS_RESPONSE = [403, { 'Content-Type' => 'text/html' }, "Forbidden"]
|
10
|
+
|
11
|
+
# this is function will be called by the Rack server (iodine) for every request.
|
12
|
+
def self.call env
|
13
|
+
req = Rack::Request.new(env)
|
14
|
+
# check if this is an upgrade request (WebsSocket / SSE).
|
15
|
+
return WS_RESPONSE if(env['rack.upgrade?'.freeze])
|
16
|
+
# simply return the RESPONSE object, no matter what request was received.
|
17
|
+
return STATIC_RESPONSE if req.params.empty?
|
18
|
+
return bates(req.params)
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def self.bates(params)
|
23
|
+
params['file'] = params['file'].values # convert to Array
|
24
|
+
# catch any exception and tell the user which PDF caused the exception.
|
25
|
+
begin
|
26
|
+
# set the file_name variable
|
27
|
+
# this will be used in case an exception is caught
|
28
|
+
# to state which file caused the exception.
|
29
|
+
file_name = ''
|
30
|
+
|
31
|
+
# container for the complete pdf
|
32
|
+
# the complete pdf container will hold all
|
33
|
+
# the merged pdf data.
|
34
|
+
completed_pdf = CombinePDF.new
|
35
|
+
|
36
|
+
# get the output file name
|
37
|
+
# this will be used to name the download for the client's browser
|
38
|
+
output_name = params['bates']['output'].to_s + '.pdf'
|
39
|
+
output_name = "unknown.pdf" if output_name == '.pdf'
|
40
|
+
|
41
|
+
# get some paramaters that will be used while combining pages
|
42
|
+
params['bates'] ||= {}
|
43
|
+
first_page_number = params['bates']['first_page_number'].to_i
|
44
|
+
first_index_number = params['bates']['first_index_number'].to_i
|
45
|
+
|
46
|
+
# we will add an option for the stamping to ignore the first pdf
|
47
|
+
# this is useful for the court cases that use bates numbering
|
48
|
+
# (the "cover PDF" will be the briefs of submissions that contain exhibits to be bates stamped)
|
49
|
+
ignore_first_file = params['bates']['first_pdf_is_cover']
|
50
|
+
first_page = nil
|
51
|
+
|
52
|
+
# we will pick some data up while running combining the different pdf files.
|
53
|
+
# this will be used for the table of contents later on.
|
54
|
+
pdfs_pages_count = []
|
55
|
+
pdf_dates = []
|
56
|
+
pdf_titles = []
|
57
|
+
|
58
|
+
# we will be creating title pages before each PDF file.
|
59
|
+
# the title pages will be sized using the mediabox variable
|
60
|
+
# wich will be set with the dimentions of each pdf file's first page.
|
61
|
+
mediabox = nil
|
62
|
+
|
63
|
+
# register UNICODE fonts if necessary
|
64
|
+
# in this example I will register the Hebrew font David from an existing PDF file.
|
65
|
+
unless CombinePDF::Fonts.get_font :my_new_david
|
66
|
+
# if your running Rails, consider Rails.root instead of Root
|
67
|
+
fonts = CombinePDF.new(File.expand_path('./david+bold.pdf').to_s).fonts(true)
|
68
|
+
# I know the first font is David regular, after using the
|
69
|
+
# ruby console and looking at the fonts array for the file.
|
70
|
+
CombinePDF.register_font_from_pdf_object :my_new_david, fonts[0]
|
71
|
+
# the second font of the array was the latin font for a newline and space... useless
|
72
|
+
# the third was the david bold. I will now add that font.
|
73
|
+
CombinePDF.register_font_from_pdf_object :my_new_david_bold, fonts[2]
|
74
|
+
end
|
75
|
+
|
76
|
+
# iterate through the different files sent from the client's browser's web form
|
77
|
+
params['file'].each do |v|
|
78
|
+
# set the file_name variable in case an exception will be raised
|
79
|
+
file_name = v['name']
|
80
|
+
|
81
|
+
# parse the pdf data
|
82
|
+
# we will use the CombinePDF.parse method which allows us
|
83
|
+
# to parse data without saving the PDF to the file system.
|
84
|
+
# our javascript encoded the file data using base64, which we will need to decode.
|
85
|
+
# (this is specific to my form which uses the HTML5 File API in this specific manner)
|
86
|
+
# begin
|
87
|
+
puts "parsing file: #{file_name}"
|
88
|
+
pdf_file = CombinePDF.parse(
|
89
|
+
Base64.urlsafe_decode64(
|
90
|
+
v['data'].slice('data:application/pdf;base64,'.length,
|
91
|
+
v['data'].length)
|
92
|
+
)
|
93
|
+
)
|
94
|
+
# rescue
|
95
|
+
# puts "Failed when parsing #{file_name} with data:\n#{v['data'].inspect}"
|
96
|
+
# raise
|
97
|
+
# end
|
98
|
+
|
99
|
+
# we will use the pages array a few times, so in order to avoid
|
100
|
+
# recomputing the array every time, we will save it to a local variable.
|
101
|
+
pdf_file_pages = pdf_file.pages
|
102
|
+
|
103
|
+
# we will add the page count to the page count array,
|
104
|
+
# used by the table of contents
|
105
|
+
pdfs_pages_count << pdf_file_pages.length
|
106
|
+
|
107
|
+
######
|
108
|
+
# create and add title page to arrays.
|
109
|
+
|
110
|
+
if ignore_first_file && first_page.nil?
|
111
|
+
# if the first PDF file is a "cover page" PDF,
|
112
|
+
# we will not add a title, nor add the file.
|
113
|
+
# instead we will save the data in a variable to add it after we're done
|
114
|
+
pdf_dates << ''
|
115
|
+
pdf_titles << ''
|
116
|
+
first_page = pdf_file
|
117
|
+
else
|
118
|
+
# set title page mediabox size
|
119
|
+
# the mediabox data (page size) is contained in the page's
|
120
|
+
# :CropBox or :MediaBox keys (pages are Hash objects).
|
121
|
+
mediabox ||= pdf_file_pages[0][:CropBox] || pdf_file_pages[0][:MediaBox]
|
122
|
+
|
123
|
+
# create a title page unless we're only merging or there is no indexing
|
124
|
+
if params['bates']['should_index'] && params['bates']['numbering'] != 3
|
125
|
+
|
126
|
+
# create an empty page object
|
127
|
+
title_page = CombinePDF.create_page mediabox
|
128
|
+
|
129
|
+
# write the content to the title page.
|
130
|
+
# we will be using the I18n.t shortcut to write some of the data.
|
131
|
+
# the rest of the data, like the title, we got from the form.
|
132
|
+
title_page.textbox("#{params['bates']['title_type']} #{pdfs_pages_count.length + first_index_number - (ignore_first_file ? 2 : 1)}",
|
133
|
+
max_font_size: 34,
|
134
|
+
font: :my_new_david,
|
135
|
+
y: (mediabox[3] - mediabox[1]) / 2) unless params['bates']['title_type'].to_s.empty?
|
136
|
+
title_page.textbox v['title'].to_s, max_font_size: 36, font: :my_new_david_bold
|
137
|
+
title_page.textbox v['date'].to_s, max_font_size: 24, font: :my_new_david, height: (mediabox[3] - mediabox[1]) / 2
|
138
|
+
|
139
|
+
# we will add the page object to the completed pdf object.
|
140
|
+
# notice that page objects are created as "floating" pages,
|
141
|
+
# not attached to any specific PDF file/object.
|
142
|
+
completed_pdf << title_page
|
143
|
+
|
144
|
+
# we will add some data that will be used to create the
|
145
|
+
# table of contents at a later stage.
|
146
|
+
page_count = pdfs_pages_count.pop + 1
|
147
|
+
pdfs_pages_count << page_count
|
148
|
+
pdf_dates << v['date'].to_s
|
149
|
+
pdf_titles << v['title'].to_s
|
150
|
+
end
|
151
|
+
|
152
|
+
# now we are ready to add the pdf file data to the completed pdf object.
|
153
|
+
# there is no need to add each page, we can add the pdf as a whole.
|
154
|
+
# (it's actually faster, as the PDF page catalog isn't recomputed for each page)
|
155
|
+
completed_pdf << pdf_file
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
##########
|
160
|
+
# create the index pdf...
|
161
|
+
# ...unless we're only merging or there is no indexing
|
162
|
+
if params['bates']['should_index'] && params['bates']['numbering'].to_i != 3
|
163
|
+
|
164
|
+
# set the fonts and formatting for the table of contents.
|
165
|
+
#
|
166
|
+
# also, add an empty array for the table data.
|
167
|
+
#
|
168
|
+
# the table data array will contain arrays of String objects, each one
|
169
|
+
# corresponding to a row in the table.
|
170
|
+
table_options = { font: :my_new_david,
|
171
|
+
header_font: :my_new_david_bold,
|
172
|
+
max_font_size: 12,
|
173
|
+
column_widths: (params['bates']['date_header'].to_s.empty? ? [3, 40, 4] : [3, 10, 30, 4]),
|
174
|
+
table_data: [] }
|
175
|
+
|
176
|
+
# set the table header array.
|
177
|
+
# this is an array of strings.
|
178
|
+
# to chose the localized strings
|
179
|
+
table_options[:headers] = [params['bates']['number_header'],
|
180
|
+
(params['bates']['date_header'].to_s.empty? ? nil : params['bates']['date_header']),
|
181
|
+
params['bates']['title_header'].to_s,
|
182
|
+
params['bates']['page_header'].to_s]
|
183
|
+
table_options[:headers].compact!
|
184
|
+
|
185
|
+
# by default, there are 25 rows per page for table pdf created by CombinePDF
|
186
|
+
# we can override this in the formatting (but we didn't).
|
187
|
+
#
|
188
|
+
# the 25 rows include 1 header row per page - so there are only 24 effective rows.
|
189
|
+
#
|
190
|
+
# we will calculate how many pages the table of contents pdf will have once completes,
|
191
|
+
# so we can add the count to the page numbers in the index.
|
192
|
+
index_page_length = pdfs_pages_count.length / 24
|
193
|
+
index_page_length += 1 if pdfs_pages_count.length % 24 > 0
|
194
|
+
|
195
|
+
# set the page number for the first entry in the table of contents.
|
196
|
+
page_number = first_page_number + index_page_length
|
197
|
+
|
198
|
+
# set the index count to 0, we will use it to change the index for each entry.
|
199
|
+
# we need a different variable in case the first PDF file is a "cover page".
|
200
|
+
index_count = 0
|
201
|
+
|
202
|
+
# iterate over the data we collected before and add it to the table data.
|
203
|
+
pdfs_pages_count.each_index do |i|
|
204
|
+
# add the data unless it is set to be ignored
|
205
|
+
unless ignore_first_file
|
206
|
+
|
207
|
+
# add an array of strings to the :table_data array,
|
208
|
+
# representing a row in our table.
|
209
|
+
# remember there might not be a date column.
|
210
|
+
if params['bates']['date_header'].to_s.empty?
|
211
|
+
table_options[:table_data] << [(first_index_number + index_count).to_s,
|
212
|
+
pdf_titles[i], page_number]
|
213
|
+
else
|
214
|
+
table_options[:table_data] << [(first_index_number + index_count).to_s,
|
215
|
+
pdf_dates[i],
|
216
|
+
pdf_titles[i], page_number]
|
217
|
+
end
|
218
|
+
|
219
|
+
# if the data was added to the index table, bump the index count
|
220
|
+
index_count += 1
|
221
|
+
|
222
|
+
end
|
223
|
+
|
224
|
+
# make sure future data will not be ignored
|
225
|
+
ignore_first_file = false
|
226
|
+
|
227
|
+
# add the page count to the page number, so that the next
|
228
|
+
# index's page number is up to date.
|
229
|
+
page_number += pdfs_pages_count[i]
|
230
|
+
end
|
231
|
+
|
232
|
+
# if out current locale is hebrew, which is a right to left language,
|
233
|
+
# set the direction for the table to Right-To-left (:rtl).
|
234
|
+
#
|
235
|
+
# notice that RTL text should be automatically recognized, but that
|
236
|
+
# feature isn't available (and shouldn't be available) for tables.
|
237
|
+
table_options[:direction] = :rtl if params['bates']['dir'] == 'rtl'
|
238
|
+
|
239
|
+
# if there is table data, we will create an index pdf.
|
240
|
+
unless table_options[:table_data].empty?
|
241
|
+
|
242
|
+
# create the index PDF from the table data and options we have.
|
243
|
+
index_pdf = CombinePDF.create_table table_options
|
244
|
+
|
245
|
+
# We will now add the words "Table of Contents" (or the I18n equivilant)
|
246
|
+
# to the first page of our new index_pdf PDF object.
|
247
|
+
#
|
248
|
+
# the table PDF object was created by CombinePDF using writable PDF pages,
|
249
|
+
# so we have properties like .mediabox and methods like .textbox
|
250
|
+
# at our disposal.
|
251
|
+
|
252
|
+
# get the first page of the index_pdf object, we will use this reference a lot.
|
253
|
+
title_page = index_pdf.pages[0]
|
254
|
+
|
255
|
+
# write the textbox, using the mediabox page data [x,y,width,height] to place
|
256
|
+
# the text we want to write.
|
257
|
+
#
|
258
|
+
# we will use the I18n.t shortcut to choose the text to write down.
|
259
|
+
title_page.textbox params['bates']['index_title'],
|
260
|
+
y: ((title_page.mediabox[3] - title_page.mediabox[1]) * 0.91),
|
261
|
+
height: ((title_page.mediabox[3] - title_page.mediabox[1]) * 0.03),
|
262
|
+
font: :my_new_david,
|
263
|
+
max_font_size: 36,
|
264
|
+
text_valign: :bottom
|
265
|
+
|
266
|
+
# now we will add the index_pdf to the BEGINING of the completed pdf.
|
267
|
+
# for this we will use the >> operator instead of the << operator.
|
268
|
+
completed_pdf >> index_pdf
|
269
|
+
|
270
|
+
end
|
271
|
+
|
272
|
+
end
|
273
|
+
|
274
|
+
# add first file if it was skipped
|
275
|
+
completed_pdf >> first_page unless first_page.nil?
|
276
|
+
|
277
|
+
#####
|
278
|
+
# number pages
|
279
|
+
# unless no numbering
|
280
|
+
if params['bates']['numbering'].to_i != 3
|
281
|
+
# list the numbering options
|
282
|
+
numbering_options = [[:top, :bottom], [:top_left, :bottom_left], [:top_right, :bottom_right]]
|
283
|
+
|
284
|
+
# set the first visible page number to the page where numbering starts
|
285
|
+
# this assumes that the bates numbering include the numbering of the "cover page",
|
286
|
+
# yet at the same time the numbering isn't visible on the "cover page"
|
287
|
+
first_page_number += pdfs_pages_count[0] if params['bates']['first_pdf_is_cover'] && params['bates']['skip_cover']
|
288
|
+
|
289
|
+
# call the page numbering method and
|
290
|
+
# add the special properties we want for the textbox
|
291
|
+
completed_pdf.number_pages(start_at: first_page_number,
|
292
|
+
page_range: params['bates']['skip_cover'] ? (pdfs_pages_count[0].to_i..-1) : nil,
|
293
|
+
font_name: :my_new_david,
|
294
|
+
font_size: 14,
|
295
|
+
font_color: [0, 0, 0.4],
|
296
|
+
box_color: [0.8, 0.8, 0.8],
|
297
|
+
border_width: 1,
|
298
|
+
border_color: [0.3, 0.3, 0.3],
|
299
|
+
box_radius: 8,
|
300
|
+
number_location: numbering_options[params['bates']['numbering'].to_i],
|
301
|
+
opacity: 0.75)
|
302
|
+
end
|
303
|
+
|
304
|
+
# send the completed PDF to the client.
|
305
|
+
# if the completed PDF is empty, raise an error.
|
306
|
+
if completed_pdf.pages.empty?
|
307
|
+
# inform the client there was an unknown error.
|
308
|
+
response = STATIC_RESPONSE.dup
|
309
|
+
response[1] = response[1].dup
|
310
|
+
response[1]['set-cookie'] = "Unknown error - 0 pages."
|
311
|
+
return response
|
312
|
+
end
|
313
|
+
|
314
|
+
# make sure the PDF version is high enough for the opacity we used in the page numbering.
|
315
|
+
completed_pdf.version = [completed_pdf.version, 1.6].max
|
316
|
+
|
317
|
+
# we will format the PDF to a pdf file WITHOUT saving it to the file system,
|
318
|
+
# using the .to_pdf method (instead of the .save method).
|
319
|
+
# we will send the raw PDF data stream.
|
320
|
+
return [200, {'content-type' => "application/pdf",
|
321
|
+
'content-disposition' => "attachment; filename=\"#{output_name}\""}, completed_pdf.to_pdf]
|
322
|
+
|
323
|
+
rescue Exception => e
|
324
|
+
puts e.message, e.backtrace
|
325
|
+
puts "The file causing the exception is: #{file_name}"
|
326
|
+
# if an exception was raised, tell the user which PDF caused the exception
|
327
|
+
response = STATIC_RESPONSE.dup
|
328
|
+
response[1] = response[1].dup
|
329
|
+
response[1]['set-cookie'] = "notice=Unsupported or error reading file: #{file_name}"
|
330
|
+
return response
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
Iodine.workers = 1
|
336
|
+
Iodine.threads = 5
|
337
|
+
Iodine::DEFAULT_SETTINGS[:public] ||= './public'
|
338
|
+
|
339
|
+
p Iodine::DEFAULT_SETTINGS
|
340
|
+
Iodine::DEFAULT_SETTINGS[:max_body] = 70 if Iodine::DEFAULT_SETTINGS[:max_body].to_i < 5
|
341
|
+
|
342
|
+
run BatesAPP
|
Binary file
|
Binary file
|