-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathbody_builder.rb
More file actions
103 lines (93 loc) · 3.83 KB
/
body_builder.rb
File metadata and controls
103 lines (93 loc) · 3.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# encoding: UTF-8
# frozen_string_literal: true
require "faraday"
require "faraday_middleware"
require_relative "response"
require_relative "protocol"
require "active_support"
require "active_support/core_ext"
module Parse
# @!attribute self.logging
# Sets {Parse::Middleware::BodyBuilder} logging.
# You may specify `:debug` for additional verbosity.
# @return (see Parse::Middleware::BodyBuilder.logging)
def self.logging
Parse::Middleware::BodyBuilder.logging
end
# @!visibility private
def self.logging=(value)
Parse::Middleware::BodyBuilder.logging = value
end
# Namespace for Parse-Stack related middleware.
module Middleware
# This middleware takes an incoming Parse response, after an outgoing request,
# and creates a Parse::Response object.
class BodyBuilder < Faraday::Middleware
include Parse::Protocol
# Header sent when a GET requests exceeds the limit.
HTTP_METHOD_OVERRIDE = "X-Http-Method-Override"
# Maximum url length for most server requests before HTTP Method Override is used.
MAX_URL_LENGTH = 2_000.freeze
class << self
# Allows logging. Set to `true` to enable logging, `false` to disable.
# You may specify `:debug` for additional verbosity.
# @return [Boolean]
attr_accessor :logging
end
# Thread-safety
# @!visibility private
def call(env)
dup.call!(env)
end
# @!visibility private
def call!(env)
# the maximum url size is ~2KB, so if we request a Parse API url greater than this
# (which is most likely a very complicated query), we need to override the request method
# to be POST instead of GET and send the query parameters in the body of the POST request.
# The standard maximum POST request (which is a server setting), is usually set to 20MBs
if env[:method] == :get && env[:url].to_s.length >= MAX_URL_LENGTH
env[:request_headers][HTTP_METHOD_OVERRIDE] = "GET"
env[:request_headers][CONTENT_TYPE] = "application/x-www-form-urlencoded"
# parse-sever looks for method overrides in the body under the `_method` param.
# so we will add it to the query string, which will now go into the body.
env[:body] = "_method=GET&" + env[:url].query
env[:url].query = nil
#override
env[:method] = :post
# else if not a get, always make sure the request is JSON encoded if the content type matches
elsif env[:request_headers][CONTENT_TYPE] == CONTENT_TYPE_FORMAT &&
(env[:body].is_a?(Hash) || env[:body].is_a?(Array))
env[:body] = env[:body].to_json
end
if self.class.logging
puts "[Request #{env.method.upcase}] #{env[:url]}"
env[:request_headers].each do |k, v|
next if k == Parse::Protocol::MASTER_KEY
puts "[Header] #{k} : #{v}"
end
puts "[Request Body] #{env[:body]}"
end
@app.call(env).on_complete do |response_env|
# on a response, create a new Parse::Response and replace the :body
# of the env
# @todo CHECK FOR HTTP STATUS CODES
if self.class.logging
puts "[[Response #{response_env[:status]}]] ----------------------------------"
puts response_env.body
puts "[[Response]] --------------------------------------\n"
end
begin
r = Parse::Response.new(response_env.body)
rescue => e
r = Parse::Response.new
r.code = response_env.status
r.error = "Invalid response for #{env[:method]} #{env[:url]}: #{e}"
end
r.http_status = response_env[:status]
r.code ||= response_env[:status] if r.error.present?
response_env[:body] = r
end
end
end
end #Middleware
end