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 |