################################################################################ # Copyright (C) 2013-2014 by gempa GmbH # # HTTP -- Utility methods which generate HTTP result strings # # Author: Stephan Herrnkind # Email: herrnkind@gempa.de ################################################################################ from twisted.web import http, resource, server, static, util import seiscomp.core import seiscomp.logging from .utils import accessLog, b_str, u_str, writeTSBin VERSION = "1.2.5" ################################################################################ class HTTP: # --------------------------------------------------------------------------- @staticmethod def renderErrorPage(request, code, msg, version=VERSION, ro=None): resp = b"""\ Error %i: %s %s Usage details are available from %s Request: %s Request Submitted: %s Service Version: %s """ noContent = code == http.NO_CONTENT # rewrite response code if requested and no data was found if noContent and ro is not None: code = ro.noData # set response code request.setResponseCode(code) # status code 204 requires no message body if code == http.NO_CONTENT: response = b"" else: request.setHeader("Content-Type", "text/plain; charset=utf-8") reference = b"%s/" % request.path.rpartition(b"/")[0] codeStr = http.RESPONSES[code] date = b_str(seiscomp.core.Time.GMT().toString("%FT%T.%f")) response = resp % ( code, codeStr, b_str(msg), reference, request.uri, date, b_str(version), ) if not noContent: seiscomp.logging.warning( f"responding with error: {code} ({u_str(codeStr)})" ) accessLog(request, ro, code, len(response), msg) return response # --------------------------------------------------------------------------- @staticmethod def renderNotFound(request, version=VERSION): msg = "The requested resource does not exist on this server." return HTTP.renderErrorPage(request, http.NOT_FOUND, msg, version) # --------------------------------------------------------------------------- @staticmethod def renderNotModified(request, ro=None): code = http.NOT_MODIFIED request.setResponseCode(code) request.responseHeaders.removeHeader("Content-Type") accessLog(request, ro, code, 0, None) ################################################################################ class ServiceVersion(resource.Resource): isLeaf = True # --------------------------------------------------------------------------- def __init__(self, version): super().__init__() self.version = version self.type = "text/plain" # --------------------------------------------------------------------------- def render(self, request): request.setHeader("Content-Type", "text/plain; charset=utf-8") return b_str(self.version) ################################################################################ class WADLFilter(static.Data): # --------------------------------------------------------------------------- def __init__(self, path, paramNameFilterList): data = "" removeParam = False with open(path, "r", encoding="utf-8") as fp: for line in fp: lineStripped = line.strip().replace(" ", "") if removeParam: if "" in lineStripped: removeParam = False continue valid = True if "": removeParam = True break if valid: data += line super().__init__(b_str(data), "application/xml; charset=utf-8") ################################################################################ class BaseResource(resource.Resource): # --------------------------------------------------------------------------- def __init__(self, version=VERSION): super().__init__() self.version = version # --------------------------------------------------------------------------- def renderErrorPage(self, request, code, msg, ro=None): return HTTP.renderErrorPage(request, code, msg, self.version, ro) # --------------------------------------------------------------------------- def writeErrorPage(self, request, code, msg, ro=None): data = self.renderErrorPage(request, code, msg, ro) if data: writeTSBin(request, data) # --------------------------------------------------------------------------- def returnNotModified(self, request, ro=None): HTTP.renderNotModified(request, ro) # --------------------------------------------------------------------------- # Renders error page if the result set exceeds the configured maximum number # objects def checkObjects(self, request, objCount, maxObj): if objCount <= maxObj: return True msg = ( "The result set of your request exceeds the configured maximum " f"number of objects ({maxObj}). Refine your request parameters." ) self.writeErrorPage(request, http.REQUEST_ENTITY_TOO_LARGE, msg) return False ################################################################################ class NoResource(BaseResource): isLeaf = True # --------------------------------------------------------------------------- def render(self, request): return HTTP.renderNotFound(request, self.version) # --------------------------------------------------------------------------- def getChild(self, _path, _request): return self ################################################################################ class ListingResource(BaseResource): html = """
Index of %s