magellan-rails 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|