#include #include #include "http_lua.h" #include #include #include #include #include #include bool g_print_to_stderr = true; struct lua_http_head_field { TAILQ_ENTRY(lua_http_head_field) next; char * value; struct http_field_name *field; }; struct lua_http_headers { TAILQ_HEAD(http_field_list_head, lua_http_head_field) lua_http_field_list; int nvlen; uint8_t flag; }; struct def_lua_http_headers { const char *filed_name; const char *value; enum tfe_http_std_field field_id; }; struct def_lua_http_headers def_lua_http_head_value[]={{"accept", "text/html", TFE_HTTP_UNKNOWN_FIELD}, {"accept-encoding", "gzip, deflate, br", TFE_HTTP_UNKNOWN_FIELD}, {"accept-language", "zh-CN,zh;q=0.9", TFE_HTTP_UNKNOWN_FIELD}, {"pragma", "no-cache", TFE_HTTP_PRAGMA}, {"user-agent", "Mozilla/5.0", TFE_HTTP_USER_AGENT}, {"cache-control", "max-age=3600", TFE_HTTP_CACHE_CONTROL}, {"content-encoding", "gzip", TFE_HTTP_CONT_ENCODING}, {"content-type", "text/html", TFE_HTTP_CONT_TYPE}, {"server", "nginx", TFE_HTTP_SERVER}, {"expires", "Tue, 12 Jul 2022 07:11:56 GMT", TFE_HTTP_EXPIRES}}; struct tsg_lua_pattern { int thread_num; struct elua_script **elua_ctx; struct tsg_lua_script *lua_script; struct lua_http_headers lua_http_head_list; }; struct tsg_lua_pattern *g_tsg_lua_pattern=NULL; struct lua_http_headers *lua_get_http_head_list() { return &g_tsg_lua_pattern->lua_http_head_list; } struct http_field_name *lua_http_field_name_dup(const struct http_field_name * orig) { struct http_field_name * field_name_item = ALLOC(struct http_field_name, 1); assert(field_name_item != NULL); if (orig->field_id == TFE_HTTP_UNKNOWN_FIELD) { field_name_item->field_id = TFE_HTTP_UNKNOWN_FIELD; field_name_item->field_name = tfe_strdup(orig->field_name); } else { field_name_item->field_id = orig->field_id; field_name_item->field_name = NULL; } return field_name_item; } const char *lua_http_field_iterate(const struct tfe_http_half * half, void ** iter, struct http_field_name * field) { struct lua_http_head_field **http_head_field = (struct lua_http_head_field **) iter; if (*http_head_field == NULL) *http_head_field = TAILQ_FIRST(&(lua_get_http_head_list()->lua_http_field_list)); else *http_head_field = TAILQ_NEXT(*http_head_field, next); if (*http_head_field == NULL) return NULL; field->field_id = (*http_head_field)->field->field_id; field->field_name = (*http_head_field)->field->field_name; return (*http_head_field)->value; } int lua_http_field_write(struct tfe_http_half * half, const struct http_field_name * field, const char * value) { if (value != NULL) { struct lua_http_head_field * http_head_field = ALLOC(struct lua_http_head_field, 1); http_head_field->field = lua_http_field_name_dup(field); http_head_field->value = tfe_strdup(value); TAILQ_INSERT_TAIL(&g_tsg_lua_pattern->lua_http_head_list.lua_http_field_list, http_head_field, next); } else { struct lua_http_head_field * http_head_field = NULL; struct lua_http_head_field * http_head_field_peer = NULL; TAILQ_FOREACH_SAFE(http_head_field, &g_tsg_lua_pattern->lua_http_head_list.lua_http_field_list, next, http_head_field_peer) { if (http_field_name_compare(http_head_field->field, field) != 0) continue; TAILQ_REMOVE(&g_tsg_lua_pattern->lua_http_head_list.lua_http_field_list, http_head_field, next); http_field_name_destory(http_head_field->field); free(http_head_field->value); free(http_head_field); } } return 0; } const char *lua_http_field_read(const struct tfe_http_half * half, const struct http_field_name * field) { struct lua_http_head_field * http_head_field = NULL; struct lua_http_head_field * http_head_field_node = NULL; TAILQ_FOREACH(http_head_field, &g_tsg_lua_pattern->lua_http_head_list.lua_http_field_list, next) { if (http_field_name_compare(http_head_field->field, field) != 0) continue; http_head_field_node = http_head_field; break; } return http_head_field_node != NULL ? http_head_field->value : NULL; } static int lua_http_default_headers_init(struct def_lua_http_headers *lua_http_head_value) { for(size_t i=0; i < sizeof(def_lua_http_head_value)/sizeof(struct def_lua_http_headers); i++) { struct http_field_name field; field.field_id = lua_http_head_value[i].field_id; field.field_name = lua_http_head_value[i].filed_name; struct lua_http_head_field * http_head_field = ALLOC(struct lua_http_head_field, 1); http_head_field->field = lua_http_field_name_dup(&field); http_head_field->value = tfe_strdup(lua_http_head_value[i].value); TAILQ_INSERT_TAIL(&g_tsg_lua_pattern->lua_http_head_list.lua_http_field_list, http_head_field, next); } return 0; } int http_lua_profile_for_test(int profile_id, struct elua_script ***elua_ctx) { *elua_ctx=g_tsg_lua_pattern->elua_ctx; return 0; } void lua_http_session_destory(struct tfe_http_session *session) { if(session != NULL) { char *uri=(char *)session->req->req_spec.uri; if(uri) FREE(&uri); struct tfe_http_half_ops *ops=(struct tfe_http_half_ops *)session->resp->ops; if(ops) FREE(&ops); if(session->resp) FREE(&session->resp); if(session->req) FREE(&session->req); FREE(&session); } return; } const struct tfe_http_session *lua_http_session_init() { struct tfe_http_session *session =ALLOC(struct tfe_http_session, 1); struct tfe_http_half * in_req_half=ALLOC(struct tfe_http_half, 1); session->req = in_req_half; struct tfe_http_half * in_resp_half=ALLOC(struct tfe_http_half, 1); session->resp = in_resp_half; struct tfe_http_half_ops *ops = ALLOC(struct tfe_http_half_ops, 1); in_resp_half->ops = ops; in_req_half->ops = ops; ops->ops_http_field_iterate = lua_http_field_iterate; ops->ops_http_field_write = lua_http_field_write; ops->ops_http_field_read = lua_http_field_read; return session; } TEST(TSG_LUA_SCRIPT, Lua_TimeOut) { int ret=0; int profile_id=0,thread_id=0; struct tsg_script_ctx tsg_ctx; struct timespec start_time, end_time; memset(&tsg_ctx, 0, sizeof(tsg_ctx)); tsg_ctx.session=lua_http_session_init(); tsg_ctx.http_req_uri=2; struct tsg_lua_script * lua_script=g_tsg_lua_pattern->lua_script; lua_script->http_lua_profile = http_lua_profile_for_test; clock_gettime(CLOCK_REALTIME, &(start_time)); ret = execute_lua_script_rule(lua_script, profile_id, NULL, thread_id, (void *)&tsg_ctx); EXPECT_TRUE(ret!=0); clock_gettime(CLOCK_REALTIME, &(end_time)); printf("take time %lu(s)\n", end_time.tv_sec - start_time.tv_sec); lua_http_session_destory((struct tfe_http_session *)tsg_ctx.session); } TEST(TSG_LUA_SCRIPT, Req_Uri) { int ret=0; int profile_id=0,thread_id=0; struct tsg_script_ctx tsg_ctx; memset(&tsg_ctx, 0, sizeof(tsg_ctx)); tsg_ctx.session=lua_http_session_init(); tsg_ctx.events = EV_HTTP_REQ_HDR; tsg_ctx.http_req_uri=1; struct tsg_lua_script * lua_script=g_tsg_lua_pattern->lua_script; lua_script->http_lua_profile = http_lua_profile_for_test; tsg_ctx.session->req->req_spec.uri = tfe_strdup("forecast"); ret = execute_lua_script_rule(lua_script, profile_id, NULL, thread_id, (void *)&tsg_ctx); EXPECT_TRUE(ret==0); EXPECT_STREQ(tsg_ctx.rewrite_uri,"team"); FREE(&tsg_ctx.rewrite_uri); lua_http_session_destory((struct tfe_http_session *)tsg_ctx.session); } TEST(TSG_LUA_SCRIPT, Req_Header) { int ret=0; int profile_id=0,thread_id=0; struct tsg_script_ctx tsg_ctx; memset(&tsg_ctx, 0, sizeof(tsg_ctx)); tsg_ctx.session=lua_http_session_init(); tsg_ctx.events = EV_HTTP_REQ_HDR; struct tsg_lua_script * lua_script=g_tsg_lua_pattern->lua_script; lua_script->http_lua_profile = http_lua_profile_for_test; tsg_ctx.session->req->req_spec.method = TFE_HTTP_METHOD_GET; ret = execute_lua_script_rule(lua_script, profile_id, NULL, thread_id, (void *)&tsg_ctx); EXPECT_TRUE(ret==0); const char* user_agent_val=tfe_http_std_field_read(tsg_ctx.session->resp, TFE_HTTP_USER_AGENT); EXPECT_TRUE(user_agent_val!=NULL); EXPECT_STREQ(user_agent_val, "curl-v1.1"); const char* x_tg_val=tfe_http_nonstd_field_read(tsg_ctx.session->resp, "x-tg-construct-by"); EXPECT_TRUE(x_tg_val!=NULL); EXPECT_STREQ(x_tg_val, "tfe"); lua_http_session_destory((struct tfe_http_session *)tsg_ctx.session); } TEST(TSG_LUA_SCRIPT, Resp_Header) { int ret=0; int profile_id=0,thread_id=0; struct tsg_script_ctx tsg_ctx; memset(&tsg_ctx,0,sizeof(struct tsg_script_ctx)); tsg_ctx.session=lua_http_session_init(); tsg_ctx.events = EV_HTTP_RESP_HDR; struct tsg_lua_script * lua_script=g_tsg_lua_pattern->lua_script; lua_script->http_lua_profile = http_lua_profile_for_test; tsg_ctx.session->resp->resp_spec.resp_code = 200; ret = execute_lua_script_rule(lua_script, profile_id, NULL, thread_id, (void *)&tsg_ctx); EXPECT_TRUE(ret==0); const char* content_type_val=tfe_http_std_field_read(tsg_ctx.session->resp, TFE_HTTP_CONT_TYPE); EXPECT_TRUE(content_type_val!=NULL); EXPECT_STREQ(content_type_val, "utf8"); lua_http_session_destory((struct tfe_http_session *)tsg_ctx.session); } TEST(TSG_LUA_SCRIPT, Req_Data) { int ret=0; int profile_id=0,thread_id=0; struct tsg_script_ctx tsg_ctx; memset(&tsg_ctx,0,sizeof(struct tsg_script_ctx)); tsg_ctx.session=lua_http_session_init(); tsg_ctx.events = EV_HTTP_REQ_BODY_END; struct tsg_lua_script * lua_script=g_tsg_lua_pattern->lua_script; lua_script->http_lua_profile = http_lua_profile_for_test; const char *input="This is request data"; tsg_ctx.http_body = evbuffer_new(); evbuffer_add(tsg_ctx.http_body, input, strlen(input)); ret = execute_lua_script_rule(lua_script, profile_id, NULL, thread_id, (void *)&tsg_ctx); EXPECT_TRUE(ret==0); ASSERT_TRUE(tsg_ctx.http_lua_body!=NULL); char *__http_body=(char *) evbuffer_pullup(tsg_ctx.http_lua_body, -1); EXPECT_STREQ(__http_body, "This is request data set req body"); printf("__http_body: %s\n",__http_body); evbuffer_free(tsg_ctx.http_body); evbuffer_free(tsg_ctx.http_lua_body); lua_http_session_destory((struct tfe_http_session *)tsg_ctx.session); } TEST(TSG_LUA_SCRIPT, Resq_Data) { int ret=0; int profile_id=3,thread_id=0; struct tsg_script_ctx tsg_ctx; memset(&tsg_ctx,0,sizeof(struct tsg_script_ctx)); tsg_ctx.session=lua_http_session_init(); tsg_ctx.events = EV_HTTP_RESP_BODY_END; struct tsg_lua_script * lua_script=g_tsg_lua_pattern->lua_script; lua_script->http_lua_profile = http_lua_profile_for_test; const char *input="This is response data"; tsg_ctx.http_body = evbuffer_new(); evbuffer_add(tsg_ctx.http_body, input, strlen(input)); ret = execute_lua_script_rule(lua_script, profile_id, NULL, thread_id, (void *)&tsg_ctx); EXPECT_TRUE(ret==0); ASSERT_TRUE(tsg_ctx.http_lua_body!=NULL); char *__http_body=(char *) evbuffer_pullup(tsg_ctx.http_lua_body, -1); EXPECT_STREQ(__http_body, "This is response data set resp body"); printf("__http_body: %s\n",__http_body); evbuffer_free(tsg_ctx.http_body); evbuffer_free(tsg_ctx.http_lua_body); lua_http_session_destory((struct tfe_http_session *)tsg_ctx.session); } TEST(TSG_LUA_SCRIPT, Lua_Http_Session) { int ret=0; int profile_id=0,thread_id=0; struct tsg_script_ctx tsg_ctx; memset(&tsg_ctx,0,sizeof(struct tsg_script_ctx)); tsg_ctx.session=lua_http_session_init(); tsg_ctx.events = EV_HTTP_RESP_HDR; struct tsg_lua_script * lua_script=g_tsg_lua_pattern->lua_script; lua_script->http_lua_profile = http_lua_profile_for_test; tsg_ctx.elua_ctx=http_lua_ctx_new(lua_script, thread_id); ret = execute_lua_script_rule(lua_script, profile_id, tsg_ctx.elua_ctx, thread_id, (void *)&tsg_ctx); EXPECT_TRUE(ret==0); const char* content_type_val=tfe_http_std_field_read(tsg_ctx.session->resp, TFE_HTTP_CONT_TYPE); EXPECT_TRUE(content_type_val!=NULL); EXPECT_STREQ(content_type_val, "utf8"); tsg_ctx.events = EV_HTTP_RESP_BODY_END; tsg_ctx.http_body = evbuffer_new(); const char *user_input="This is response data"; evbuffer_add(tsg_ctx.http_body, user_input, strlen(user_input)); ret = execute_lua_script_rule(lua_script, profile_id, tsg_ctx.elua_ctx, thread_id, (void *)&tsg_ctx); EXPECT_TRUE(ret==0); EXPECT_TRUE(tsg_ctx.http_lua_body!=NULL); char *__http_body=(char *) evbuffer_pullup(tsg_ctx.http_lua_body, -1); EXPECT_STREQ(__http_body, "This is response data set resp body"); printf("__http_body: %s\n",__http_body); evbuffer_free(tsg_ctx.http_body); evbuffer_free(tsg_ctx.http_lua_body); http_lua_ctx_free(lua_script, thread_id, tsg_ctx.elua_ctx); lua_http_session_destory((struct tfe_http_session *)tsg_ctx.session); } int main(int argc, char ** argv) { struct tsg_lua_pattern *tsg_lua_pattern = ALLOC(struct tsg_lua_pattern, 1); TAILQ_INIT(&tsg_lua_pattern->lua_http_head_list.lua_http_field_list); int i=0, thread_num=1; struct tsg_lua_script *lua_script=ALLOC(struct tsg_lua_script, 1); http_lua_handle_create(lua_script, thread_num, "tfe"); size_t input_sz; const char* filename="./test_data/http_session.lua"; char *input= tfe_read_file(filename, &input_sz); tsg_lua_pattern->elua_ctx = ALLOC(struct elua_script*, thread_num); for(i=0; ielua_ctx[i]=http_lua_map_cache_script(lua_script->http_lua_handle[i], input, input_sz, 1000); } tsg_lua_pattern->lua_script=lua_script; tsg_lua_pattern->thread_num=thread_num; g_tsg_lua_pattern = tsg_lua_pattern; lua_http_default_headers_init(def_lua_http_head_value); ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }