OSDN Git Service

ns_search: create 'newslash_searchd' module
authorhylom <hylom@users.sourceforge.jp>
Thu, 22 Feb 2018 12:16:54 +0000 (21:16 +0900)
committerhylom <hylom@users.sourceforge.jp>
Thu, 22 Feb 2018 12:16:54 +0000 (21:16 +0900)
src/ns_search/newslash_searchd/__init__.py [new file with mode: 0644]
src/ns_search/newslash_searchd/codes.py [new file with mode: 0644]
src/ns_search/newslash_searchd/router.py [new file with mode: 0644]
src/ns_search/newslash_searchd/searchd.py [new file with mode: 0644]
src/ns_search/ns_searchd.py [new file with mode: 0644]

diff --git a/src/ns_search/newslash_searchd/__init__.py b/src/ns_search/newslash_searchd/__init__.py
new file mode 100644 (file)
index 0000000..9692fcd
--- /dev/null
@@ -0,0 +1,8 @@
+# coding: utf-8
+'''newslash_searchd: Search daemon for newslash'''
+__author__ = 'Hiromichi Matsushima <hylom@users.osdn.net>'
+__version__ = "0.1.0"
+
+from searchd import Searchd
+
+__all__ = []
diff --git a/src/ns_search/newslash_searchd/codes.py b/src/ns_search/newslash_searchd/codes.py
new file mode 100644 (file)
index 0000000..438bd6e
--- /dev/null
@@ -0,0 +1,6 @@
+# -*- coding: utf-8
+'''router: HTTP Status codes'''
+
+status_code = {
+    
+}
diff --git a/src/ns_search/newslash_searchd/router.py b/src/ns_search/newslash_searchd/router.py
new file mode 100644 (file)
index 0000000..15b7537
--- /dev/null
@@ -0,0 +1,97 @@
+# -*- coding: utf-8
+'''router: Routing and preprocess system for Web applications'''
+
+import httplib
+import json
+
+class Response(object):
+    def __init__(self, start_response):
+        self.status = None
+        self.response_headers = []
+        self.finished = False
+        self.response_bodies = []
+        self.start_response = start_response
+
+    def add_response(self, response):
+        self.response_bodies.append(response)
+
+    def add_header(self, name, value):
+        self.response_headers.append((name, value))
+
+    def set_status_code(self, code):
+        self.status = "{} {}".format(code, httplib.responses[code])
+
+    def render_json(self, data):
+        self.add_header("Content-Type", "application/json")
+        raw_json = json.dumps(data, ensure_ascii=False)
+        self.add_response(raw_json.encode('utf-8'))
+
+    def render(self, code=None, **kwargs):
+        if code is not None:
+            self.set_status_code(code)
+        if 'json' in kwargs:
+            return self.render_json(kwargs["json"])
+
+    def finish(self, code=None, body=None):
+        if code is not None:
+            self.set_status_code(code)
+
+        if self.status is None:
+            self.set_status_code(200)
+
+        if body is not None:
+            self.add_response(body)
+
+        self.start_response(self.status, self.response_headers)
+        self.finished = True
+
+
+class Request(object):
+    def __init__(self, environ):
+        self.environ = environ
+        self.body = self.decode_request_body()
+
+    def decode_request_body(self):
+        content_type = self.environ['CONTENT_TYPE']
+        if content_type == 'application/json':
+            return self._decode_json()
+        return None
+
+    def _decode_json(self):
+        body_len = int(self.environ.get('CONTENT_LENGTH', 0))
+        if body_len > 0:
+            raw_req = self.environ['wsgi.input']
+            raw_json = raw_req.read(body_len)
+            return json.loads(raw_json)
+        return None
+    
+
+class Router(object):
+    def __init__(self):
+        pass
+
+    def __call__(self, environ, start_response):
+        req = Request(environ)
+        resp = Response(start_response)
+
+        method = environ['REQUEST_METHOD']
+        try:
+            if method == 'GET':
+                self.get(req, resp)
+            elif method == 'POST':
+                self.post(req, resp)
+            else:
+                self.fallback(req, resp)
+        except AttributeError:
+            self.fallback(req, resp)
+
+        if not resp.finished:
+            resp.finish()
+
+        return resp.response_bodies
+
+    def fallback(self, req, resp):
+        resp.finish(500, "Internal Server Error")
+
+        
+
diff --git a/src/ns_search/newslash_searchd/searchd.py b/src/ns_search/newslash_searchd/searchd.py
new file mode 100644 (file)
index 0000000..440278f
--- /dev/null
@@ -0,0 +1,39 @@
+# -*- coding: utf-8
+''' searchd: Search daemon for Newslash'''
+
+from router import Router
+import lucene_wrapper
+
+class Searchd(Router):
+    def __init__(self):
+        super(Searchd, self).__init__()
+
+    def get(self, req, resp):
+        resp.render(200, json={"error": 0})
+        
+    def post(self, req, resp):
+        # check request body is valid
+        if req.body is None:
+            resp.render(400)
+            return
+
+        # start query
+        query = req.body.get('query', '')
+        limit = req.body.get('limit', 10)
+
+        searcher = lucene_wrapper.Searcher(index_directory="./lucene_index")
+        query = lucene_wrapper.Query("content_text", query)
+        result = searcher.search(query, limit)
+
+        resp_body = {
+            "total_hits": result.total_hits,
+            "hits": []
+        }
+
+        for item in result:
+            resp_body["hits"].append({ "number": item.number,
+                                       "id": item.id,
+                                       "title": item.title,
+                                       "content_text": item.content_text})
+
+        resp.render(200, json=resp_body)
diff --git a/src/ns_search/ns_searchd.py b/src/ns_search/ns_searchd.py
new file mode 100644 (file)
index 0000000..e04338a
--- /dev/null
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+# -*- coding: utf-8
+
+from wsgiref.simple_server import make_server
+
+from newslash_searchd import Searchd
+import lucene_wrapper
+
+if __name__ == '__main__':
+    # start Java VM
+    lucene_wrapper.init_vm()
+
+    app = Searchd()
+    server = make_server('', 6000, app)
+
+    print("starting server at localhost:6000...")
+    server.serve_forever()
+
+