Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Authn delegation via HTTP by mod_mruby
HOST="127.0.0.1"
PORT=80
PATH="/redmine/users/current.xml" # Using Redmine REST I/F as an example.
def main
anp = Apache::AuthnProvider.new
credentials = [[anp.user, anp.password].join(":")].pack("m").gsub("\n", "")
request = {}
request['User-Agent'] = "mruby_authn_http/0.1"
request['Authorization'] = "Basic #{credentials}"
http = SimpleHttp.new(HOST, PORT)
ret = http.request("HEAD", PATH, request)
if ret.code == 200
return(Apache::AuthnProvider::AUTH_GRANTED)
else
return(Apache::AuthnProvider::AUTH_DENIED)
end
rescue => e
Apache.errlogger(3, "mruby_authn_http An exception occured : #{e.inspect}")
return Apache::AuthnProvider::AUTH_DENIED
end
##
# Simple Http
# from https://gist.github.com/3765572
class SimpleHttp
DEFAULTPORT = 80
HTTP_VERSION = "HTTP/1.0"
DEFAULT_ACCEPT = "*/*"
SEP = "\r\n"
def initialize(address, port = DEFAULTPORT)
@socket
@uri = {}
@uri[:address] = address
@uri[:port] = port ? port.to_i : DEFAULTPORT
self
end
def address; @uri[:address]; end
def port; @uri[:port]; end
def get(path = "/", request = nil)
request("GET", path, request)
end
def post(path = "/", request = nil)
request("POST", path, request)
end
# private
def request(method, path, req)
@uri[:path] = path
if @uri[:path].nil?
@uri[:path] = "/"
elsif @uri[:path][0] != "/"
@uri[:path] = "/" + @uri[:path]
end
request_header = create_request_header(method.upcase.to_s, req)
response_text = send_request(request_header)
SimpleHttpResponse.new(response_text)
end
def send_request(request_header)
@socket = TCPSocket.new(@uri[:address], @uri[:port])
@socket.write(request_header)
response_text = ""
while (t = @socket.read(1024))
response_text += t
end
@socket.close
response_text
end
def create_request_header(method, req)
req = {} unless req
str = ""
body = ""
str += sprintf("%s %s %s", method, @uri[:path], HTTP_VERSION) + SEP
header = {}
req.each do |key,value|
header[key.capitalize] = value
end
header["Host"] = @uri[:address] unless header.keys.include?("Host")
header["Accept"] = DEFAULT_ACCEPT unless header.keys.include?("Accept")
header["Connection"] = "close"
if header["Body"]
body = header["Body"]
header.delete("Body")
end
if method == "POST" && (not header.keys.include?("content-length".capitalize))
header["Content-Length"] = (body || '').length
end
header.keys.sort.each do |key|
str += sprintf("%s: %s", key, header[key]) + SEP
end
str + SEP + body
end
class SimpleHttpResponse
SEP = SimpleHttp::SEP
def initialize(response_text)
@response = {}
if response_text.include?(SEP + SEP)
@response["header"], @response["body"] = response_text.split(SEP + SEP)
else
@response["header"] = response_text
end
parse_header
self
end
def [](key); @response[key]; end
def []=(key, value); @response[key] = value; end
def header; @response['header']; end
def body; @response['body']; end
def status; @response['status']; end
def code; @response['code']; end
def date; @response['date']; end
def content_type; @response['content-type']; end
def content_length; @response['content-length']; end
def each(&block)
if block
@response.each do |k,v| block.call(k,v) end
end
end
def each_name(&block)
if block
@response.each do |k,v| block.call(k) end
end
end
# private
def parse_header
return unless @response["header"]
h = @response["header"].split(SEP)
if h[0].include?("HTTP/1")
@response["status"] = h[0].split(" ", 2).last
@response["code"] = h[0].split(" ", 3)[1].to_i
end
h.each do |line|
if line.include?(": ")
k,v = line.split(": ")
@response[k.downcase] = v
end
end
end
end
end
Apache.return(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.