############################################################################### # = gradesheet-server.rb # # WEBrick server to supply class gradesheet information. # Copyright (C) 2005 by Allyn Dimock # # Produces a servlet processing https on the port given by the constant PORT # with root given by the constant ROOT. # Constant SHEETS is an array of hashes giving the information about the sheets # that are available: # * id => name to become part of URI # e.g. "https://foo.bar.baz.com/OOCalcGradesheetDocs/301f03/" # if server is running on foo.bar.baz.com, ROOT="/OOCalcGradesheetDocs" # and id => "301f03" # * file => name of OOCalc spresasheet file to be passed to # StreadsheetContent.new # * fixed_rows => array of integers showing rows in spreadsheet to be returned # along with the row for the query. # * id_column => column in spreadsheet that contains an identifier that # indicates the row to be returned. # ############################################################################### raise "Please, use ruby1.8.2 or later." if RUBY_VERSION < "1.8.2" require 'webrick' require 'webrick/https' require 'gradesheet-rows' include WEBrick # Port number of server (default https port number = 443) PORT_NUMBER = 8080 # URI doesn't use a real file name ROOT = "/OOCalcGradesheetDocs" # Certificate: self-certified CERTIFICATE = [ ["C","USA"], ["O","cs.uml.edu"], ["CN", "OocalcGradesheetViewer"] ] # # Gradesheets to serve: # resource name, file name, rows to always return, id column # SHEETS = [ {:id => '301f03', :file => "~/earth/grade301-F03/gradesheet.sxc", :fixed_rows => [1,2,20,21], :id_column => 0}, {:id => '531f03', :file => "~/earth/grade531-F03/roster.sxc", :fixed_rows => [1,35], :id_column => 1} ] ############################################################################### # # Define a HTTPS server following model in "Gnome's Guide to WEBrick" by # Yohanes Santoso. Create new server, then yield to caller who can mount some # services, then start server. # ############################################################################### def start_webrick(config={}) # Should we let caller set any config options? config.update(:Port => PORT_NUMBER) # set port number config.update(:DocumentRoot => ROOT) config.update(:SSLEnable => true) config.update(:SSLVerifyClient => ::OpenSSL::SSL::VERIFY_NONE) config.update(:SSLCertName => CERTIFICATE) server = WEBrick::HTTPServer.new(config) # start server yield server if block_given? # execute caller's block # # Set to trap INT, TERM signals and shut down cleanly on the signal # ['INT','TERM'].each { |signal| trap(signal){ server.shutdown } } server.start end ############################################################################### # # class OOCalcLinesServlet serves requests like # # GET /OOCalcGradesheetDocs/sheet_id/?id=123456789 HTTP/1.1 # From: myhost.mysubdomain.mydomain.com # # * if ?id=... not specified, replies with 412 (Precondition failed) # * if no row is found for the id, replies with 404 (Not Found) # * else replies with 200 (OK) and the payload from the students_html message # passed to the SpreadsheetContent object for sheet_id. # # Requests other than GET are not served! ############################################################################### class OOCalcLinesServlet < HTTPServlet::AbstractServlet ############################################################################# # # Method do_GET handles a get request. # ############################################################################# def do_GET(req,resp) # puts "in do_GET" if req.query['id'] raise HTTPStatus::NotFound if req.query['id'] == "" begin # puts "processing " + '"' + req.query['id'] + '"' obj = @options[0] row = obj.students_row(req.query['id']) rescue Exception => exn puts "found some error " + exn.message print exn.backtrace.join("\n") + "\n" # puts "about to raise NotFound" raise HTTPStatus::NotFound end raise HTTPStatus::NotFound if row.nil? resp.body = obj.students_html(row) # puts "about to raise OK" raise HTTPStatus::OK else # puts "about to raise PreconditionFailed" raise HTTPStatus::PreconditionFailed.new( "missing attribute 'id'") end # if end # def do_GET end # class OOCalcLinesServlet ############################################################################### # # Start the web service: # Create SpreadsheetContent.new for each sheet in SHEETS, # Start web server # Mount a resource for each gradesheet being serviced. # ############################################################################### def start_service() sheets = [] # initialize gradesheet info for each gradesheet served SHEETS.each { |sheet| sheets << {'id' => sheet[:id], 'obj' => SpreadsheetContent.new(sheet[:file],sheet[:fixed_rows], sheet[:id_column])} } # start WEBrick HTTP server start_webrick() { |server| # mount a resource for each gradesheet served sheets.each { |sheet| server.mount(ROOT + '/' + sheet['id'], OOCalcLinesServlet, sheet['obj']) } # sheets.each } # block to start_webrick() end # start_service start_service()