diff --git a/dotests.py b/dotests.py index e6bb305..c0215ff 100644 --- a/dotests.py +++ b/dotests.py @@ -113,12 +113,13 @@ async def run_benchmarks(): opts = ('-H','Cookie: mrsession=43709dd361cc443e976b05714581a7fb; foo=fdsfdasdfasdfdsfasdfsdfsdfasdfas; short=fazc;') print(" Pipelined") + print (" Hello (cached) ", await run_wrk(loop, 'http://localhost:8080/cached',lua='tests/lua/q-cached.lua'), "Requests/second" ) print (" Hello ", await run_wrk(loop, 'http://localhost:8080/',lua='tests/lua/pipeline.lua'), "Requests/second" ) print (" More hdrs ", await run_wrk(loop, 'http://localhost:8080/',options=more_headers,lua='tests/lua/pipeline.lua'), "Requests/second" ) print (" Sessions ", await run_wrk(loop, 'http://localhost:8080/s',lua='tests/lua/q-session.lua'), "Requests/second" ) print (" File Upload ", await run_wrk(loop, 'http://localhost:8080/upload',lua='tests/lua/q-upload.lua'), "Requests/second" ) - print (" mrpacker ", await run_wrk(loop, 'http://localhost:8080/mrpacker',lua='tests/lua/q-mrp.lua'), "Requests/second" ) - print (" Form ", await run_wrk(loop, 'http://localhost:8080/form',lua='tests/lua/q-form.lua'), "Requests/second" ) + #print (" mrpacker ", await run_wrk(loop, 'http://localhost:8080/mrpacker',lua='tests/lua/q-mrp.lua'), "Requests/second" ) + #print (" Form ", await run_wrk(loop, 'http://localhost:8080/form',lua='tests/lua/q-form.lua'), "Requests/second" ) if 1: print("") diff --git a/setup.py b/setup.py index 52a76bc..1b2771a 100644 --- a/setup.py +++ b/setup.py @@ -33,7 +33,7 @@ setup( name="mrhttp", - version="0.10", + version="0.11", license='MIT', description='A python web framework written in C', long_description=open('README.md').read(), diff --git a/src/mrhttp/__init__.py b/src/mrhttp/__init__.py index 9f91411..09c5286 100644 --- a/src/mrhttp/__init__.py +++ b/src/mrhttp/__init__.py @@ -21,5 +21,5 @@ from .app import * from .internals import randint, escape, to64, from64, timesince -__version__=0.10 +__version__=0.11 diff --git a/src/mrhttp/app.py b/src/mrhttp/app.py index 4b38fac..9ad06de 100644 --- a/src/mrhttp/app.py +++ b/src/mrhttp/app.py @@ -145,7 +145,6 @@ def static_cached_timer(self): for item in self.static_cached_files: fn = item[1] if os.path.getmtime(fn) > self.static_cached_timestamp: - print("DELME timer updating cache of ",fn) with open(fn, 'rb') as f: b = f.read() self.router.update_cached_route( [item[0], b] ) diff --git a/src/mrhttp/internals/app.c b/src/mrhttp/internals/app.c index c5c0501..7d0c576 100644 --- a/src/mrhttp/internals/app.c +++ b/src/mrhttp/internals/app.c @@ -213,7 +213,7 @@ void MrhttpApp_setup_error_pages(MrhttpApp* self) { char *body = PyUnicode_AsUTF8AndSize( u, &l ); char *resp = malloc( l + 1024 ); - sprintf(resp, "HTTP/1.1 404 Not Found\r\nServer: MrHTTP/0.8\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: %zu\r\n\r\n", l); + sprintf(resp, "HTTP/1.1 404 Not Found\r\nServer: MrHTTP/0.11\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: %zu\r\n\r\n", l); char *p = resp + strlen(resp); memcpy(p, body, l); @@ -225,7 +225,7 @@ void MrhttpApp_setup_error_pages(MrhttpApp* self) { body = PyUnicode_AsUTF8AndSize( u, &l ); resp = malloc( l + 1024 ); - sprintf(resp, "HTTP/1.1 400 Bad Request\r\nServer: MrHTTP/0.8\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: %zu\r\n\r\n", l); + sprintf(resp, "HTTP/1.1 400 Bad Request\r\nServer: MrHTTP/0.11\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: %zu\r\n\r\n", l); p = resp + strlen(resp); memcpy(p, body, l); diff --git a/src/mrhttp/internals/protocol.c b/src/mrhttp/internals/protocol.c index 6be2e8d..feb856f 100644 --- a/src/mrhttp/internals/protocol.c +++ b/src/mrhttp/internals/protocol.c @@ -537,9 +537,13 @@ Protocol* Protocol_handle_request(Protocol* self, Request* request, Route* r) { if ( self->request == request ) self->request = (Request*)MrhttpApp_get_request( self->app ); } + //if ( r->dyncache ) { // Lookup path in dict + //} // If we have cached bytes if ( r->cached ) { + response_setMimeType(r->mtype); if(!protocol_write_response(self, request, r->cached)) goto error; + return self; } if(!(result = protocol_callPageHandler(self, r->func, request)) ) { diff --git a/src/mrhttp/internals/response.c b/src/mrhttp/internals/response.c index 5413ecb..ece656a 100644 --- a/src/mrhttp/internals/response.c +++ b/src/mrhttp/internals/response.c @@ -36,7 +36,7 @@ void response_setupResponseBuffer(void) { // Also all 115 and 143s ( updateHeaders ) s = "HTTP/1.1 200 OK\r\n"; memcpy(p, s, strlen(s)); p += strlen(s); s = "Content-Length: 1 \r\n"; memcpy(p, s, strlen(s)); p += strlen(s); - s = "Server: MrHTTP/0.10\r\n"; memcpy(p, s, strlen(s)); p += strlen(s); + s = "Server: MrHTTP/0.11\r\n"; memcpy(p, s, strlen(s)); p += strlen(s); s = "Date: Thu, 05 Apr 2018 22:54:19 GMT\r\n"; memcpy(p, s, strlen(s)); p += strlen(s); s = "Content-Type: text/html; charset=utf-8\r\n\r\n"; memcpy(p, s, strlen(s)); p += strlen(s); DBG_RESP printf("Init resp buffer:\n%.*s", (int)(p-rbuf), rbuf); @@ -74,7 +74,7 @@ PyObject *response_updateDate(PyObject *date) { Py_ssize_t l; char *d = PyUnicode_AsUTF8AndSize( date, &l ); char *p = rbuf; - p += strlen("HTTP/1.1 200 OK\r\n") + strlen("Server: MrHTTP/0.10\r\n") + strlen("Content-Length: 1 \r\n"); + p += strlen("HTTP/1.1 200 OK\r\n") + strlen("Server: MrHTTP/0.11\r\n") + strlen("Content-Length: 1 \r\n"); p += 6; memcpy(p, d, l); Py_RETURN_NONE; @@ -234,10 +234,10 @@ PyObject *response_getErrorResponse(int code, char *reason, char *msg) { sprintf( body, "%d %s

%s

%s

", code, reason, reason, msg ); int blen = strlen(body); - sprintf(p, "HTTP/1.1 %d %s\r\nServer: MrHTTP/0.10\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: %d\r\n", code, reason, blen); + sprintf(p, "HTTP/1.1 %d %s\r\nServer: MrHTTP/0.11\r\nContent-Type: text/html; charset=utf-8\r\nContent-Length: %d\r\n", code, reason, blen); p += strlen(p); memcpy(p, - rbuf + strlen("HTTP/1.1 200 OK\r\n") + strlen("Server: MrHTTP/0.10\r\n") + strlen("Content-Length: 17 \r\n"), + rbuf + strlen("HTTP/1.1 200 OK\r\n") + strlen("Server: MrHTTP/0.11\r\n") + strlen("Content-Length: 17 \r\n"), strlen("Date: Thu, 05 Apr 2018 22:54:19 GMT\r\n")); p += strlen("Date: Thu, 05 Apr 2018 22:54:19 GMT\r\n"); diff --git a/src/mrhttp/internals/router.c b/src/mrhttp/internals/router.c index 05dc136..eb44486 100644 --- a/src/mrhttp/internals/router.c +++ b/src/mrhttp/internals/router.c @@ -64,7 +64,9 @@ PyObject* Router_update_cached_route(Router* self, PyObject* item) { //DBG printf("request path len %d - %.*s\n", (int)request->path_len, (int)request->path_len, request->path); //DBG printf("route path %.*s \n", (int)r->len, r->path); if ( plen == r->len && !memcmp(r->path, p, plen) ) { + if ( r->cached ) { Py_DECREF(b); } r->cached = b; + Py_INCREF(b); Py_RETURN_NONE; } } @@ -103,9 +105,16 @@ PyObject *Router_setupRoutes (Router* self) { o = PyDict_GetItemString( r, "type" ); if (o) rte->mtype = PyLong_AsLong(o); rte->user_key = PyDict_GetItemString( r, "user_key" ); - rte->cached = PyDict_GetItemString( r, "cached" ); + PyObject *b = PyDict_GetItemString( r, "cached" ); + rte->cached = b; if (b) Py_INCREF(b); if ( Py_True == PyDict_GetItemString( r, "cache" ) ) { - rte->cached = PyObject_CallFunctionObjArgs(handler, r, NULL); + b = PyObject_CallFunctionObjArgs(handler, r, NULL); + rte->cached = b; Py_INCREF(b); + if ( !( PyBytes_Check(b) || PyUnicode_Check(b) ) ) { + printf(" ERROR - cached route must return a unicode or bytes object\n"); + printf(" path: "); PyObject_Print(PyDict_GetItemString(r,"path"),stdout,0); printf("\n"); + Py_DECREF(rte->cached); rte->cached = 0; + } } DBG printf(" path %.*s func ptr %p\n", (int)rte->len, rte->path, rte->func); diff --git a/src/mrhttp/internals/router.h b/src/mrhttp/internals/router.h index 25887f2..f857f8d 100644 --- a/src/mrhttp/internals/router.h +++ b/src/mrhttp/internals/router.h @@ -21,6 +21,7 @@ typedef struct { int max_byte_size; PyObject *cached; + PyObject *dyncache; PyObject *user_key; //char *user_key; //long user_key_len; diff --git a/tests/lua/pipeline.lua b/tests/lua/pipeline.lua index bc37741..2a2530b 100755 --- a/tests/lua/pipeline.lua +++ b/tests/lua/pipeline.lua @@ -2,38 +2,37 @@ init = function(args) local r = {} - r[1] = wrk.format(nil, "/") - r[2] = wrk.format(nil, "/") - r[3] = wrk.format(nil, "/") - r[4] = wrk.format(nil, "/") - r[5] = wrk.format(nil, "/") - r[6] = wrk.format(nil, "/") - r[7] = wrk.format(nil, "/") - r[8] = wrk.format(nil, "/") - r[9] = wrk.format(nil, "/") - r[10] = wrk.format(nil, "/") - r[11] = wrk.format(nil, "/") - r[12] = wrk.format(nil, "/") - r[13] = wrk.format(nil, "/") - r[14] = wrk.format(nil, "/") - r[15] = wrk.format(nil, "/") - r[16] = wrk.format(nil, "/") - r[17] = wrk.format(nil, "/") - r[18] = wrk.format(nil, "/") - r[19] = wrk.format(nil, "/") - r[20] = wrk.format(nil, "/") - r[21] = wrk.format(nil, "/") - r[22] = wrk.format(nil, "/") - r[23] = wrk.format(nil, "/") - r[24] = wrk.format(nil, "/") - r[25] = wrk.format(nil, "/") - r[26] = wrk.format(nil, "/") - r[27] = wrk.format(nil, "/") - r[28] = wrk.format(nil, "/") - r[29] = wrk.format(nil, "/") - r[30] = wrk.format(nil, "/") - r[31] = wrk.format(nil, "/") - r[32] = wrk.format(nil, "/") + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) + table.insert( r, wrk.format(nil, "/") ) req = table.concat(r) end diff --git a/tests/lua/q-cached.lua b/tests/lua/q-cached.lua new file mode 100755 index 0000000..95e3736 --- /dev/null +++ b/tests/lua/q-cached.lua @@ -0,0 +1,43 @@ +-- example script demonstrating HTTP pipelining + +init = function(args) + local r = {} + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + table.insert( r, wrk.format(nil, "/cached") ) + req = table.concat(r) +end + +request = function() + return req +end diff --git a/tests/s_bench.py b/tests/s_bench.py index 63d1fbf..0a6b6c5 100755 --- a/tests/s_bench.py +++ b/tests/s_bench.py @@ -38,6 +38,9 @@ @app.route('/') def index(r): return 'Hello World!' +@app.route('/cached', options=['cache']) +def cached_index(r): + return 'Hello World!' @app.route('/print/{}') def pr(r,foo): diff --git a/tst.py b/tst.py index 6c2cb56..5cb5746 100755 --- a/tst.py +++ b/tst.py @@ -12,26 +12,15 @@ #app.c = asyncmrq.Client() #await app.c.connect(servers=[("127.0.0.1",7100)]) -#@app.route('/',options=['cache']) -@app.route('/') +@app.route('/',_type='text',options=['cache']) +#@app.route('/',_type='text') def index(r): return "hello world" -@app.route('/123456789123456789') -async def long(r): - return "long" - @app.route('/json') def json(r): return mrjson.dumps({'message': 'Hello, world!'}) -@app.route('/mrp',_type="mrp") -def mrp(r): - return mrpacker.pack("hello") - -@app.route('/{}/tst') -def firstarg(r,a): - return a try: