diff --git a/README.md b/README.md index a243c17..53b29d7 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,15 @@ jolla is a pure API server framework,and it is based on the gevent. > still being constrating -##Install +version:1.1.0 +- basic work have done,it's already a api server for api collect. +- delete the statics function,if you wanna css or js,use cdn or server like nginx and apache httpd; - sudo pip install jolla +## INSTALL + +``` +sudo pip install jolla +``` ## QUICKSTART add a `app.py`,and write dowm: @@ -21,6 +27,14 @@ session = session() def index(request): return plugins.render('index.html') +def chinese(request): + try: + if request['data']['ww']=='海贼王': + return 'great anime' + except: + pass + return 'yeah!chinese' + def data(request): data = {'data': request['id']} @@ -29,6 +43,7 @@ def data(request): def add(request): session.add_value('qq', 'ww') + return 'yes' @@ -56,12 +71,9 @@ class app(server.WebApp): (r'/data', data), (r'/add', add), (r'/get', get), - (r'/blog', blog) + (r'/blog', blog), + (r'/chinese',chinese) ] - -if __name__ == '__main__': - server = server.jolla_server(app) - server.run_server() ``` and then,run: diff --git a/example/ajax_calculater.py b/example/ajax_calculater.py new file mode 100644 index 0000000..1f71115 --- /dev/null +++ b/example/ajax_calculater.py @@ -0,0 +1,19 @@ +from jolla import WebApp,jolla_server,render_json,render + +def index(request): + return render('index.html') + +def add(request): + return render_json({'answer':int(request['data']['a'])+int(request['data']['b'])}) + +class app(WebApp): + urls = [ + (r'/', index), + (r'/add', add) + ] + + templates='cal' + +if __name__ == '__main__': + server = jolla_server(app) + server.run_server() diff --git a/example/app.py b/example/app.py index 1f01df0..ca8fd23 100644 --- a/example/app.py +++ b/example/app.py @@ -15,6 +15,15 @@ def index(request): return plugins.render('index.html') +def chinese(request): + try: + if request['data']['ww'] == '海贼王': + return 'great anime' + except: + pass + return 'yeah!' + + def data(request): data = {'data': request['id']} return plugins.render_json(data) @@ -50,9 +59,10 @@ class app(server.WebApp): (r'/data', data), (r'/add', add), (r'/get', get), - (r'/blog', blog) + (r'/blog', blog), + (r'/chinese', chinese) ] if __name__ == '__main__': server = server.jolla_server(app) - server.run_server() + server.run_server(reload = True) diff --git a/example/cal/index.html b/example/cal/index.html new file mode 100644 index 0000000..7574949 --- /dev/null +++ b/example/cal/index.html @@ -0,0 +1,34 @@ + + + + +

two numbers

+
+ a: + +
b: + +
+

result:

+ +
+ + + + + + diff --git a/example/templates/index.html b/example/templates/index.html index 6905073..e3bff62 100644 --- a/example/templates/index.html +++ b/example/templates/index.html @@ -1,11 +1,11 @@ + - - index - + + -

hello world!

- +

hello world!我是汉字

+ diff --git a/jolla/HTTPerror.py b/jolla/HTTPerror.py index f652d95..8ec8ad8 100644 --- a/jolla/HTTPerror.py +++ b/jolla/HTTPerror.py @@ -15,25 +15,25 @@ class HTTP404Error(HTTPError): error_code = 404 def __str__(self): - return "404 NOT FOUND" + return "<404 NOT FOUND>" class HTTP502Error(HTTPError): error_code = 502 def __str__(self): - return "502 SERVER ERROR" + return "<502 SERVER ERROR>" class HTTP403Error(HTTPError): error_code = 403 def __str__(self): - return "403 FORBBIDEN" + return "<403 FORBBIDEN>" class HTTP500Error(HTTPError): error_code = 500 def __str__(self): - return "server error" + return "" diff --git a/jolla/HTTPerror.pyc b/jolla/HTTPerror.pyc new file mode 100644 index 0000000..f5c875c Binary files /dev/null and b/jolla/HTTPerror.pyc differ diff --git a/jolla/__init__.pyc b/jolla/__init__.pyc new file mode 100644 index 0000000..376b444 Binary files /dev/null and b/jolla/__init__.pyc differ diff --git a/jolla/plugins.py b/jolla/plugins.py index 5723e4f..b057826 100644 --- a/jolla/plugins.py +++ b/jolla/plugins.py @@ -4,24 +4,48 @@ import json import os +from HTTPerror import HTTP404Error +from server import static_setting def render(filename): - with open(os.path.abspath('templates/' + filename), "r") as f: - res = f.read() + if static_setting['templates'][-1] != '/': + static_setting['templates'] = static_setting['templates'] + '/' - return (res, ('Content-Type', 'text/html')) + try: + with open(os.path.abspath(static_setting['templates'] + filename), "r") as f: + res = f.read() + return (res, ('Content-Type', 'text/html')) -def render_json(data): + except IOError: + print "" + raise HTTP404Error + + +def render_json(data,indent=0): if isinstance(data, dict): - return (json.dumps(data), ('Content-Type', 'application/json')) + return (json.dumps(data,ensure_ascii=False,indent=indent), ('Content-Type', 'application/json')) else: + print "" raise AttributeError def render_media(filename): - with open(os.path.abspath('statics/' + filename), "r") as f: - res = f.read() - - return res + if static_setting['statics'][-1] != '/': + static_setting['statics'] = static_setting['statics'] + '/' + + try: + with open(os.path.abspath(static_setting['statics'] + filename), "r") as f: + res = f.read() + + if 'css' in filename[-4:]: + content = ('Content-Type', 'text/css') + elif 'js' in filename[-4:]: + content = ('Content-Type', 'application/javascript') + else: + raise HTTP404Error + return (res, content) + + except IOError: + raise HTTP404Error diff --git a/jolla/plugins.pyc b/jolla/plugins.pyc new file mode 100644 index 0000000..c1de109 Binary files /dev/null and b/jolla/plugins.pyc differ diff --git a/jolla/server.py b/jolla/server.py index cc7b3f6..e91db62 100644 --- a/jolla/server.py +++ b/jolla/server.py @@ -7,19 +7,40 @@ from gevent.pywsgi import WSGIServer import re +from urllib import unquote + +static_setting = { + 'templates': r'templates' +} + + from HTTPerror import HTTP404Error, HTTP403Error, HTTP502Error -from plugins import render_media class RouteError(Exception): - def __init__(self, info): - if(info == 'too many re'): - print "TOO MORE REGULAR SEARCH" - if(info == 'route error'): - print 'WRONG ROUTE DESIGN' - if(info == 'query already in request'): - print "IT HAS ALREADY IN REQUEST VALUE" + def __init__(self, info=None): + print "<" + info + ">" + + def __str__(self): + if(self.info == 'too many re'): + return "" + if(self.info == 'route error'): + return '' + if(self.info == 'query already in request'): + return "" + + +class RequestError(Exception): + + def __init__(self): + pass + + +class RequestValueError(RequestError): + + def __str__(self): + return "" class WebApp(): @@ -28,87 +49,101 @@ class WebApp(): _parsed_urls = [] - setting = { - 'statics': r'/statics', - 'templates': r'/templates' - } - - def __init__(self, environ): - - self._environ = environ + global static_setting - self._path = self._environ['PATH_INFO'] - if self._path[-1] != '/': - self._path = self._path + '/' + templates = False + def __init__(self, environ=None, get_urls=True): self.request = {} - try: - self.request['cookies'] = self._environ['HTTP_COOKIE'] - except KeyError: - self.request['cookies'] = None + if environ: + self._environ = environ + + self._path = self._environ['PATH_INFO'] + if self._path[-1] != '/': + self._path = self._path + '/' + + try: + self.request['cookies'] = self._environ['HTTP_COOKIE'] + except KeyError: + self.request['cookies'] = None + + self.request['http_protocol'] = self._environ['SERVER_PROTOCOL'] + + self.request['user_agent'] = self._environ['HTTP_USER_AGENT'] + + try: + self.request['http_connect'] = self._environ['HTTP_CONNECTION'] + except KeyError: + self.request['http_connect'] = None + + self.request['http_port'] = self._environ['HTTP_HOST'] + + self.request['method'] = self._environ['REQUEST_METHOD'] + + try: + self.request['content_length'] = self._environ[ + 'CONTENT_LENGTH'] + self.request['content_type'] = self._environ['CONTENT_TYPE'] + self.request['http_accept_encoding'] = self._environ[ + 'HTTP_ACCEPT_ENCODING'] + except KeyError: + self.request['content_length'] = None + self.request['content_type'] = None + self.request['http_accept_encoding'] = None + + self.request['data'] = {} + self.request['query_string'] = {} + # Beyond Comp + line = self._environ['QUERY_STRING'] + request_data = environ['wsgi.input'].read(environ.get('content_length', 0)) + if request_data: + request_data = unquote(request_data) + for data_pair in request_data.split('&'): + key, value = data_pair.split('=') - self.request['http_protocol'] = self._environ['SERVER_PROTOCOL'] + self.request['data'][key] = value + # up + query_string = self._environ['QUERY_STRING'] + if query_string: + query_string = unquote(query_string) + for data_pair in query_string.split('&'): + try: + key, value = data_pair.split('=') + self.request['data'][key] = value + self.request['query_string'][key] = value + except ValueError: + pass + # Below Comp + if not get_urls: + for url in self.urls: + try: + res = self.url_parse(url[0]) + except RouteError: + print "" + raise HTTP404Error - self.request['user_agent'] = self._environ['HTTP_USER_AGENT'] + if isinstance(res, tuple): + self._parsed_urls.append((res[0] + '$', url[1], res[1])) + else: + self._parsed_urls.append((res + '$', url[1])) - self.request['http_connect'] = self._environ['HTTP_CONNECTION'] + if self.templates: + static_setting['templates'] = self.templates - self.request['http_port'] = self._environ['HTTP_HOST'] + def __repr__(self): + return "Jolla.WebAppObject" - self.request['method'] = self._environ['REQUEST_METHOD'] + def __str__(self): + return "" - try: - self.request['content_length'] = self._environ['CONTENT_LENGTH'] - self.request['content_type'] = self._environ['CONTENT_TYPE'] - except KeyError: - self.request['content_length'] = None - self.request['content_type'] = None - - self.request['http_accept_encoding'] = self._environ[ - 'HTTP_ACCEPT_ENCODING'] - - self.request['data'] = {} - line = self._environ['QUERY_STRING'] - request_data = environ['wsgi.input'].read() - if request_data: - for data_pair in request_data.split('&'): - key, value = data_pair.split('=') - self.request['data'][key] = value - query_string = self._environ['QUERY_STRING'] - if query_string: - for data_pair in query_string.split('&'): - try: - key, value = data_pair.split('=') - self.request['data'][key] = value - except ValueError: - pass - - for url in self.urls: - res = self.url_parse(url[0]) - if isinstance(res, tuple): - self._parsed_urls.append((res[0] + '$', url[1], res[1])) - else: - self._parsed_urls.append((res + '$', url[1])) - - def parse(self): - for url_handler in self._parsed_urls: + def parse(self, urls): + for url_handler in urls: if url_handler[0] == r'/': if self._path != '/': continue else: html_code = url_handler[1](self.request) - ''' - if self.setting['statics'] in self._path: - path = self._path.replace( - self.setting['statics'], '') - - try: - res = render_media(path) - except IOError: - raise HTTP404Error("NOT FOUND THIS FILE") - return res - ''' url_reg = re.compile(url_handler[0]) if url_reg.match(self._path): @@ -117,16 +152,24 @@ def parse(self): re_query = re.findall(url_reg, self._path) if re_query[0]: - self.request[url_handler[2]] = re_query[0] - html_code = url_handler[1](self.request) - return html_code + if url_handler[2] in self.request: + raise RouteError("query already in request") + else: - html_code = url_handler[1](self.request) + self.request[url_handler[2]] = re_query[0] + html_code = url_handler[1](self.request) + return html_code + + try: + html_code = url_handler[1](self.request) + except TypeError: + html_code = url_handler[1]() return html_code raise HTTP404Error('REQUEST NOT FOUND IN ROUTE CONFIGURATION') def url_parse(self, path): + path = path.replace(' ', '') if path[-1] != '/': path = path + '/' @@ -138,15 +181,14 @@ def url_parse(self, path): reg = re.compile(r'<(\w+)>') url_query = re.findall(reg, path)[0] - if url_query in self.request: - raise RouteError("query already in request") - else: - self.request[url_query] = None the_url = path.replace('<' + url_query + '>', - '(?P<' + url_query + '>\\w*)') + '(?P<' + url_query + '>\\w+)') return (the_url, url_query) return path + def get_parsed_urls(self): + return self._parsed_urls + class jolla_server(WSGIServer): @@ -154,15 +196,24 @@ def __init__(self, app, port=8000, host="127.0.0.1", debug=False): self.port = port self.host = host self.app = app + + my_app = self.app(get_urls=False) + self.urls = my_app.get_parsed_urls() + WSGIServer.__init__(self, listener=( self.host, self.port), application=self.application) - def application(self, environ, start_response): + def __str__(self): + return "" - the_app = self.app(environ) + def __repr__(self): + return 'Jolla.jolla_serverObeject' + + def application(self, environ, start_response): try: - html_code = the_app.parse() + the_app = self.app(environ) + html_code = the_app.parse(self.urls) if not isinstance(html_code, tuple): html_code = (html_code, ('Content-Type', 'text/html')) status = '200 OK' @@ -171,15 +222,23 @@ def application(self, environ, start_response): html_code = ('404 NOT FOUND', ('Content-Type', 'text/html')) header = [ - html_code[1], ('Server', 'Jolla/1.0') ] + for i in range(1, len(html_code)): + header.append(html_code[i]) + start_response(status, header) return html_code[0] - def run_server(self): + def run_server(self, reload = False): print "the server is running on the {} in the port {}".format(self.host, self.port) - - self.serve_forever() + if reload: + from werkzeug.serving import run_simple + run_simple(self.host, self.port, self, use_debugger=True, use_reloader=True) + else: + self.serve_forever() + + def __call__(self, environ, start_response): + return self.application(environ, start_response) diff --git a/jolla/server.pyc b/jolla/server.pyc new file mode 100644 index 0000000..2490a11 Binary files /dev/null and b/jolla/server.pyc differ diff --git a/jolla/session.py b/jolla/session.py index 71769c8..e7d5abd 100644 --- a/jolla/session.py +++ b/jolla/session.py @@ -16,6 +16,21 @@ def __str__(self): class session(buffer): + def __str__(self): + return "Jolla.jolla_sessionObject" + + def __repr__(self): + return "" + + def empty(self): + if self._data: + return True + else: + return False + + def session_count(self): + return len(self._data) + def add_value(self, key, value): self._data[key] = value return True @@ -25,6 +40,7 @@ def check_value(self, key, value=None): if value: if self._data[key] == value: return True + else: return False else: diff --git a/jolla/session.pyc b/jolla/session.pyc new file mode 100644 index 0000000..34cc965 Binary files /dev/null and b/jolla/session.pyc differ diff --git a/setup.py b/setup.py index b2db781..0421e1d 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ setup( name='jolla', keywords=['back-end', 'framework', 'RESTful', 'gevent'], - version='1.0.5', + version='1.1.6', description='high performance RESTful framework', author='aljun', author_email='salamer_gaga@163.com', @@ -15,7 +15,8 @@ download_url='https://github.com/salamer/jolla', install_requires=[ - 'gevent' + 'gevent', + 'werkzeug' ], packages=['jolla'],