132 lines
3.0 KiB
Ruby
132 lines
3.0 KiB
Ruby
# typed: strict
|
|
class HttpLogEntry < ReduxApplicationRecord
|
|
include ImmutableModel
|
|
before_destroy { raise ActiveRecord::ReadOnlyRecord }
|
|
|
|
enum :verb, %i[get post], prefix: true
|
|
enum :performed_by,
|
|
%i[
|
|
direct
|
|
legacy
|
|
proxy-1
|
|
dedipath-1
|
|
direct-gdl
|
|
serverhost-1
|
|
airvpn-1-netherlands
|
|
airvpn-2-san-jose
|
|
tor-1
|
|
],
|
|
prefix: true
|
|
|
|
belongs_to :response,
|
|
foreign_key: :response_sha256,
|
|
class_name: "::BlobFile",
|
|
autosave: true
|
|
|
|
belongs_to :request_headers, class_name: "::HttpLogEntryHeader"
|
|
|
|
belongs_to :response_headers, class_name: "::HttpLogEntryHeader"
|
|
|
|
validates :response_sha256, length: { is: 32 }
|
|
|
|
belongs_to :caused_by_entry,
|
|
class_name: "::HttpLogEntry",
|
|
foreign_key: :caused_by_id,
|
|
optional: true
|
|
|
|
has_many :triggered_entries,
|
|
class_name: "::HttpLogEntry",
|
|
foreign_key: :caused_by_id
|
|
|
|
validates_presence_of(
|
|
:uri_scheme,
|
|
:uri_host,
|
|
:uri_path,
|
|
:verb,
|
|
:performed_by,
|
|
:status_code,
|
|
:response_time_ms,
|
|
:content_type,
|
|
:requested_at,
|
|
)
|
|
|
|
sig do
|
|
params(uri: T.any(String, Addressable::URI)).returns(
|
|
T.nilable(HttpLogEntry),
|
|
)
|
|
end
|
|
def self.find_by_uri_host_path(uri)
|
|
uri = Addressable::URI.parse(uri) unless uri.is_a?(Addressable::URI)
|
|
where(uri_host: uri.host, uri_path: uri.path).order(
|
|
requested_at: :desc,
|
|
).first
|
|
end
|
|
|
|
sig do
|
|
params(uri: T.any(String, Addressable::URI)).returns(
|
|
T.nilable(HttpLogEntry),
|
|
)
|
|
end
|
|
def self.find_by_uri(uri)
|
|
find_all_by_uri(uri).first
|
|
end
|
|
|
|
sig do
|
|
params(uri: T.any(String, Addressable::URI)).returns(
|
|
::ActiveRecord::Relation,
|
|
)
|
|
end
|
|
def self.find_all_by_uri(uri)
|
|
if uri.is_a?(String) &&
|
|
%w[https:// http:// //].none? { |prefix| uri.start_with?(prefix) }
|
|
uri = "//#{uri}"
|
|
end
|
|
uri = Addressable::URI.parse(uri) unless uri.is_a?(Addressable::URI)
|
|
where(
|
|
uri_host: uri.host,
|
|
uri_path: uri.path,
|
|
uri_query: uri.query,
|
|
uri_hash: uri.fragment,
|
|
).order(requested_at: :desc)
|
|
end
|
|
|
|
sig { returns(T.nilable(Integer)) }
|
|
def response_size
|
|
response&.size_bytes
|
|
end
|
|
|
|
sig { returns(T.nilable(String)) }
|
|
def response_bytes
|
|
response&.content_bytes
|
|
end
|
|
|
|
sig { params(uri: T.any(String, Addressable::URI)).void }
|
|
def uri=(uri)
|
|
uri = Addressable::URI.parse(uri) if uri.is_a?(String)
|
|
self.uri_scheme = uri.scheme
|
|
self.uri_host = uri.host
|
|
self.uri_path = uri.path
|
|
self.uri_query = uri.query
|
|
self.uri_hash = uri.fragment
|
|
end
|
|
|
|
sig { returns(Addressable::URI) }
|
|
def uri
|
|
Addressable::URI.parse(uri_str)
|
|
end
|
|
|
|
sig { returns(String) }
|
|
def uri_str
|
|
"#{uri_scheme}://#{uri_host}#{uri_str_without_host}"
|
|
end
|
|
|
|
sig { returns(String) }
|
|
def uri_str_without_host
|
|
str = ""
|
|
str += "#{uri_path}"
|
|
str += "?#{uri_query}" if uri_query
|
|
str += "\##{uri_hash}" if uri_hash
|
|
str
|
|
end
|
|
end
|