///|
pub struct AccessRecord {
verb : String
url : String
status : Int
agent : String
} derive(Debug, Eq)
///|
pub fn access_record(
verb : String,
url : String,
status : Int,
agent : String,
) -> AccessRecord {
{ verb, url, status, agent }
}
///|
pub fn replay_access(
text : String,
records : Array[AccessRecord],
) -> Array[String] {
let robots = parse(text)
let lines : Array[String] = []
for record in records {
let decision = decide_url(robots, record.agent, record.url)
if !decision.allowed {
lines.push(
record.verb + " " + record.url + " violates " + decision.matched_pattern,
)
}
}
lines
}
///|
pub fn replay_report(text : String, records : Array[AccessRecord]) -> String {
let lines = replay_access(text, records)
if lines.is_empty() {
"ok"
} else {
join_lines(lines)
}
}
///|
pub fn records_for_agent(
records : Array[AccessRecord],
agent : String,
) -> Array[AccessRecord] {
let result : Array[AccessRecord] = []
let needle = normalize_agent(agent)
for record in records {
if normalize_agent(record.agent).find(needle) is Some(_) {
result.push(record)
}
}
result
}
///|
pub fn count_status(records : Array[AccessRecord], status : Int) -> Int {
let mut total = 0
for record in records {
if record.status == status {
total += 1
}
}
total
}
///|
pub fn access_summary(records : Array[AccessRecord]) -> String {
"records=" +
records.length().to_string() +
" ok=" +
count_status(records, 200).to_string() +
" not_found=" +
count_status(records, 404).to_string()
}