def make_example1_httpd(service=None, service_config=None): """Make a HTTPd running in a separate thread. Return the thread and the HTTPd. :param service: if provided NB: the service is assumed to be located on localhost:1234 """ if service is None: if service_config is None: service_config = get_service_configuration() service_config.set('server', 'port', '1234') service_config.set('server', 'base-path', '/foo') service = make_example1_service(service_config) # cache_control="max-age=60") app = HttpFrontend(service, service_config) _httpd = make_server(service_config.get('server', 'host-name', 1), service_config.getint('server', 'port'), app) thread = Thread(target=_httpd.serve_forever) thread.start() return thread, _httpd
def main(): """Runs an HTTP server serving items and groups. If 'test' is passed as argument, first run :func:`do_tests` from :mod:`.example1` on the service. """ test = len(argv) > 1 and argv[1] == "test" service_config = get_service_configuration() service_config.set('server', 'port', '1234') service_config.set('server', 'base-path', '/foo') # TODO Store management : special tests ? serv = make_example2_service(service_config) root_uri = serv.root_uri if test: do_tests(serv.get(root_uri)) print "Local tests passed" app = HttpFrontend(serv, service_config) _httpd = make_server(service_config.get('server', 'host-name', 1), service_config.getint('server', 'port'), app) print "Now listening on", root_uri _httpd.serve_forever()
def main(): """I launch KTBS as a standalone HTTP server. """ cmdline_options = parse_options() # Get default configuration possibly overriden by a user configuration file # or command line configuration OPTIONS ktbs_config = parse_configuration_options(cmdline_options) # TODO : remove this option ? if ktbs_config.getboolean('server', 'resource-cache'): LOG.warning("option --resource-cache is deprecated; it has no effect") apply_global_config(ktbs_config) LOG.info("KTBS pid: %d" % getpid()) ktbs_service = KtbsService(ktbs_config) #.service atexit.register(lambda: ktbs_service.store.close()) application = HttpFrontend(ktbs_service, ktbs_config) if ktbs_config.getboolean('server', 'flash-allow'): application = FlashAllower(application) httpd = make_server(ktbs_config.get('server', 'host-name', 1), ktbs_config.getint('server', 'port'), application, make_server_class(ktbs_config)) LOG.info("KTBS server at %s" % ktbs_service.root_uri) httpd.serve_forever()
def setUp(self): try: self.service = make_example2_service(URL) root = self.service.get(URIRef(URL)) assert isinstance(root, Group2Implementation) root.create_new_simple_item("foo") self.app = HttpFrontend(self.service, cache_control="max-age=60") except: raise
def setUp(self): try: service_config = get_service_configuration() self.service = make_example2_service(service_config) #root = self.service.get(URIRef(URL)) root = self.service.get(self.service.root_uri, [EXAMPLE.Group2]) assert isinstance(root, Group2Implementation) root.create_new_simple_item("foo") # max-age is now deprecated, cache_control="max-age=60") self.app = HttpFrontend(self.service, service_config) except: raise
def setUp(self): super(HttpKtbsTestCaseMixin, self).setUp() ktbs_config = get_ktbs_configuration() app = HttpFrontend(self.service, ktbs_config) #app = HttpFrontend(self.service, cache_control="max-age=60") try: httpd = make_server("localhost", 12345, app, handler_class=StdoutHandler) thread = Thread(target=httpd.serve_forever) thread.start() self.httpd = httpd self.my_ktbs = HttpClientCore.factory("http://localhost:12345/", [KTBS.KtbsRoot]) assert isinstance(self.my_ktbs, KtbsRootMixin) except: self.tearDown() raise
def main(): """I launch KTBS as a standalone HTTP server. """ cmdline_options = parse_options() # Get default configuration possibly overriden by a user configuration file # or command line configuration OPTIONS ktbs_config = parse_configuration_options(cmdline_options) apply_global_config(ktbs_config) LOG.info("KTBS pid: %d" % getpid()) ktbs_service = KtbsService(ktbs_config) #.service atexit.register(lambda: ktbs_service.store.close()) application = HttpFrontend(ktbs_service, ktbs_config) kwargs = { 'host': ktbs_config.get('server', 'host-name', 1), 'port': ktbs_config.getint('server', 'port'), 'threads': ktbs_config.getint('server', 'threads'), } if ktbs_config.getboolean('server', 'force-ipv4'): kwargs['ipv6'] = False if ktbs_config.getboolean('server', 'flash-allow'): application = FlashAllower(application) if ktbs_config.has_option('server', 'base-path'): base_path = ktbs_config.get('server', 'base-path') application = SimpleRouter([(base_path, application)]) LOG.info("KTBS server at %s" % ktbs_service.root_uri) serve(application, **kwargs)
class TestHttpFront(object): service = None server = None def setUp(self): try: self.service = make_example2_service(URL) root = self.service.get(URIRef(URL)) assert isinstance(root, Group2Implementation) root.create_new_simple_item("foo") self.app = HttpFrontend(self.service, cache_control="max-age=60") except: raise def tearDown(self): if self.app is not None: del self.app if self.service is not None: unregister_service(self.service) del self.service def request(self, url, method="GET", body=None, headers=None): scheme, http_host, path_info, query_string, frag_id = urisplit(url) if frag_id is not None: raise ValueError("request should not include a fragment-id") if ":" in http_host: netloc, port = http_host.split(":") else: netloc = http_host port = "80" # should be different if scheme == 'https' environ = { "HTTP_ACCEPT": "test/turtle,*/*;q=.1", "HTTP_HOST": http_host, "HTTP_USER_AGENT": "unit-test", "PATH_INFO": path_info, "REMOTE_ADDR": "127.0.0.1", "REMOTE_HOST": "localhost.localdomain", "REQUEST_METHOD": method.upper(), "SCRIPT_NAME": "", "SERVER_NAME": netloc, "SERVER_PORT": port, "SERVER_PROTOCOL": "HTTP/1.1", "SERVER_SOFTWARE": "direct-access", "wsgi.errors": stderr, "wsgi.file_wrapper": body and [body] or [], "wsgi.input": StringIO(body or ""), "wsgi.multiprocess": "False", "wsgi.multithread": "False", "wsgi.run_once": "False", "wsgi.url_scheme": scheme, "wsgi.version": "(1, 0)" } if query_string is not None: environ["QUERY_STRING"] = query_string if body is not None: environ["CONTENT_LENGTH"] = str(len(body)) environ["CONTENT_TYPE"] = "text/plain;charset=utf-8" if headers is not None: for key, val in headers.items(): key = key.upper() key = key.replace("-", "_") if key not in ("CONTENT_LENGTH", "CONTENT_TYPE"): key = "HTTP_" + key environ[key] = val req = Request(environ) res = self.app.get_response(req) return res, res.body def test_bad_method(self): resp, content = self.request(URL, "XXX") eq_(resp.status_int, 405) def test_get_not_found(self): resp, content = self.request(URL+"not_there") eq_(resp.status_int, 404) def test_get(self): resp, content = self.request(URL) eq_(resp.status_int, 200) def test_get_valid_params(self): resp, content = self.request(URL+"?valid=a") eq_(resp.status_int, 200) def test_get_invalid_params(self): resp, content = self.request(URL+"?invalid=a") eq_(resp.status_int, 404) def test_get_not_allowed(self): resp, content = self.request(URL+"?notallowed=a") eq_(resp.status_int, 405) def test_get_redirect(self): resp, content = self.request(URL+"?redirect=foo") eq_(resp.status_int, 303) eq_(resp.location, URL+"foo") def test_get_proxy(self): resp, content = self.request(URL+"@proxy") eq_(resp.status_int, 303) eq_(resp.location, URL) def test_put_not_found(self): resp_put, content_put = self.request(URL+"not_there", "PUT", "") eq_(resp_put.status_int, 404) def test_put_without_etag(self): resp_get, content_get = self.request(URL) assert resp_get.content_type is not None reqhead = { "content-type": resp_get.content_type } resp_put, content_put = self.request(URL, "PUT", content_get, reqhead) eq_(resp_put.status_int, 403) def test_put_bad_content(self): resp_get, content_get = self.request(URL) assert resp_get.etag is not None assert resp_get.content_type is not None reqhead = { "if-match": resp_get.etag, "content-type": resp_get.content_type, # NB: content-type and etag must be kept consistent } new_content = ">" # illegal in most syntaxes (Turtle, XML, JSON, HTML) resp_put, content_put = self.request(URL, "PUT", new_content, reqhead) eq_(resp_put.status_int, 400) def test_put_bad_mediatype(self): resp_get, content_get = self.request(URL) assert resp_get.etag is not None reqhead = { "if-match": resp_get.etag, "content-type": "application/x-not-supported" } new_content = "" resp_put, content_put = self.request(URL, "PUT", new_content, reqhead) #eq_(resp_put.status_int, 415) # no parser found # NB: in fact, the bad mediatype does not match the etag, so we get eq_(resp_put.status_int, 412) # pre-condition failed def test_put_idem(self, url=URL): resp_get, content_get = self.request(url) assert resp_get.etag is not None assert resp_get.content_type is not None reqhead = { "if-match": resp_get.etag, "content-type": resp_get.content_type, } resp_put, content_put = self.request(url, "PUT", content_get, reqhead) eq_(resp_put.status_int, 200) assert "etag" in resp_put.headers def test_put_legal_rdf(self): reqhead = { "accept": "text/nt" } resp_get, content_get = self.request(URL, headers=reqhead) graph = Graph() graph.parse(data=content_get, publicID=URL, format="nt") graph.set((URIRef(URL), RDFS.label, Literal("label has been changed"))) new_content = graph.serialize(format="nt") assert resp_get.etag is not None reqhead = { "if-match": resp_get.etag, "content-type": "text/nt", } resp_put, content_put = self.request(URL, "PUT", new_content, reqhead) eq_(resp_put.status_int, 200) assert "etag" in resp_put.headers def test_put_illegal_rdf(self): # try to put a graph without any rdf:type for the resource reqhead = { "accept": "text/nt" } resp_get, content_get = self.request(URL, headers=reqhead) graph = Graph() graph.parse(data=content_get, publicID=URL, format="nt") graph.remove((URIRef(URL), RDF.type, None)) new_content = graph.serialize(format="nt") assert resp_get.etag is not None reqhead = { "if-match": resp_get.etag, "content-type": "text/nt", } resp_put, content_put = self.request(URL, "PUT", new_content, reqhead) eq_(resp_put.status_int, 403) def test_put_valid_params(self): self.test_put_idem(URL+"?valid=a") def test_put_invalid_params(self): reqhead = { "content-type": "text/turtle" } resp_put, content_put = self.request(URL+"invalid=a", "PUT", POSTABLE_TURTLE, reqhead) eq_(resp_put.status_int, 404) def test_post_not_found(self): resp_put, content_put = self.request(URL+"not_there", "POST", "") eq_(resp_put.status_int, 404) def test_post_bad_content(self): new_content = "illegal xml" reqhead = { "content-type": "application/rdf+xml" } resp, content = self.request(URL, "POST", new_content, reqhead) eq_(resp.status_int, 400) def test_post_bad_mediatype(self): new_content = "" reqhead = { "content-type": "application/x-not-supported" } resp, content = self.request(URL, "POST", new_content, reqhead) eq_(resp.status_int, 415) def test_post_legal_rdf(self, url=URL): #graph = Graph() #graph.parse(data=POSTABLE_TURTLE, publicID=url, format="n3") #new_content = graph.serialize(format="nt") #reqhead = { "content-type": "text/nt" } reqhead = { "content-type": "text/turtle" } resp, content = self.request(url, "POST", POSTABLE_TURTLE, reqhead) eq_(resp.status_int, 201) assert resp.location resp, content = self.request(resp.location) eq_(resp.status_int, 200) def test_post_illegal_rdf(self): # try to post a graph without an rdf:type for the created element graph = Graph() graph.parse(data=POSTABLE_TURTLE, publicID=URL, format="n3") created = next(graph.triples((URIRef(URL), None, None)))[2] graph.remove((created, RDF.type, None)) new_content = graph.serialize(format="nt") reqhead = { "content-type": "text/nt" } resp, content = self.request(URL, "POST", new_content, reqhead) eq_(resp.status_int, 403) def test_post_valid_params(self): self.test_post_legal_rdf(URL+"?valid=a") def test_post_invalid_params(self): reqhead = { "content-type": "text/turtle" } resp, content = self.request(URL+"?invalid=a", "POST", POSTABLE_TURTLE, reqhead) eq_(resp.status_int, 404) def test_delete_not_found(self): resp_put, content_put = self.request(URL+"not_there", "DELETE") eq_(resp_put.status_int, 404) def test_delete(self): resp, content = self.request(URL + "foo", "DELETE") eq_(resp.status_int, 204) def test_delete_conflict(self): # we create a non-empty group, then try to delete it reqhead = { "content-type": "text/turtle" } resp, _ = self.request(URL, "POST", POSTABLE_TURTLE, reqhead) url2 = resp.location assert url2 is not None _ = self.request(url2, "POST", POSTABLE_TURTLE, reqhead) resp, content = self.request(url2, "DELETE") eq_(resp.status_int, 409) def test_delete_valid_params(self): resp, content = self.request(URL + "foo?valid=a", "DELETE") eq_(resp.status_int, 204) def test_delete_invalid_params(self): resp, content = self.request(URL + "foo?invalid=a", "DELETE") eq_(resp.status_int, 404) def test_cache_control(self): resp, _ = self.request(URL) assert resp.cache_control is not None resp, _ = self.request(URL + "foo") assert resp.cache_control is not None def test_serialize_error(self): # we use the fact that rdfrest_demo can "simulate" a serialize error resp, content = self.request(URL, headers={"accept": "text/errer"}) eq_(resp.status_int, 550) def test_ctype(self): for ctype in [ "text/turtle", "application/rdf+xml", "text/nt", ]: yield self._do_test_ctype, ctype def test_max_bytes_get_ok(self): self.app.max_bytes = 1000 self.test_get() def test_max_bytes_get_ko(self): self.app.max_bytes = 1000 foo = self.service.get(URIRef(URL + "foo")) assert isinstance(foo, Item2Implementation) with foo.edit(_trust=True) as editable: editable.add((foo.uri, RDFS.label, Literal(1000*"x"))) resp, content = self.request(URL + "foo") eq_(resp.status_int, 403) def test_max_bytes_put_ok(self): self.app.max_bytes = 1000 self.test_put_idem() def test_max_bytes_put_ko(self): self.app.max_bytes = 1000 resp_get, content_get = self.request(URL) assert resp_get.etag is not None assert resp_get.content_type is not None reqhead = { "if-match": resp_get.etag, "content-type": resp_get.content_type, } content_get = content_get + "#"*1000 resp_put, content_put = self.request(URL, "PUT", content_get, reqhead) eq_(resp_put.status_int, 413) def test_max_bytes_post_ok(self): self.app.max_bytes = 1000 self.test_post_legal_rdf() def test_max_bytes_post_ko(self): self.app.max_bytes = 1000 reqhead = { "content-type": "text/turtle" } resp, content = self.request(URL, "POST", POSTABLE_TURTLE + "#"*1000, reqhead) eq_(resp.status_int, 413) def test_max_triples_get_ok(self): self.app.max_triples = 10 self.test_get() def test_max_triples_get_ko(self): self.app.max_triples = 10 foo = self.service.get(URIRef(URL + "foo")) with foo.edit(_trust=True) as editable: for i in range(10): editable.add((foo.uri, RDFS.label, Literal("label%i" % i))) resp, content = self.request(URL + "foo") eq_(resp.status_int, 403) def test_max_triples_put_ok(self): self.app.max_triples = 10 self.test_put_idem() def test_max_triples_put_ko(self): self.app.max_triples = 10 resp_get, content_get = self.request(URL) assert resp_get.etag is not None assert resp_get.content_type is not None reqhead = { "if-match": resp_get.etag, "content-type": resp_get.content_type, } content_get += ("<> <http://example.org/other#label>" + ",".join('"%s"' % i for i in range(10)) + ".") resp_put, content_put = self.request(URL, "PUT", content_get, reqhead) eq_(resp_put.status_int, 413) def test_max_triples_post_ok(self): self.app.max_triples = 10 self.test_post_legal_rdf() def test_max_triples_post_ko(self): self.app.max_triples = 10 reqhead = { "content-type": "text/turtle" } patch = ("<http://example.org/other#label> " + ", ".join('"%s"' % i for i in range(10)) + "; ].") content = POSTABLE_TURTLE.replace("].", patch) resp, content = self.request(URL, "POST", content, reqhead) eq_(resp.status_int, 413) def _do_test_ctype(self, ctype): reqhead = { "accept": ctype } resp_get, content_get = self.request(URL, headers=reqhead) eq_(resp_get.status_int, 200) eq_(resp_get.content_type, ctype) assert resp_get.etag is not None reqhead = { "if-match": resp_get.etag, "content-type": ctype, } resp_put, content_put = self.request(URL, "PUT", content_get, reqhead) eq_(resp_put.status_int, 200)
def app(service_config, service): app = HttpFrontend(service, service_config) yield app del app