blobsterix 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/.gitignore +27 -0
  2. data/CHANGELOG.txt +13 -0
  3. data/Gemfile +16 -0
  4. data/LICENSE +22 -0
  5. data/README.md +122 -0
  6. data/Rakefile +13 -0
  7. data/bin/blobsterix +152 -0
  8. data/bin/test +26 -0
  9. data/blobsterix.gemspec +39 -0
  10. data/config/lighttpd.conf +50 -0
  11. data/lib/blobsterix.rb +213 -0
  12. data/lib/blobsterix/blob/blob_api.rb +55 -0
  13. data/lib/blobsterix/blob/blob_url_helper.rb +55 -0
  14. data/lib/blobsterix/helper/accept_type.rb +62 -0
  15. data/lib/blobsterix/helper/blob_access.rb +73 -0
  16. data/lib/blobsterix/helper/config_loader.rb +33 -0
  17. data/lib/blobsterix/helper/data_response.rb +54 -0
  18. data/lib/blobsterix/helper/http.rb +47 -0
  19. data/lib/blobsterix/helper/logable.rb +11 -0
  20. data/lib/blobsterix/helper/murmur.rb +137 -0
  21. data/lib/blobsterix/helper/status_info.rb +42 -0
  22. data/lib/blobsterix/helper/template_renderer.rb +39 -0
  23. data/lib/blobsterix/mimemagic/magic.rb +138 -0
  24. data/lib/blobsterix/mimemagic/tables.rb +1770 -0
  25. data/lib/blobsterix/mimemagic/version.rb +5 -0
  26. data/lib/blobsterix/router/app_router.rb +134 -0
  27. data/lib/blobsterix/s3/s3_api.rb +92 -0
  28. data/lib/blobsterix/s3/s3_url_helper.rb +93 -0
  29. data/lib/blobsterix/service.rb +34 -0
  30. data/lib/blobsterix/status/status_api.rb +62 -0
  31. data/lib/blobsterix/status/status_url_helper.rb +11 -0
  32. data/lib/blobsterix/storage/blob_meta_data.rb +60 -0
  33. data/lib/blobsterix/storage/bucket.rb +36 -0
  34. data/lib/blobsterix/storage/bucket_entry.rb +29 -0
  35. data/lib/blobsterix/storage/bucket_list.rb +26 -0
  36. data/lib/blobsterix/storage/cache.rb +90 -0
  37. data/lib/blobsterix/storage/file_system.rb +132 -0
  38. data/lib/blobsterix/storage/file_system_meta_data.rb +136 -0
  39. data/lib/blobsterix/storage/storage.rb +30 -0
  40. data/lib/blobsterix/transformation/image_transformation.rb +439 -0
  41. data/lib/blobsterix/transformation/transformation.rb +30 -0
  42. data/lib/blobsterix/transformation/transformation_chain.rb +78 -0
  43. data/lib/blobsterix/transformation/transformation_manager.rb +115 -0
  44. data/lib/blobsterix/version.rb +3 -0
  45. data/scripts/download.rb +30 -0
  46. data/scripts/test +6 -0
  47. data/spec/lib/blob/blob_api_spec.rb +81 -0
  48. data/spec/lib/helper/blob_access_spec.rb +72 -0
  49. data/spec/lib/s3/s3_api_spec.rb +183 -0
  50. data/spec/lib/service_spec.rb +12 -0
  51. data/spec/lib/status/status_api_spec.rb +42 -0
  52. data/spec/lib/storage/cache_spec.rb +135 -0
  53. data/spec/lib/storage/file_system_spec.rb +84 -0
  54. data/spec/spec_helper.rb +139 -0
  55. data/templates/app/Gemfile +12 -0
  56. data/templates/app/Rakefile +7 -0
  57. data/templates/app/config.rb +61 -0
  58. data/templates/app/config/environments/development.rb +40 -0
  59. data/templates/app/config/environments/production.rb +40 -0
  60. data/templates/app/storages/.keep +0 -0
  61. data/templates/app/transformators/.keep +0 -0
  62. data/templates/app/views/.keep +0 -0
  63. data/templates/storage_template.rb +30 -0
  64. data/templates/transformation_template.rb +41 -0
  65. data/templates/views/error_page.erb +18 -0
  66. data/templates/views/status_page.erb +31 -0
  67. metadata +325 -0
data/.gitignore ADDED
@@ -0,0 +1,27 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .rbenv-gemsets
7
+ .ruby-gemset
8
+ .ruby-version
9
+
10
+ Gemfile.lock
11
+ InstalledFiles
12
+ _yardoc
13
+ coverage
14
+ doc/
15
+ lib/bundler/man
16
+ pkg
17
+ rdoc
18
+ spec/reports
19
+ test/tmp
20
+ test/version_tmp
21
+ tmp
22
+ contents/
23
+ cache/
24
+ typescript
25
+ *~
26
+ .idea
27
+ spec.log
data/CHANGELOG.txt ADDED
@@ -0,0 +1,13 @@
1
+ = 0.0.7
2
+ * now uses blobaccess to access all data in the transformation manager
3
+ cache and storage are now hidden and are used in the background accordingly. allows the system to prevent unneeded caching
4
+ = 0.0.6
5
+ * renaming maxsize to resizemax
6
+ * event listener now accepts hashes
7
+ * adding events for API calls
8
+ * adding Blobsterix.event hook
9
+ = 0.0.5
10
+ * adding maxsize
11
+ = 0.0.4
12
+ * The first rc
13
+
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in blob_server.gemspec
4
+ gemspec
5
+
6
+ gem 'simplecov', :require => false, :group => :test
7
+ gem 'rack-test', :group => :test
8
+ gem 'em-http-request', :group => :test
9
+
10
+ group :development do
11
+ gem "capistrano", "2.15.4"
12
+ gem "capistrano-ext", "1.2.1"
13
+ gem "rvm-capistrano", "~> 1.5.1"
14
+ gem 'whenever', '=0.8.2', :require => false
15
+ gem "railsless-deploy", :require => false
16
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Daniel Sudmann
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,122 @@
1
+ # Blobsterix
2
+
3
+
4
+ # IMPORTANT
5
+ Use at least ruby-2.0.0-p451 to ensure thread safety (reference: https://github.com/eventmachine/eventmachine/issues/457)
6
+
7
+
8
+ Blobsterix is a s3 compliant content server that supports on the fly transformations for its data. Images for example can be scaled, rotated and so on before delivered to the client. The system also supports encryption and transformation signing for the non s3 interface functions. The s3 interface itself is unsecured and should not be visible to the outside.
9
+
10
+ # Install
11
+
12
+ * Checkout the repository
13
+
14
+ * Setup binary dependencies
15
+ * Webp
16
+ - Download precompiled binaries from google: https://developers.google.com/speed/webp/download
17
+ - OR apt-get install webp (on newer ubuntu this should work)
18
+ - OR make sure you have a cwbep script that behaves the right way
19
+ * MiniMagick
20
+ sudo apt-get install imagemagick
21
+ * VIPS(deprecated)
22
+ sudo apt-get install libjpeg-dev libpng-dev libtiff-dev libvips-dev
23
+ * lightpd config(not needed):
24
+ sudo apt-get install libpcre3-dev libbz2-dev libglib2.0-dev
25
+ * ASCII Art (optional)
26
+ sudo apt-get install jp2a
27
+
28
+ * Setup ruby
29
+ - bundle install
30
+
31
+ # Usage
32
+
33
+ To install blobsterix simply do a:
34
+
35
+ * gem install blobsterix
36
+
37
+ This will install blobsterix with all its dependencies. After that you have to install the binary dependecies which are written above. Those are needed for the transformation pipeline not for the server itself. If you have your own transformations you might not need thoose.
38
+
39
+ Now the server is basicly ready to run with
40
+
41
+ * blobsterix server
42
+
43
+ This will run the server in the current directory which will create a contents and a cache folder uppon the first request that needs them. If this is enough you are basicly done and you can use the server. When you need more control over the server you will have to create a server configuration. For this process there are generators shipped with blobsterix.
44
+
45
+ # HTTP interface
46
+
47
+ Now the server has two http interface and a status page.
48
+
49
+ ## Status Page
50
+
51
+ The status page can be retrived via
52
+
53
+ * GET /status
54
+ * GET /status.json
55
+ * GET /status.xml
56
+
57
+ The first returns a "beautifull" html page. The other two return the status data as json or xml as expected.
58
+
59
+ ## S3 interface
60
+
61
+ The s3 interface works like the aws system but without the encryption and security parameters. Because of this you shouldn't route GET, PUT, POST requests to the outside.
62
+ Check the amazon s3 specs for more information. It only supports the REST api with the following actions:
63
+
64
+ * list buckets
65
+ * list bucket entries
66
+ * get file
67
+ * head file
68
+ * create bucket
69
+ * delete bucket
70
+ * put file into bucket
71
+ * delete file from bucket
72
+
73
+ ## Blob interface
74
+
75
+ The blob interface is reachable at
76
+
77
+ * GET /blob/v1/
78
+
79
+ It only supports GET and HEAD requests and the url is constructed as this:
80
+
81
+ * /blob/v1/$trafo.$bucket/$file
82
+
83
+ The transformation is expected in the following format:
84
+
85
+ * $trafoname_$value,$trafoname_$value,...
86
+
87
+ The trafo is optional the bucket and file are not. The blob interface does not allow listing of buckets or files inside buckets.
88
+
89
+
90
+ # Config setup
91
+
92
+ To setup a special server change into and empty directory:
93
+
94
+ * mkdir special-blobsterix
95
+ * blobsterix generate init special-blobsterix
96
+
97
+ This will copy a base template into special-blobsterix. Now you can checkout the generated config files for documentation on how to change things.
98
+
99
+ # Custom Transformation
100
+
101
+ The biggest strength of the system is it supports custom transformations without much coding required. To use a custom transformation you first have to setup a configuration as explained in the step before. Then you can use transformation generator to create a new transformation with
102
+
103
+ * blobsterix generate transformator CropToFace
104
+
105
+ This will generate a new transforamtion in the transformators subdirectory of your server configuration. The transformation has standard parameters set which already make the transformation work. There are five functions:
106
+
107
+ * name
108
+ * is_format?
109
+ * input_type
110
+ * output_type
111
+ * transform
112
+
113
+ The name function is used to match a parameter in the transformation string to a specific transformator. If it can not a transformator with the given name a dummy transformator is used which does nothing. The is_format? function tells the transformation manager if this transformator is an output format which should override a requested format send by the browser. For example images requested by a chrome browser are requested as webp and if in the transformation chain is no transformator with is_format? == true then in the end the transformation manager will try to find a transformation which will convert the image to webp. Now the input_type and output_type function do what they say. They tell the system what kind of file the transformator accepts and what kind of file it produces. With this information the transformation chain is build. So incase those function return wrong values the transformation might fail horribly. The last function is the one with all the magic. It transforms an input file to an output file. Now those files are passed as paths and are saved in the tmp folder or where ever ruby decides to save TempFiles. Those are outmaticly cleaned up after the transformation finishes. The value parameter is the second part of the transformation: resize_50
114
+ Now the 50 would be passed as value with type string. The transformation has to take care of parsing the parameter and ensuring its not doing any harm to the system. Another thing to keep in mind is that the transform functions are called in a different thread than the rest of the server.
115
+
116
+ # Custom Storage
117
+
118
+ Blobsterix also supports different kinds of backend storages. For this purpose you can again use a generator to create template storage system with:
119
+
120
+ * blobsterix generate storage MyBackend
121
+
122
+ This will again generate a working empty storage that doesn't allow saving or retriving of data. To see a working storage implementation checkout the FileSystem storage in the source code. Now you will see that all data there is returned as a BlobMetaData or better in the FileSystem storage as a FileSystemMetaData. As long as your implementation supports the interface everything should work like expected.
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+
5
+ desc "Simple cov"
6
+ task :simplecov do
7
+ require 'simplecov'
8
+ SimpleCov.start do
9
+ command_name "Tests"
10
+ end
11
+ require "blobsterix"
12
+ `rspec`
13
+ end
data/bin/blobsterix ADDED
@@ -0,0 +1,152 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "goliath/runner"
4
+ require "fileutils"
5
+
6
+ require "blobsterix"
7
+
8
+ module ArgParser
9
+ def parse(args)
10
+ args[1..-1].each{|command|
11
+ @param ||= command if command != "generate" and @type
12
+ @type ||= command if command != "generate"
13
+ }
14
+ end
15
+ end
16
+
17
+ class Generator
18
+ include ArgParser
19
+ def initialize(args)
20
+ parse(args)
21
+ end
22
+
23
+ def run()
24
+ puts "Doing #{@type} with #{@param} in #{Dir.pwd}"
25
+
26
+ init(@param||"") if @type == "init"
27
+ transformation(@param||"NewTrafo") if @type == "transformator"
28
+ storage(@param||"Special") if @type == "storage"
29
+ end
30
+
31
+ def init(folder)
32
+ puts "Init new Blobsterix Server"
33
+
34
+ files_to_write = Dir.glob(File.join(BLOBSTERIX_GEM_DIR, "templates/app/**/*"))
35
+ check_files = files_to_write.map{|file|file.gsub(File.join(BLOBSTERIX_GEM_DIR, "templates/app/"), "")}
36
+
37
+ check_files.each_with_index {|file, index|
38
+ if !Dir.exist?(File.dirname(Blobsterix.root.join(folder, file)))
39
+ puts "Create folder: #{File.dirname(Blobsterix.root.join(folder, file))}"
40
+ FileUtils.mkdir_p(File.dirname(Blobsterix.root.join(folder, file)))
41
+ end
42
+ if !File.directory?(files_to_write[index]) && !File.exist?(Blobsterix.root.join(folder, file))
43
+ puts "Create file: #{Blobsterix.root.join(folder, file)}"
44
+ FileUtils.cp(files_to_write[index], Blobsterix.root.join(folder, file))
45
+ end
46
+ }
47
+ end
48
+
49
+ def storage(name)
50
+ storages_dir = Blobsterix.root.join("storages")
51
+ if File.exist?(File.join(storages_dir, "#{name.downcase}_storage.rb"))
52
+ puts "Storage #{name} at #{File.join(storages_dir, "#{name.downcase}_transformation.rb")} already exists. cancel"
53
+ return
54
+ end
55
+ FileUtils.mkdir_p(storages_dir)
56
+ new_transformator = File.read(File.join(BLOBSTERIX_GEM_DIR, "templates/storage_template.rb"))
57
+ new_transformator = new_transformator.gsub("$ClassName", name.capitalize)
58
+ new_transformator = new_transformator.gsub("$url_name", name.downcase)
59
+ File.write(File.join(storages_dir, "#{name.downcase}_storage.rb"), new_transformator)
60
+ end
61
+
62
+ def transformation(name)
63
+ trafo_dir = Blobsterix.root.join("transformators")
64
+ if File.exist?(File.join(trafo_dir, "#{name.downcase}_transformation.rb"))
65
+ puts "Transformator #{name} at #{File.join(trafo_dir, "#{name.downcase}_transformation.rb")} already exists. cancel"
66
+ return
67
+ end
68
+ FileUtils.mkdir_p(trafo_dir)
69
+ new_transformator = File.read(File.join(BLOBSTERIX_GEM_DIR, "templates/transformation_template.rb"))
70
+ new_transformator = new_transformator.gsub("$ClassName", name.capitalize)
71
+ new_transformator = new_transformator.gsub("$url_name", name.downcase)
72
+ File.write(File.join(trafo_dir, "#{name.downcase}_transformation.rb"), new_transformator)
73
+ end
74
+ end
75
+ class BlobsterixRunner
76
+ include ArgParser
77
+ include Blobsterix::ConfigLoader
78
+
79
+ def initialize(args)
80
+ parse(args)
81
+ end
82
+
83
+ def run_command()
84
+ begin
85
+ require "pry"
86
+
87
+ require_storages
88
+ require_config
89
+ require_transformators
90
+
91
+ Kernel.eval(@type)
92
+ exit
93
+ rescue LoadError => e
94
+ warn "=> Unable to load pry: #{e}"
95
+ end
96
+ end
97
+
98
+ def run_console()
99
+ begin
100
+ require "pry"
101
+
102
+ require_storages
103
+ require_config
104
+ require_transformators
105
+
106
+ Pry.start
107
+ exit
108
+ rescue LoadError => e
109
+ warn "=> Unable to load pry: #{e}"
110
+ end
111
+ end
112
+
113
+ def run_blobsterix()
114
+ require_storages
115
+ require_config
116
+ require_transformators
117
+
118
+ runner = Goliath::Runner.new(ARGV, nil)
119
+ runner.logger=Blobsterix.logger
120
+ runner.port = Blobsterix.port if Blobsterix.respond_to?(:port)
121
+ runner.address = Blobsterix.address if Blobsterix.respond_to?(:address)
122
+
123
+ Goliath.env = Blobsterix.env if Blobsterix.respond_to?(:env)
124
+
125
+ runner.api = Blobsterix::Service.new
126
+ runner.app = Goliath::Rack::Builder.build(Blobsterix::Service, runner.api)
127
+
128
+ puts "Now starting Blobsterix #{Blobsterix::VERSION}...."
129
+ runner.run
130
+ end
131
+ end
132
+
133
+ puts "Blobsterix #{Blobsterix::VERSION}"
134
+ if ARGV.length == 0
135
+ puts "Usage: "
136
+ puts "\tserver (goliath server options) \n\t\tStarts blobsterix. When a blobsterix config is present in the executing folder it \n\t\twill be used otherwise blobsterix will run with standard options."
137
+ puts "\tconsole \n\t\tStarts blobsterix console and loads app config"
138
+ puts "\tgenerate (generator) (param) Used to generate blobsterix server files"
139
+ puts "\t\t init (foldername) - Creates a new blobsterix project. When a foldername is supplied it will be created in that folder."
140
+ puts "\t\t transformator (TrafoName) - Creates a new blobsterix transformator with the given name or just new as name."
141
+ puts "\t\t storage (StorageName) - Creates a new blobsterix storage with the given name or just new as name."
142
+ exit
143
+ end
144
+ if ARGV[0] == "server"
145
+ BlobsterixRunner.new(ARGV).run_blobsterix
146
+ elsif ARGV[0] == "console"
147
+ BlobsterixRunner.new(ARGV).run_console
148
+ elsif ARGV[0] == "run"
149
+ BlobsterixRunner.new(ARGV).run_command
150
+ elsif ARGV[0] == "generate"
151
+ Generator.new(ARGV).run
152
+ end
data/bin/test ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env ruby
2
+ require 'blob_server'
3
+
4
+ trafoManager = Blobsterix::Transformations::TransformationManager.new.add("ImageTransformation")
5
+
6
+ bucket = "test"
7
+ id = "droid2.png"
8
+ type = "image/webp"
9
+ trafo = "rotate_20,shrink_2"
10
+ etag = "1fea74d710de911a9fd2807250765a20"
11
+
12
+ #trafo = trafoManager.create(:bucket => bucket, :id => id, :type => type, :trafo => trafo)
13
+ #trafo.run
14
+
15
+ trafoManager.create(:bucket => bucket, :id => id, :type => type, :trafo => trafo).run
16
+ trafoManager.create(:bucket => bucket, :id => id, :type => type, :trafo => trafo).run
17
+
18
+
19
+ #f = File.open('contents/test/droid2.png')
20
+ #blob = f.read
21
+
22
+ ##image = Magick::Image.from_blob(blob)
23
+ #ilist = Magick::ImageList.new.from_blob(blob)
24
+ ##ilist << image[0]
25
+ #ilist.background_color = "none"
26
+ #ilist.rotate(20).write("out.png")
@@ -0,0 +1,39 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/blobsterix/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.required_ruby_version = '>= 2.0.0.p451'
6
+ gem.authors = ["Daniel Sudmann"]
7
+ gem.email = ["suddani@googlemail.com"]
8
+ gem.description = "BlobServer"
9
+ gem.summary = "BlobServer"
10
+ gem.homepage = "http://experteer.com"
11
+ gem.license = "MIT License"
12
+
13
+ gem.files = `git ls-files`.split($\).select{|filename|
14
+ if filename.match(/^(\"contents).*/)
15
+ false
16
+ else
17
+ true
18
+ end
19
+ }
20
+ gem.executables = ["blobsterix"]#gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
21
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
22
+ gem.name = "blobsterix"
23
+ gem.require_paths = ["lib"]
24
+ gem.version = Blobsterix::VERSION
25
+
26
+
27
+ gem.add_dependency "json", "~> 1.8.1"
28
+ gem.add_dependency "goliath", "~> 1.0.3"
29
+ gem.add_dependency "journey", "~> 1.0.4"
30
+ gem.add_dependency "nokogiri", "~> 1.6.1"
31
+ gem.add_dependency "ruby-webp", "~> 0.1.0"
32
+ gem.add_dependency "mini_magick", "~> 3.5.0"
33
+
34
+ gem.add_development_dependency "rspec"
35
+ gem.add_development_dependency "rspec-core"
36
+ gem.add_development_dependency "rspec-expectations"
37
+ gem.add_development_dependency "rspec-mocks"
38
+ gem.add_development_dependency "pry"
39
+ end
@@ -0,0 +1,50 @@
1
+ #lightpd config: sudo apt-get install libpcre3-dev libbz2-dev libglib2.0-dev
2
+ #run: lighttpd -m /home/dsudmann/workspace/libs/lighttpd-1.4.33/src/.libs/ -D -f workspace/blobserver/config/lighttpd.conf
3
+ #run: lighttpd -m /home/dsudmann/workspace/libs/lighttpd-1.5.0/src/.libs/ -D -f workspace/blobserver/config/lighttpd.conf
4
+
5
+ server.document-root = "/home/dsudmann/workspace/experteer/blobsterix/contents/"
6
+
7
+ server.port = 3000
8
+
9
+ server.modules += (
10
+ #"mod_fastcgi",
11
+ #"mod_proxy",
12
+ "mod_proxy_core", "mod_proxy_backend_http", "mod_proxy_backend_fastcgi", "mod_staticfile", "mod_setenv" )
13
+
14
+ mimetype.assign = (
15
+ ".html" => "text/html",
16
+ ".txt" => "text/plain",
17
+ ".jpg" => "image/jpeg",
18
+ ".png" => "image/png"
19
+ )
20
+
21
+ #$HTTP["url"] =~ "(^/blob/)" {
22
+ # #proxy.server = ( "" => ("" => ( "host" => "127.0.0.1", "port" => 9000 )))
23
+ # proxy.server = ("" => (
24
+ # ( "host" => "127.0.0.1", "port" => 9000),
25
+ # ( "host" => "127.0.0.1", "port" => 9001)
26
+ # ))
27
+ #}
28
+
29
+ $HTTP["url"] =~ "^/blob/" {
30
+ setenv.add-request-header = (
31
+ "X-File" => "yes"
32
+ )
33
+ proxy-core.backends = (
34
+ "127.0.0.1:9000"
35
+ , "127.0.0.1:9001"
36
+ , "127.0.0.1:9002"
37
+ #, "127.0.0.1:9003"
38
+ #, "127.0.0.1:9004"
39
+ #, "127.0.0.1:9005"
40
+ )
41
+ #proxy-core.balancer = "round-robin"
42
+ proxy-core.protocol = "http"
43
+ proxy-core.max-pool-size = 20
44
+ proxy-core.allow-x-sendfile = "enable"
45
+ #proxy-core.rewrite-request = (
46
+ # "X-File" => (".*" => "YES" )
47
+ # "_pathinfo" => ( "^/trac(/.*)" => "$1" ),
48
+ # "_scriptname" => ( "^(/trac/)" => "$1" )
49
+ #)
50
+ }