How To Create An ICAPrb Service
Because having only an ICAP server is boring because it is doing nothing. So you should write your first Service.
So lets start with a little template:
# load the icap server
require 'icaprb/server'
# create a class that inherits the base of (all) ICAP services in ICAPrb
class SampleService < ::ICAPrb::Server::Services::ServiceBase
# initialize the service: our module does only RESPMOD
# (which means it has no support to edit responses which are
# called REQMOD in the protocol and request_mod in ICAPrb)
def initialize
# the first parameter here is the service name used in the icap headers (not the URL)
super('name',[:response_mod])
end
# you need to override this method to do the work of your module
def process_request(icap_server,ip,socket,data)
# get the logger from the server to use it for sending data to the log
# use it for errors in your module
# logger = icap_server.logger
# this creates a new ICAP response to be sent to the ICAP client
response = ::ICAPrb::Server::Response.new
# if you change the data, you should use 200.
# If the data is unchanged and the client accepts 204, use it here
# as it is shorter (less network traffic, better performance).
response.icap_status_code = 200
http_resp_header = data[:http_response_header]
http_resp_body = data[:http_response_body]
# do your modification here
# modified is a variable you must set
if modified
# this will update the HTTP Content-Length header because the length may have changed
# (for example if you removed ad tags, the content is shorter now)
http_resp_header['Content-Length'] = http_resp_body.length.to_s
# this is required by the interface of ICAPrb::Server
# it detects that this string is an ICAP response body by checking the type (class)
http_resp_body = ::ICAPrb::Server::ResponseBody.new(http_resp_body)
# add the components to your response - order does not matter because it will find it by the type - other types are ignored.
# If you have an error here, your response may be malformed and your ICAP service is broken - make sure you are not using a wrong type like string.
response.components << http_resp_header
response.components << http_resp_body
# this method sends only the headers to the socket, not the content itself - if your
response.write_headers_to_socket socket
# send everything in one chunk - you could use multiple but you are not required to - on large downloads, this may make sense
socket.write(http_resp_body.to_chunk)
# this methods sends the last chunk of your connection - after that, the connection may be terminated
::ICAPrb::Server::Response.send_last_chunk(socket,false)
else
# Just send a 204 message (we do not check if it is supported here because this is only a short sample).
response.icap_status_code = 204
response.write_headers_to_socket socket
end
end
end
The next step is using it in your ICAPrb server. It is really simple. If s
contains the instance of your server, you only need to attach it.
# this makes your service available as service.
# For example, your URL may look like icap://[::1]:1344/service
s.services['service'] = SampleService.new