magellan-rails 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +37 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +76 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +7 -0
- data/bin/magellan-rails +7 -0
- data/gems/magellan-publisher/.gitignore +37 -0
- data/gems/magellan-publisher/Gemfile +11 -0
- data/gems/magellan-publisher/Gemfile.lock +51 -0
- data/gems/magellan-publisher/LICENSE.txt +22 -0
- data/gems/magellan-publisher/README.md +29 -0
- data/gems/magellan-publisher/Rakefile +14 -0
- data/gems/magellan-publisher/lib/magellan/publisher/version.rb +5 -0
- data/gems/magellan-publisher/lib/magellan/publisher.rb +37 -0
- data/gems/magellan-publisher/magellan-publisher.gemspec +27 -0
- data/gems/magellan-publisher/spec/magellan/publisher_spec.rb +39 -0
- data/gems/magellan-publisher/spec/spec_helper.rb +8 -0
- data/lib/generators/install_generator.rb +20 -0
- data/lib/generators/templates/Magellan.yml +115 -0
- data/lib/magellan/extentions/rails/engine.rb +28 -0
- data/lib/magellan/extentions/rails.rb +2 -0
- data/lib/magellan/extentions.rb +2 -0
- data/lib/magellan/rails/executor.rb +35 -0
- data/lib/magellan/rails/railtie.rb +12 -0
- data/lib/magellan/rails/request.rb +111 -0
- data/lib/magellan/rails/response.rb +35 -0
- data/lib/magellan/rails/version.rb +5 -0
- data/lib/magellan/rails.rb +10 -0
- data/lib/magellan/subscriber/base.rb +26 -0
- data/lib/magellan/subscriber/executor.rb +21 -0
- data/lib/magellan/subscriber/mapper.rb +105 -0
- data/lib/magellan/subscriber/request.rb +25 -0
- data/lib/magellan/subscriber/rspec.rb +7 -0
- data/lib/magellan/subscriber/testing/integration.rb +22 -0
- data/lib/magellan/subscriber.rb +10 -0
- data/lib/magellan/worker/config.rb +33 -0
- data/lib/magellan/worker/core.rb +70 -0
- data/lib/magellan/worker/executor.rb +38 -0
- data/lib/magellan/worker.rb +14 -0
- data/lib/magellan.rb +28 -0
- data/magellan-rails.gemspec +28 -0
- data/spec/magellan/rails/request_spec.rb +103 -0
- data/spec/magellan/rails/response_spec.rb +58 -0
- data/spec/magellan/subscriber/mapper_spec.rb +264 -0
- data/spec/magellan/worker/core_spec.rb +70 -0
- data/spec/spec_helper.rb +4 -0
- metadata +167 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'magellan/rails'
|
3
|
+
|
4
|
+
ActiveSupport::Dependencies.autoload_paths << Rails.root.join("app/subscribers").to_s
|
5
|
+
|
6
|
+
class Magellan::Subscriber::Executor
|
7
|
+
def initialize
|
8
|
+
@map = Magellan::Subscriber::Mapper.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute(request_message)
|
12
|
+
request = Magellan::Subscriber::Request.new()
|
13
|
+
request.parse_message(request_message)
|
14
|
+
|
15
|
+
# ロード済み定数をクリア
|
16
|
+
# TODO: 更新時刻をチェックする
|
17
|
+
ActiveSupport::Dependencies.clear
|
18
|
+
|
19
|
+
@map.call(request)
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'magellan/rails'
|
3
|
+
|
4
|
+
class Magellan::Subscriber::RoutingError < StandardError
|
5
|
+
end
|
6
|
+
|
7
|
+
class Magellan::Subscriber::Mapper
|
8
|
+
def initialize(map_file_path=Rails.root.join("config/subscribes.yml"))
|
9
|
+
# テストのため nil で初期化できるようにしています
|
10
|
+
if map_file_path
|
11
|
+
@config_file = map_file_path.to_s
|
12
|
+
@config_file_size = nil
|
13
|
+
@config_file_mtime = nil
|
14
|
+
load_mapper_file
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def load_mapper_file
|
19
|
+
if @config_file
|
20
|
+
st = File.stat(@config_file)
|
21
|
+
if st.size != @config_file_size or st.mtime > @config_file_mtime
|
22
|
+
@config = YAML.load(File.read(@config_file))
|
23
|
+
self.map = @config
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def topic_regexp(topic)
|
29
|
+
# "#" は特別に任意の1文字以上のトピックにマッチするとする(MQTT の仕様上空文字列はトピックとして不正)
|
30
|
+
return /.+/ if topic == "#"
|
31
|
+
|
32
|
+
words = topic.split("/", -1) # 末尾の a/ を ["a", ""] と分離するため第2引数の-1が必要
|
33
|
+
# 前処理ととして連続している "#" は冗長なので1つに正規化する
|
34
|
+
words.each_cons(2).each_with_index{|(w1, w2), idx| words[idx] = nil if w1 == "#" and w2 == "#" }
|
35
|
+
words.compact!
|
36
|
+
first, *remain = words
|
37
|
+
optional_sep = false
|
38
|
+
# 先頭の要素を正規表現文字列にする
|
39
|
+
regexp_str = "\\A"
|
40
|
+
case first
|
41
|
+
when "#"
|
42
|
+
# 先頭が "#" の場合 "#/a" は "a" にもマッチするので後続の要素の "/" の正規表現はここで追加する
|
43
|
+
optional_sep = true
|
44
|
+
# #/〜 の場合 # はなくてもマッチするので、空文字列もしくは任意のword+"/"とする
|
45
|
+
regexp_str += "(?:.*/|)"
|
46
|
+
when "+"
|
47
|
+
regexp_str += "[^/]*"
|
48
|
+
else
|
49
|
+
regexp_str += Regexp.escape(first)
|
50
|
+
end
|
51
|
+
remain.each do |w|
|
52
|
+
case w
|
53
|
+
when "#"
|
54
|
+
# "〜/#" の場合 "/" はなくてもマッチする(# はレベル0でもマッチする)ので、空文字列もしくは"/"+任意のwordとする
|
55
|
+
regexp_str += "(?:|/.*)"
|
56
|
+
when "+"
|
57
|
+
regexp_str += "/" unless optional_sep
|
58
|
+
regexp_str += "[^/]*"
|
59
|
+
else
|
60
|
+
regexp_str += "/" unless optional_sep
|
61
|
+
regexp_str += Regexp.escape(w)
|
62
|
+
end
|
63
|
+
optional_sep = false
|
64
|
+
end
|
65
|
+
regexp_str += "\\z"
|
66
|
+
Regexp.compile(regexp_str)
|
67
|
+
end
|
68
|
+
private :topic_regexp
|
69
|
+
|
70
|
+
def map=(config)
|
71
|
+
@map = config.each_with_object({}) do |(key, value), tbl|
|
72
|
+
regexp = topic_regexp(key)
|
73
|
+
controller, action = value.split("#", 2)
|
74
|
+
controller_name = (controller.classify + "Subscriber")
|
75
|
+
tbl[regexp] = [controller_name, action]
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def map
|
80
|
+
if Rails.env.development?
|
81
|
+
load_mapper_file
|
82
|
+
end
|
83
|
+
@map
|
84
|
+
end
|
85
|
+
|
86
|
+
def map_action(topic)
|
87
|
+
self.map.select do |re, _|
|
88
|
+
re.match(topic)
|
89
|
+
end.map do |_, (controller_name, action)|
|
90
|
+
[controller_name, action]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def call(request)
|
95
|
+
actions = map_action(request.topic)
|
96
|
+
actions.each do |controller_name, action|
|
97
|
+
controller_class = ActiveSupport::Dependencies.constantize(controller_name)
|
98
|
+
controller = controller_class.new(request)
|
99
|
+
return controller.process_action(action)
|
100
|
+
end
|
101
|
+
if actions.empty?
|
102
|
+
raise Magellan::Subscriber::RoutingError, "topic #{request.topic} has no matched subscriber"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'magellan/rails'
|
3
|
+
require 'set'
|
4
|
+
|
5
|
+
class Magellan::Subscriber::Request
|
6
|
+
attr_reader :headers, :options, :topic, :body
|
7
|
+
|
8
|
+
def option(key)
|
9
|
+
options[key]
|
10
|
+
end
|
11
|
+
|
12
|
+
def parse_message(request_message)
|
13
|
+
# @options = request_message['options']
|
14
|
+
# TRから送られるメッセージのoptionsの型が本来はHash型なのですが、配列型になってしまっているため、暫定的に空のHashをセットします
|
15
|
+
@options = {}
|
16
|
+
@headers = request_message['headers']
|
17
|
+
@topic = request_message["headers"]["Path-Info"]
|
18
|
+
case request_message["body_encoding"]
|
19
|
+
when /\Aplain\z/i, nil
|
20
|
+
@body = request_message["body"]
|
21
|
+
when /\Abase64\z/i
|
22
|
+
@body = Base64.decode64(request_message['body'])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require "base64"
|
4
|
+
require "magellan/subscriber"
|
5
|
+
|
6
|
+
module Magellan::Subscriber::Testing
|
7
|
+
module Integration
|
8
|
+
def publish(topic, body="")
|
9
|
+
executor = Magellan::Subscriber::Executor.new
|
10
|
+
request_message = {
|
11
|
+
"headers" => {
|
12
|
+
"Method" => "PUBLISH",
|
13
|
+
"Path-Info" => topic,
|
14
|
+
},
|
15
|
+
"body" => Base64.strict_encode64(body),
|
16
|
+
"body_encoding" => "base64",
|
17
|
+
}
|
18
|
+
executor.execute(request_message)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require "magellan"
|
3
|
+
require "magellan/rails"
|
4
|
+
|
5
|
+
module Magellan::Subscriber
|
6
|
+
autoload :Executor, "magellan/subscriber/executor"
|
7
|
+
autoload :Request, "magellan/subscriber/request"
|
8
|
+
autoload :Mapper, "magellan/subscriber/mapper"
|
9
|
+
autoload :Base, "magellan/subscriber/base"
|
10
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'magellan/rails'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Magellan::Worker::Config
|
6
|
+
class << self
|
7
|
+
|
8
|
+
def parse_boolean(val, default_value=false)
|
9
|
+
case val
|
10
|
+
when /\A1\z/, /\Atrue\z/i, /\Ayes\z/i, /\Aon\z/
|
11
|
+
true
|
12
|
+
when /\A0\z/, /\Afalse\z/i, /\Ano\z/i, /\Aoff\z/
|
13
|
+
false
|
14
|
+
else
|
15
|
+
default_value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def load_config()
|
20
|
+
config = {}
|
21
|
+
config[:host] = ENV['RABBITMQ_PORT_5672_TCP_ADDR']
|
22
|
+
config[:port] = ENV['RABBITMQ_PORT_5672_TCP_PORT']
|
23
|
+
config[:vhost] = ENV['VHOST']
|
24
|
+
config[:rabbitmq_user] = ENV['RABBITMQ_USER']
|
25
|
+
config[:rabbitmq_password] = ENV['RABBITMQ_PASS']
|
26
|
+
config[:request_queue] = ENV['REQUEST_QUEUE']
|
27
|
+
config[:response_exchange] = ENV['RESPONSE_EXCHANGE']
|
28
|
+
config[:http_worker] = parse_boolean(ENV['MAGELLAN_HTTP_WORKER'], true)
|
29
|
+
config[:subscriber_worker] = parse_boolean(ENV['MAGELLAN_SUBSCRIBER_WORKER'], true)
|
30
|
+
config
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'magellan/rails'
|
3
|
+
require "magellan/worker"
|
4
|
+
require "magellan/extentions"
|
5
|
+
|
6
|
+
require 'json'
|
7
|
+
require "bunny"
|
8
|
+
|
9
|
+
class Magellan::Worker::Core
|
10
|
+
|
11
|
+
attr_reader :config
|
12
|
+
|
13
|
+
def initialize()
|
14
|
+
# ワーカーの設定ファイルを読み込む
|
15
|
+
@config = Magellan::Worker::Config.load_config
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize!
|
19
|
+
# 設定ファイルからRabbitMQへの接続設定を作成
|
20
|
+
connection_settings = {
|
21
|
+
host: @config[:host],
|
22
|
+
port: @config[:port],
|
23
|
+
vhost: @config[:vhost],
|
24
|
+
user: @config[:rabbitmq_user],
|
25
|
+
pass: @config[:rabbitmq_password],
|
26
|
+
timeout: 0.3
|
27
|
+
}
|
28
|
+
|
29
|
+
@conn = Bunny.new(connection_settings)
|
30
|
+
@conn.start
|
31
|
+
@channel = @conn.create_channel
|
32
|
+
|
33
|
+
queue_name = @config[:request_queue]
|
34
|
+
exchange_name = @config[:response_exchange]
|
35
|
+
|
36
|
+
# no_declareを設定しない場合、キューやエクスチェンジに対してdeclareを実行してしまい、
|
37
|
+
# Acess Contorolにひっかかりエラーとなります
|
38
|
+
# queueとexchange及びbindはmagellan-conductorによって作成済みの想定です
|
39
|
+
@queue = @channel.queue(queue_name, no_declare: true)
|
40
|
+
@exchange = @channel.exchange(exchange_name, no_declare: true)
|
41
|
+
|
42
|
+
@executor = Magellan::Worker::Executor.new(@exchange)
|
43
|
+
|
44
|
+
self
|
45
|
+
end
|
46
|
+
|
47
|
+
def run
|
48
|
+
Magellan.logger.info("====== Magellan Worker start ======")
|
49
|
+
@queue.subscribe(block: true, ack: true) do |delivery_info, properties, payload|
|
50
|
+
reply_to = properties.reply_to # ワーカー実行結果返却時のルーティングキー
|
51
|
+
correlation_id = properties.correlation_id # ワーカー実行結果返却時にどのリクエストに対応するメッセージか判別するための識別子
|
52
|
+
delivery_tag = delivery_info.delivery_tag # ackを返却時に使用
|
53
|
+
|
54
|
+
# ワーカーロジック実行中に落ちたとしてもRabbitMQから再送させないために
|
55
|
+
# メッセージを取得した直後にackを返します
|
56
|
+
# 第1引数: ackを返す対象のメッセージを指定
|
57
|
+
# 第2引数: ackを返す対象以前のメッセージもackを返すか
|
58
|
+
# true: 指定したメッセージ以前に受信したメッセージ全てが対象
|
59
|
+
# false: 指定したメッセージのみが対象
|
60
|
+
@channel.basic_ack(delivery_tag, false)
|
61
|
+
|
62
|
+
begin
|
63
|
+
request_message = JSON.parse(payload)
|
64
|
+
@executor.execute(reply_to, correlation_id, delivery_tag, request_message)
|
65
|
+
rescue
|
66
|
+
Magellan.logger.error("Magellan Worker request execution error: #{$!}\n" + $@.join("\n"))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'magellan/rails'
|
3
|
+
require "magellan/subscriber"
|
4
|
+
require "bunny"
|
5
|
+
|
6
|
+
class Magellan::Worker::Executor
|
7
|
+
def initialize(exchange)
|
8
|
+
@exchange = exchange
|
9
|
+
@rails_executor = nil
|
10
|
+
@subscriber_executor = nil
|
11
|
+
|
12
|
+
# Rails 環境の初期化は Subscriber だけの時も実施する
|
13
|
+
# Rails.root やら Rails.application.config がないと困ることが多いと思うので
|
14
|
+
require File.expand_path('config/environment')
|
15
|
+
|
16
|
+
# production 環境で subscriber として動作する時は eager loading しておく
|
17
|
+
if Rails.env.production? and Magellan::Worker.worker.config[:subscriber_worker]
|
18
|
+
subscriber_executor
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def rails_executor
|
23
|
+
@rails_executor ||= Magellan::Rails::Executor.new(@exchange)
|
24
|
+
end
|
25
|
+
|
26
|
+
def subscriber_executor
|
27
|
+
@subscriber_executor ||= Magellan::Subscriber::Executor.new
|
28
|
+
end
|
29
|
+
|
30
|
+
def execute(reply_to, correlation_id, delivery_tag, request_message)
|
31
|
+
case request_message["headers"]["Method"]
|
32
|
+
when /\Apublish\z/i
|
33
|
+
subscriber_executor.execute(request_message)
|
34
|
+
else
|
35
|
+
rails_executor.execute(reply_to, correlation_id, delivery_tag, request_message)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require "magellan"
|
3
|
+
|
4
|
+
module Magellan::Worker
|
5
|
+
autoload :Core, 'magellan/worker/core'
|
6
|
+
autoload :Executor, 'magellan/worker/executor'
|
7
|
+
autoload :Config, 'magellan/worker/config'
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def worker
|
11
|
+
@worker ||= Magellan::Worker::Core.new
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/magellan.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'logger'
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
module Magellan
|
6
|
+
autoload :Rails, 'magellan/rails'
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_accessor :logger
|
10
|
+
|
11
|
+
# loggerの設定
|
12
|
+
# ログレベルは環境変数: MAGELLAN_RAILS_LOG_LEVEL に設定して必要に応じて変更してください
|
13
|
+
environment = ENV['RAILS_ENV'] || 'development'
|
14
|
+
log_dir = File.expand_path("log")
|
15
|
+
FileUtils.makedirs(log_dir) unless File.exists?(log_dir)
|
16
|
+
logger = ::Logger.new(File.expand_path("log/#{environment}.log"))
|
17
|
+
|
18
|
+
log_level_env = ENV['MAGELLAN_RAILS_LOG_LEVEL']
|
19
|
+
log_levels = ['debug', 'info', 'warn', 'error', 'fatal', 'unknown']
|
20
|
+
if log_level_env && log_levels.include?(log_level_env)
|
21
|
+
log_level = Logger.const_get(log_level_env.upcase.to_sym)
|
22
|
+
else
|
23
|
+
log_level = Logger::INFO
|
24
|
+
end
|
25
|
+
logger.level = log_level
|
26
|
+
Magellan.logger = logger
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'magellan/rails/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "magellan-rails"
|
8
|
+
spec.version = Magellan::Rails::VERSION
|
9
|
+
spec.authors = ["Yuuki Noguchi"]
|
10
|
+
spec.email = ["otonakaoru@gmail.com"]
|
11
|
+
spec.summary = %q{}
|
12
|
+
spec.description = %q{}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_runtime_dependency "railties", '~> 4.1.0'
|
22
|
+
spec.add_runtime_dependency "bunny"
|
23
|
+
spec.add_runtime_dependency "json"
|
24
|
+
|
25
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
26
|
+
spec.add_development_dependency "rspec"
|
27
|
+
# spec.add_development_dependency "bunny_mock"
|
28
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
describe Magellan::Rails::Request do
|
7
|
+
describe '#parse_message' do
|
8
|
+
before(:all) do
|
9
|
+
@request_message_base = {
|
10
|
+
'headers' => {
|
11
|
+
'Title' => 'groovenauts-app',
|
12
|
+
'Interface-Version' => '1.0.0',
|
13
|
+
'Title-Runtime-Version'=> '1.0.0',
|
14
|
+
'Reference-Id' => '192.168.1.110',
|
15
|
+
'Url' => 'http://magellan-clouds.com/worker/test',
|
16
|
+
'Oauth-Requester-Id' => 'tarou',
|
17
|
+
'Content-Type' => 'application/json',
|
18
|
+
'Method' => 'GET',
|
19
|
+
"Server-Name" => "localhost",
|
20
|
+
"Server-Port" => 3000,
|
21
|
+
"Path-Info" => "/hello/index",
|
22
|
+
"Query-String" => "qs1=abc&qs2=def"
|
23
|
+
},
|
24
|
+
'body' => '',
|
25
|
+
'body_encoding' => 'plain',
|
26
|
+
'options' => {
|
27
|
+
# 当分実装される予定がなく、空のハッシュが渡されます
|
28
|
+
# 'reply_ttl' => 1000
|
29
|
+
}
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
context "valid format" do
|
34
|
+
context "body_encoding=nil" do
|
35
|
+
let(:request){ Magellan::Rails::Request.new }
|
36
|
+
|
37
|
+
before do
|
38
|
+
@request_message = @request_message_base.dup
|
39
|
+
@request_message.delete("body_encoding")
|
40
|
+
end
|
41
|
+
|
42
|
+
subject{ request }
|
43
|
+
|
44
|
+
it do
|
45
|
+
request.parse_message(@request_message)
|
46
|
+
expect(request.headers).to eq(@request_message['headers'])
|
47
|
+
expect(request.body ).to eq(@request_message['body'])
|
48
|
+
expect(request.options).to eq(@request_message['options'])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "body_encoding=plain" do
|
53
|
+
let(:request){ Magellan::Rails::Request.new }
|
54
|
+
|
55
|
+
before do
|
56
|
+
@request_message = @request_message_base.dup
|
57
|
+
end
|
58
|
+
|
59
|
+
subject{ request }
|
60
|
+
|
61
|
+
it do
|
62
|
+
request.parse_message(@request_message)
|
63
|
+
expect(request.headers).to eq(@request_message['headers'])
|
64
|
+
expect(request.body ).to eq(@request_message['body'])
|
65
|
+
expect(request.options).to eq(@request_message['options'])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "body_encoding=base64" do
|
70
|
+
let(:request){ Magellan::Rails::Request.new }
|
71
|
+
|
72
|
+
before do
|
73
|
+
@request_body = "\xff"
|
74
|
+
@request_message = @request_message_base.dup
|
75
|
+
@request_message['body'] = Base64.strict_encode64(@request_body)
|
76
|
+
@request_message['body_encoding'] = 'base64'
|
77
|
+
end
|
78
|
+
|
79
|
+
subject{ request }
|
80
|
+
|
81
|
+
it do
|
82
|
+
request.parse_message(@request_message)
|
83
|
+
expect(request.headers).to eq(@request_message['headers'])
|
84
|
+
expect(request.body.inspect).to eq(@request_body.inspect)
|
85
|
+
expect(request.options).to eq(@request_message['options'])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
context "invalid format" do
|
91
|
+
it 'raise invalid format exception'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
describe '#option' do
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#reply_ttl' do
|
99
|
+
end
|
100
|
+
|
101
|
+
describe '#to_rack_env' do
|
102
|
+
end
|
103
|
+
end
|