def GET(self): args = web.input() output_format = args.get("output_format", "") version = catoconfig.VERSION if output_format == "json": response = api.response(response='{"Version" : "%s"}' % version) elif output_format == "text": response = api.response(response=version) else: response = api.response(response="<Version>%s</Version>" % version) return response.Write(output_format)
def handle(self): try: return web.application.handle(self) except (web.HTTPError, KeyboardInterrupt, SystemExit): raise except InfoException as ex: # we're using a custom HTTP status code to indicate 'information' back to the user. args = web.input() web.ctx.status = "280 Informational Response" output_format = args.get("output_format", "") logger.info(ex.__str__()) response = api.response(err_code=api.response.Codes.Exception, err_detail=ex.__str__()) return response.Write(output_format) except Exception as ex: args = web.input() web.ctx.status = "400 Bad Request" output_format = args.get("output_format", "") logger.exception(ex.__str__()) response = api.response(err_code=api.response.Codes.Exception, err_detail=ex.__str__()) return response.Write(output_format)
def go(self, method): args = web.input() web.header('X-CSK-Method', method) # web.header('Content-Type', 'text/xml') # here's the rub - if this was a POST, there might be lots of additional data in web.data(). # the keys above in web.input() are valid too, but the post args take precedence. # so, merge them. if web.data(): # TODO: don't continue to assume JSON, base the unpacking of the args on the Content-Type header ct = web.ctx.env.get('CONTENT_TYPE') logger.debug("Content-Type: %s" % (ct)) if ct != "application/json": logger.warning("POST data should set the header - Content-Type: application/json.") # TODO: this should be based on content-type, but for now we continue to assume it's json # regardless of the content-type header postargs = catocommon.argloader(web.data()) if postargs: logger.info("Post Data: %s" % postargs) for k, v in postargs.iteritems(): args[k] = v logger.info("Request: %s" % method) logger.info("Args: %s" % args) output_format = args.get("output_format", "") is_authenticated, user_id = api.authenticate(method, args) if not is_authenticated: # authentication failures won't return details to the client # but will write some info in the api log # the second return arg holds a failure code if getattr(args, 'key', ''): logger.error("Authentication Failure [%s] - [%s]" % (getattr(args, 'key', ''), user_id)) else: logger.error("Authentication Failure [%s]" % user_id) response = api.response(err_code="AuthenticationFailure", err_msg="Authentication Failure") return response.Write(output_format) # the args collection is passed to the target function, BUT # we wanna stick a few things in there we might need. args["output_format"] = output_format # THESE FLAGS GRANT SPECIAL ABILITIES!!!! # ensure they are cleared before authenticating each request api._ADMIN = False api._DEVELOPER = False # the API commands do some logging that use these detail properties u = catouser.User() u.FromID(user_id) if u: logger.debug("""Authenticated: User: %s Full Name: %s Role: %s Tags: %s""" % (u.LoginID, u.FullName, u.Role, u.Tags)) api._USER_ID = u.ID api._USER_ROLE = u.Role api._USER_FULLNAME = u.FullName # flags are set so certain methods can have restricted access. if u.Role == "Administrator": logger.info("[%s] is operating with ADMIN privileges." % (u.FullName)) api._ADMIN = True api._DEVELOPER = True if u.Role == "Developer": logger.info("[%s] is operating with DEVELOPER privileges." % (u.FullName)) api._DEVELOPER = True # Tags are placed in a global for any access checks api._USER_TAGS = u.Tags else: logger.error("Authenticated, but unable to build a User object.") response = api.response(err_code="Exception", err_msg="Authenticated, but unable to build a User object.") return response.Write(output_format) endpoints = api.endpoints # If Maestro is enabled, load those endpoints try: sys.path.insert(0, os.path.join(CSK_HOME, "maestro", "lib")) from maestroapi import api as mapi endpoints = dict(endpoints.items() + mapi.endpoints.items()) except: pass # If Legato is enabled, load those endpoints try: sys.path.insert(0, os.path.join(CSK_HOME, "legato", "lib")) from cskcdapi import api as cdapi endpoints = dict(endpoints.items() + cdapi.endpoints.items()) except: pass if endpoints.get(method): response = catocommon.FindAndCall(endpoints[method], args) else: response = api.response(err_code="Exception", err_msg="'%s' is not a valid API endpoint." % (method)) return response.Write(output_format) # FindAndCall can have all sorts of return values. # in this case, we expect it would be an api.response object. # but never assume if hasattr(response, "Method"): response.Method = method # is this a JSONP request? if "callback" in args: """ IF there is an arg called "callback", that means we want the results formatted as a javascript function call. (of course, if we wanna eventually support both XML and JSON result types that's fine... it just means the payload *inside* the jsonp callback will be xml or json as requested.) """ payload = response.Write(output_format) web.header('Content-Type', 'application/javascript') return "%s(%s)" % (args["callback"], payload) else: return response.Write(output_format) else: # the result from FindAndCall wasn't a response object. # so make one response = api.response(err_code=api.response.Codes.Exception, err_detail=response) return response.Write(output_format)