void t06_empty(){ INIT_LOCAL(); onion *server=onion_new(0); onion_add_listen_point(server,NULL,NULL,onion_buffer_listen_point_new()); onion_request *request; char buffer[4096]; memset(buffer,0,sizeof(buffer)); request=onion_request_new(server->listen_points[0]); onion_response *response=onion_response_new(request); // onion_response_write_headers(response); onion_response_flush(response); onion_response_free(response); buffer[sizeof(buffer)-1]=0; strncpy(buffer,onion_buffer_listen_point_get_buffer_data(request),sizeof(buffer)-1); onion_request_free(request); onion_free(server); FAIL_IF_NOT_STRSTR(buffer, "Server:"); FAIL_IF_NOT_STRSTR(buffer, "Content-Type:"); // ONION_DEBUG(buffer); END_LOCAL(); }
void t01_handle_static_request(){ INIT_LOCAL(); char ok; onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server, NULL, NULL, lp); onion_request *request=onion_request_new(lp); FILL(request,"GET / HTTP/1.1\n"); onion_handler *handler=onion_handler_static("Not ready",302); FAIL_IF_NOT(handler); onion_set_root_handler(server, handler); onion_response *response=onion_response_new(request); ok=onion_handler_handle(handler, request, response); FAIL_IF_NOT_EQUAL(ok, OCS_PROCESSED); onion_response_free(response); const char *buffer=onion_buffer_listen_point_get_buffer_data(request); FAIL_IF_EQUAL_STR(buffer,""); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 302 REDIRECT\r\n"); FAIL_IF_NOT_STRSTR(buffer, "\r\nContent-Length: 9\r\n"); FAIL_IF_NOT_STRSTR(buffer, "libonion"); FAIL_IF_STRSTR(buffer, "License: AGPL"); // License is now LGPL, no need to advertise FAIL_IF_STRSTR(buffer, "License"); FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nNot ready"); onion_request_free(request); onion_free(server); END_LOCAL(); }
/** * @short Performs the processing of the request. * @memberof onion_server_t * * Returns the OCS_KEEP_ALIVE or OCS_CLOSE_CONNECTION value. If on keep alive the struct is already reinitialized. * * It calls the root_handler and if it returns an error of any type (or not processed), it calls the * default internal_error_handler. * * Normally it could get the server from the request, but it is passed for homogenity, and * to allow unforseen posibilities. * * @see onion_connection_status */ onion_connection_status onion_server_handle_request(onion_server *server, onion_request *req){ onion_response *res=onion_response_new(req); // Call the main handler. onion_connection_status hs=onion_handler_handle(server->root_handler, req, res); if (hs==OCS_INTERNAL_ERROR || hs==OCS_NOT_IMPLEMENTED || hs==OCS_NOT_PROCESSED){ if (hs==OCS_INTERNAL_ERROR) req->flags|=OR_INTERNAL_ERROR; if (hs==OCS_NOT_IMPLEMENTED) req->flags|=OR_NOT_IMPLEMENTED; if (hs==OCS_NOT_PROCESSED) req->flags|=OR_NOT_FOUND; if (hs==OCS_FORBIDDEN) req->flags|=OR_FORBIDDEN; hs=onion_handler_handle(server->internal_error_handler, req, res); } int rs=onion_response_free(res); if (hs>=0 && rs==OCS_KEEP_ALIVE) // if keep alive, reset struct to get the new petition. onion_request_clean(req); return hs>0 ? rs : hs; }
void t02_full_cycle_http10(){ INIT_LOCAL(); onion *server=onion_new(0); onion_add_listen_point(server,NULL,NULL,onion_buffer_listen_point_new()); onion_request *request; char buffer[4096]; memset(buffer,0,sizeof(buffer)); request=onion_request_new(server->listen_points[0]); onion_response *response=onion_response_new(request); onion_response_set_length(response, 30); FAIL_IF_NOT_EQUAL(response->length,30); onion_response_write_headers(response); onion_response_write0(response,"123456789012345678901234567890"); onion_response_flush(response); FAIL_IF_NOT_EQUAL(response->sent_bytes,30); onion_response_free(response); strncpy(buffer,onion_buffer_listen_point_get_buffer_data(request),sizeof(buffer)); onion_request_free(request); onion_free(server); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.0 200 OK\r\n"); FAIL_IF_NOT_STRSTR(buffer, "Connection: Keep-Alive\r\n"); FAIL_IF_NOT_STRSTR(buffer, "Content-Length: 30\r\n"); FAIL_IF_NOT_STRSTR(buffer, "Server: libonion"); FAIL_IF_NOT_STRSTR(buffer, "coralbits"); FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\n123456789012345678901234567890"); END_LOCAL(); }
void t05_printf(){ INIT_LOCAL(); onion *server=onion_new(0); onion_add_listen_point(server,NULL,NULL,onion_buffer_listen_point_new()); onion_request *request; char buffer[4096]; memset(buffer,0,sizeof(buffer)); request=onion_request_new(server->listen_points[0]); onion_response *response=onion_response_new(request); onion_response_printf(response, "%s %d %p", "Hello world", 123, NULL); onion_response_flush(response); onion_response_free(response); buffer[sizeof(buffer)-1]=0; strncpy(buffer,onion_buffer_listen_point_get_buffer_data(request),sizeof(buffer)-1); onion_request_free(request); onion_free(server); FAIL_IF_NOT_STRSTR(buffer, "Hello world 123 (nil)"); END_LOCAL(); }
onion_connection_status sessions(void *ignore, onion_request *req){ onion_response *res=onion_response_new(req); onion_dict *session=onion_request_get_session_dict(req); if (onion_request_get_query(req, "reset")){ onion_request_session_free(req); onion_response_write0(res, "ok"); return onion_response_free(res); } const char *n=onion_dict_get(session, "count"); int count; if (n){ count=atoi(n)+1; } else count=0; char tmp[16]; snprintf(tmp,sizeof(tmp),"%d",count); onion_dict_add(session, "count", tmp, OD_DUP_ALL|OD_REPLACE); if (onion_response_write_headers(res)==OR_SKIP_CONTENT) // Head return onion_response_free(res); onion_response_write0(res, "<html><body>\n<h1>Session data</h1>\n"); if (session){ onion_response_printf(res,"<ul>\n"); onion_dict_preorder(session, print_dict_element, res); onion_response_printf(res,"</ul>\n"); } else{ onion_response_printf(res,"No session data"); } onion_response_write0(res,"</body></html>"); return onion_response_free(res); }
void t01_create_add_free(){ INIT_LOCAL(); onion_response *res; res=onion_response_new(NULL); FAIL_IF_NOT_EQUAL(res->code, 200); FAIL_IF_EQUAL(res,NULL); onion_response_set_length(res,1024); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(res->headers,"Content-Length"),"1024"); onion_response_free(res); END_LOCAL(); }
void t02_cookies(){ INIT_LOCAL(); onion_response *res=onion_response_new(NULL); onion_dict *h=onion_response_get_headers(res); onion_response_add_cookie(res, "key1", "value1", -1, NULL, NULL, 0); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(h, "Set-Cookie"), "key1=value1"); onion_dict_remove(h, "Set-Cookie"); onion_response_add_cookie(res, "key2", "value2", -1, "/", "*.example.org", OC_HTTP_ONLY|OC_SECURE); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(h, "Set-Cookie"), "key2=value2; path=/; domain=*.example.org; HttpOnly; Secure"); onion_dict_remove(h, "Set-Cookie"); onion_response_add_cookie(res, "key3", "value3", 0, "/", "*.example.org", OC_HTTP_ONLY|OC_SECURE); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(h, "Set-Cookie"), "key3=value3; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=*.example.org; HttpOnly; Secure"); onion_dict_remove(h, "Set-Cookie"); onion_response_add_cookie(res, "key4", "value4", 60, "/", "*.example.org", OC_HTTP_ONLY|OC_SECURE); FAIL_IF_EQUAL_STR(onion_dict_get(h, "Set-Cookie"), "key4=value4; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=*.example.org; HttpOnly; Secure"); FAIL_IF_EQUAL_STR(onion_dict_get(h, "Set-Cookie"), "key4=value4; domain=*.example.org; HttpOnly; path=/; Secure"); int i; int valid_expires=0; char tmpdate[100]; const char *setcookie=onion_dict_get(h, "Set-Cookie"); for(i=59;i<62;i++){ struct tm *tmp; time_t t=time(NULL) + i; tmp = localtime(&t); strftime(tmpdate, sizeof(tmpdate), "key4=value4; expires=%a, %d %b %Y %H:%M:%S %Z; path=/; domain=*.example.org; HttpOnly; Secure", tmp); ONION_DEBUG("\ntest %s =? \nonion %s", tmpdate, setcookie); if (strcmp(tmpdate, setcookie)==0) valid_expires=1; } FAIL_IF_NOT(valid_expires); onion_response_free(res); END_LOCAL(); }
/** * @short Handler that just echoes all data, writing what was a header, what the method... */ onion_connection_status allinfo_handler(void *data, onion_request *req){ onion_response *res=onion_response_new(req); onion_response_write_headers(res); int f=onion_request_get_flags(req); onion_response_printf(res, "Method: %s\n",(f&OR_GET) ? "GET" : (f&OR_HEAD) ? "HEAD" : "POST"); onion_response_printf(res, "Path: %s\n",onion_request_get_path(req)); onion_response_printf(res, "Version: %s\n",onion_request_get_flags(req)&OR_HTTP11 ? "HTTP/1.1" : "HTTP/1.0"); allinfo_dict_print_t aid; aid.res=res; aid.part="Query"; onion_dict_preorder(onion_request_get_query_dict(req),allinfo_query, &aid); aid.part="Header"; onion_dict_preorder(onion_request_get_header_dict(req),allinfo_query, &aid); aid.part="POST"; onion_dict_preorder(onion_request_get_post_dict(req),allinfo_query, &aid); aid.part="FILE"; onion_dict_preorder(onion_request_get_file_dict(req),allinfo_query, &aid); return onion_response_free(res);; }
/** * @short Launches one handler for the given request * @ingroup request * * Once the request is ready, launch it. * * @returns The connection status: if it should be closed, error codes... */ onion_connection_status onion_request_process(onion_request *req){ onion_response *res=onion_response_new(req); if (!req->path){ onion_request_polish(req); } // Call the main handler. onion_connection_status hs=onion_handler_handle(req->connection.listen_point->server->root_handler, req, res); if (hs==OCS_INTERNAL_ERROR || hs==OCS_NOT_IMPLEMENTED || hs==OCS_NOT_PROCESSED){ if (hs==OCS_INTERNAL_ERROR) req->flags|=OR_INTERNAL_ERROR; if (hs==OCS_NOT_IMPLEMENTED) req->flags|=OR_NOT_IMPLEMENTED; if (hs==OCS_NOT_PROCESSED) req->flags|=OR_NOT_FOUND; if (hs==OCS_FORBIDDEN) req->flags|=OR_FORBIDDEN; hs=onion_handler_handle(req->connection.listen_point->server->internal_error_handler, req, res); } if (hs==OCS_YIELD){ // Remove from the poller, and yield thread to poller. From now on it will be processed somewhere else (longpoll thread). onion_poller *poller=onion_get_poller(req->connection.listen_point->server); onion_poller_slot *slot=onion_poller_get(poller, req->connection.fd); onion_poller_slot_set_shutdown(slot, NULL, NULL); return hs; } int rs=onion_response_free(res); if (hs>=0 && rs==OCS_KEEP_ALIVE) // if keep alive, reset struct to get the new petition. onion_request_clean(req); return hs>0 ? rs : hs; }
void free_reqres(reqres_t * rr) { onion_response_free(rr->res); onion_request_free(rr->req); onion_low_free(rr); }
void t03_handle_path_request(){ INIT_LOCAL(); onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server, NULL, NULL, lp); onion_url *urls=onion_url_new(); onion_url_add_static(urls, "^$", "Test index\n", HTTP_OK); onion_url_add_static(urls, "^index.html$", "Index test", 200); onion_url *pathu=onion_url_new(); onion_handler *path=onion_url_to_handler(pathu); onion_url_add_url(pathu, "^test/", urls); onion_handler_add(path, onion_handler_static("Internal error", 500 ) ); onion_set_root_handler(server, path); onion_request *request; onion_response *response; request=onion_request_new(lp); FILL(request,"GET / HTTP/1.1\n"); onion_request_polish(request); response=onion_response_new(request); onion_handler_handle(path, request, response); onion_response_free(response); const char *buffer=onion_buffer_listen_point_get_buffer_data(request); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 500 INTERNAL ERROR\r\n"); FAIL_IF_NOT_STRSTR(buffer, "Content-Length: 14\r\n"); FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nInternal error"); onion_request_free(request); // gives error, as such url does not exist. request=onion_request_new(lp); FILL(request,"GET /test/ HTTP/1.1\n"); onion_request_polish(request); response=onion_response_new(request); onion_handler_handle(path, request, response); onion_response_free(response); buffer=onion_buffer_listen_point_get_buffer_data(request); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 200 OK\r\n"); FAIL_IF_NOT_STRSTR(buffer, "Content-Length: 11\r\n"); FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nTest index\n"); onion_request_free(request); request=onion_request_new(lp); FILL(request,"GET /test/index.html HTTP/1.1\n"); onion_request_polish(request); response=onion_response_new(request); onion_handler_handle(path, request, response); onion_response_free(response); buffer=onion_buffer_listen_point_get_buffer_data(request); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 200 OK\r\n"); FAIL_IF_NOT_STRSTR(buffer, "Content-Length: 10\r\n"); FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nIndex test"); onion_request_free(request); onion_free(server); END_LOCAL(); }