src/modules/server/depot.py
changeset 2026 d1b30615bc99
parent 2011 735c3fcb057b
child 2028 b2c674e6ee28
equal deleted inserted replaced
2025:4ba5092f1b06 2026:d1b30615bc99
   143             "info",
   143             "info",
   144             "manifest",
   144             "manifest",
   145             "filelist",
   145             "filelist",
   146             "file",
   146             "file",
   147             "open",
   147             "open",
       
   148             "append",
   148             "close",
   149             "close",
   149             "abandon",
   150             "abandon",
   150             "add",
   151             "add",
   151             "p5i",
   152             "p5i",
   152             "publisher",
   153             "publisher",
   706                 self.__set_response_expires("file", 86400*365, 86400*365)
   707                 self.__set_response_expires("file", 86400*365, 86400*365)
   707                 return serve_file(fpath, "application/data")
   708                 return serve_file(fpath, "application/data")
   708 
   709 
   709         file_0._cp_config = { "response.stream": True }
   710         file_0._cp_config = { "response.stream": True }
   710 
   711 
       
   712         def file_1(self, *tokens):
       
   713                 """Outputs the contents of the file, named by the SHA-1 hash
       
   714                 name in the request path, directly to the client."""
       
   715 
       
   716                 method = cherrypy.request.method
       
   717                 if method == "GET":
       
   718                         return self.file_0(*tokens)
       
   719                 elif method in ("POST", "PUT"):
       
   720                         return self.__upload_file(*tokens)
       
   721                 raise cherrypy.HTTPError(httplib.METHOD_NOT_ALLOWED,
       
   722                     "%s is not allowed" % method)
       
   723 
       
   724         # We need to prevent cherrypy from processing the request body so that
       
   725         # file can parse the request body itself.  In addition, we also need to
       
   726         # set the timeout higher since the default is five minutes; not really
       
   727         # enough for a slow connection to upload content.
       
   728         file_1._cp_config = {
       
   729             "request.process_request_body": False,
       
   730             "response.timeout": 3600,
       
   731             "response.stream": True
       
   732         }
       
   733 
   711         @cherrypy.tools.response_headers(headers=[("Pragma", "no-cache"),
   734         @cherrypy.tools.response_headers(headers=[("Pragma", "no-cache"),
   712             ("Cache-Control", "no-cache, no-transform, must-revalidate"),
   735             ("Cache-Control", "no-cache, no-transform, must-revalidate"),
   713             ("Expires", 0)])
   736             ("Expires", 0)])
   714         def open_0(self, *tokens):
   737         def open_0(self, *tokens):
   715                 """Starts a transaction for the package name specified in the
   738                 """Starts a transaction for the package name specified in the
   728                 # signed certificate (or a more elaborate system).
   751                 # signed certificate (or a more elaborate system).
   729 
   752 
   730                 try:
   753                 try:
   731                         trans_id = self.repo.open(client_release, pfmri)
   754                         trans_id = self.repo.open(client_release, pfmri)
   732                         response.headers["Content-type"] = "text/plain; charset=utf-8"
   755                         response.headers["Content-type"] = "text/plain; charset=utf-8"
       
   756                         response.headers["Transaction-ID"] = trans_id
       
   757                 except repo.RepositoryError, e:
       
   758                         # Assume a bad request was made.  A 404 can't be
       
   759                         # returned here as misc.versioned_urlopen will interpret
       
   760                         # that to mean that the server doesn't support this
       
   761                         # operation.
       
   762                         raise cherrypy.HTTPError(httplib.BAD_REQUEST, str(e))
       
   763 
       
   764         @cherrypy.tools.response_headers(headers=[("Pragma", "no-cache"),
       
   765             ("Cache-Control", "no-cache, no-transform, must-revalidate"),
       
   766             ("Expires", 0)])
       
   767         def append_0(self, *tokens):
       
   768                 """Starts an append transaction for the package name specified
       
   769                 in the request path.  Returns no output."""
       
   770 
       
   771                 request = cherrypy.request
       
   772                 response = cherrypy.response
       
   773 
       
   774                 client_release = request.headers.get("Client-Release", None)
       
   775                 try:
       
   776                         pfmri = tokens[0]
       
   777                 except IndexError:
       
   778                         pfmri = None
       
   779 
       
   780                 # XXX Authentication will be handled by virtue of possessing a
       
   781                 # signed certificate (or a more elaborate system).
       
   782 
       
   783                 try:
       
   784                         trans_id = self.repo.append(client_release, pfmri)
       
   785                         response.headers["Content-type"] = \
       
   786                             "text/plain; charset=utf-8"
   733                         response.headers["Transaction-ID"] = trans_id
   787                         response.headers["Transaction-ID"] = trans_id
   734                 except repo.RepositoryError, e:
   788                 except repo.RepositoryError, e:
   735                         # Assume a bad request was made.  A 404 can't be
   789                         # Assume a bad request was made.  A 404 can't be
   736                         # returned here as misc.versioned_urlopen will interpret
   790                         # returned here as misc.versioned_urlopen will interpret
   737                         # that to mean that the server doesn't support this
   791                         # that to mean that the server doesn't support this
   895                 ("Cache-Control", "no-cache, no-transform, must-revalidate"),
   949                 ("Cache-Control", "no-cache, no-transform, must-revalidate"),
   896                 ("Expires", 0)
   950                 ("Expires", 0)
   897             ]
   951             ]
   898         }
   952         }
   899 
   953 
       
   954         def __upload_file(self, *tokens):
       
   955                 """Adds a file to an in-flight transaction for the Transaction
       
   956                 ID specified in the request path.  The content is expected to be
       
   957                 in the request body.  Returns no output."""
       
   958 
       
   959                 try:
       
   960                         # cherrypy decoded it, but we actually need it encoded.
       
   961                         trans_id = urllib.quote(tokens[0], "")
       
   962                 except IndexError:
       
   963                         raise
       
   964                         trans_id = None
       
   965 
       
   966                 request = cherrypy.request
       
   967                 response = cherrypy.response
       
   968 
       
   969                 size = int(request.headers.get("Content-Length", 0))
       
   970                 if size < 0:
       
   971                         raise cherrypy.HTTPError(httplib.BAD_REQUEST,
       
   972                             _("file/1 must be sent a file."))
       
   973                 data = request.rfile
       
   974 
       
   975                 try:
       
   976                         self.repo.add_file(trans_id, data, size)
       
   977                 except repo.RepositoryError, e:
       
   978                         # Assume a bad request was made.  A 404 can't be
       
   979                         # returned here as misc.versioned_urlopen will interpret
       
   980                         # that to mean that the server doesn't support this
       
   981                         # operation.
       
   982                         raise cherrypy.HTTPError(httplib.BAD_REQUEST, str(e))
       
   983                 response.headers["Content-Length"] = "0"
       
   984                 return response.body
       
   985 
   900         @cherrypy.tools.response_headers(headers=[("Pragma", "no-cache"),
   986         @cherrypy.tools.response_headers(headers=[("Pragma", "no-cache"),
   901             ("Cache-Control", "no-cache, no-transform, must-revalidate"),
   987             ("Cache-Control", "no-cache, no-transform, must-revalidate"),
   902             ("Expires", 0)])
   988             ("Expires", 0)])
   903         def index_0(self, *tokens):
   989         def index_0(self, *tokens):
   904                 """Triggers a refresh of the search indices.
   990                 """Triggers a refresh of the search indices.
  1021                         rargs[prop] = self.repo.cfg.get_property(
  1107                         rargs[prop] = self.repo.cfg.get_property(
  1022                             "repository", prop)
  1108                             "repository", prop)
  1023 
  1109 
  1024                 repo = publisher.Repository(**rargs)
  1110                 repo = publisher.Repository(**rargs)
  1025                 alias = self.repo.cfg.get_property("publisher", "alias")
  1111                 alias = self.repo.cfg.get_property("publisher", "alias")
       
  1112                 icas = self.repo.cfg.get_property("publisher",
       
  1113                     "intermediate_certs")
  1026                 pfx = self.repo.cfg.get_property("publisher", "prefix")
  1114                 pfx = self.repo.cfg.get_property("publisher", "prefix")
       
  1115                 scas = self.repo.cfg.get_property("publisher",
       
  1116                     "signing_ca_certs")
  1027                 return publisher.Publisher(pfx, alias=alias,
  1117                 return publisher.Publisher(pfx, alias=alias,
  1028                     repositories=[repo])
  1118                     repositories=[repo], ca_certs=scas, inter_certs=icas)
  1029 
  1119 
  1030         @cherrypy.tools.response_headers(headers=[(
  1120         @cherrypy.tools.response_headers(headers=[(
  1031             "Content-Type", p5i.MIME_TYPE)])
  1121             "Content-Type", p5i.MIME_TYPE)])
  1032         def publisher_0(self, *tokens):
  1122         def publisher_0(self, *tokens):
  1033                 """Returns a pkg(5) information datastream based on the
  1123                 """Returns a pkg(5) information datastream based on the