From a4e2c31b86d978632ae87946ff0fc4ed7f555f91 Mon Sep 17 00:00:00 2001 From: lianglli Date: Mon, 18 Sep 2023 22:25:58 +0800 Subject: [PATCH 1/2] HTTP Route: supports routing based on multiple values, nginx var, or mod of header, cookie, query parameter while also being able to add HTTP headers and query parameter --- modules/ngx_ingress_module/ingress.pb-c.c | 521 ++++++++++- modules/ngx_ingress_module/ingress.pb-c.h | 261 +++++- modules/ngx_ingress_module/ingress.proto | 95 +- .../ngx_ingress_module/ngx_ingress_module.c | 826 ++++++++++++++---- .../ngx_ingress_module/ngx_ingress_module.h | 43 +- .../ngx_ingress_module/ngx_ingress_protobuf.c | 292 ++++++- 6 files changed, 1793 insertions(+), 245 deletions(-) diff --git a/modules/ngx_ingress_module/ingress.pb-c.c b/modules/ngx_ingress_module/ingress.pb-c.c index e93d954b8d..5748dc5192 100644 --- a/modules/ngx_ingress_module/ingress.pb-c.c +++ b/modules/ngx_ingress_module/ingress.pb-c.c @@ -7,6 +7,96 @@ #endif #include "ingress.pb-c.h" +void ingress__tag_value_str_list__init + (Ingress__TagValueStrList *message) +{ + static const Ingress__TagValueStrList init_value = INGRESS__TAG_VALUE_STR_LIST__INIT; + *message = init_value; +} +size_t ingress__tag_value_str_list__get_packed_size + (const Ingress__TagValueStrList *message) +{ + assert(message->base.descriptor == &ingress__tag_value_str_list__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t ingress__tag_value_str_list__pack + (const Ingress__TagValueStrList *message, + uint8_t *out) +{ + assert(message->base.descriptor == &ingress__tag_value_str_list__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t ingress__tag_value_str_list__pack_to_buffer + (const Ingress__TagValueStrList *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &ingress__tag_value_str_list__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Ingress__TagValueStrList * + ingress__tag_value_str_list__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Ingress__TagValueStrList *) + protobuf_c_message_unpack (&ingress__tag_value_str_list__descriptor, + allocator, len, data); +} +void ingress__tag_value_str_list__free_unpacked + (Ingress__TagValueStrList *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &ingress__tag_value_str_list__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} +void ingress__tag_item_condition__init + (Ingress__TagItemCondition *message) +{ + static const Ingress__TagItemCondition init_value = INGRESS__TAG_ITEM_CONDITION__INIT; + *message = init_value; +} +size_t ingress__tag_item_condition__get_packed_size + (const Ingress__TagItemCondition *message) +{ + assert(message->base.descriptor == &ingress__tag_item_condition__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t ingress__tag_item_condition__pack + (const Ingress__TagItemCondition *message, + uint8_t *out) +{ + assert(message->base.descriptor == &ingress__tag_item_condition__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t ingress__tag_item_condition__pack_to_buffer + (const Ingress__TagItemCondition *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &ingress__tag_item_condition__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Ingress__TagItemCondition * + ingress__tag_item_condition__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Ingress__TagItemCondition *) + protobuf_c_message_unpack (&ingress__tag_item_condition__descriptor, + allocator, len, data); +} +void ingress__tag_item_condition__free_unpacked + (Ingress__TagItemCondition *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &ingress__tag_item_condition__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} void ingress__tag_item__init (Ingress__TagItem *message) { @@ -502,6 +592,51 @@ void ingress__metadata__free_unpacked assert(message->base.descriptor == &ingress__metadata__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } +void ingress__action__init + (Ingress__Action *message) +{ + static const Ingress__Action init_value = INGRESS__ACTION__INIT; + *message = init_value; +} +size_t ingress__action__get_packed_size + (const Ingress__Action *message) +{ + assert(message->base.descriptor == &ingress__action__descriptor); + return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message)); +} +size_t ingress__action__pack + (const Ingress__Action *message, + uint8_t *out) +{ + assert(message->base.descriptor == &ingress__action__descriptor); + return protobuf_c_message_pack ((const ProtobufCMessage*)message, out); +} +size_t ingress__action__pack_to_buffer + (const Ingress__Action *message, + ProtobufCBuffer *buffer) +{ + assert(message->base.descriptor == &ingress__action__descriptor); + return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer); +} +Ingress__Action * + ingress__action__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data) +{ + return (Ingress__Action *) + protobuf_c_message_unpack (&ingress__action__descriptor, + allocator, len, data); +} +void ingress__action__free_unpacked + (Ingress__Action *message, + ProtobufCAllocator *allocator) +{ + if(!message) + return; + assert(message->base.descriptor == &ingress__action__descriptor); + protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); +} void ingress__virtual_service__init (Ingress__VirtualService *message) { @@ -592,6 +727,134 @@ void ingress__config__free_unpacked assert(message->base.descriptor == &ingress__config__descriptor); protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator); } +static const ProtobufCFieldDescriptor ingress__tag_value_str_list__field_descriptors[1] = +{ + { + "value", + 1, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_STRING, + offsetof(Ingress__TagValueStrList, n_value), + offsetof(Ingress__TagValueStrList, value), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned ingress__tag_value_str_list__field_indices_by_name[] = { + 0, /* field[0] = value */ +}; +static const ProtobufCIntRange ingress__tag_value_str_list__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 1 } +}; +const ProtobufCMessageDescriptor ingress__tag_value_str_list__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "Ingress.TagValueStrList", + "TagValueStrList", + "Ingress__TagValueStrList", + "Ingress", + sizeof(Ingress__TagValueStrList), + 1, + ingress__tag_value_str_list__field_descriptors, + ingress__tag_value_str_list__field_indices_by_name, + 1, ingress__tag_value_str_list__number_ranges, + (ProtobufCMessageInit) ingress__tag_value_str_list__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor ingress__tag_item_condition__field_descriptors[5] = +{ + { + "value_str", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Ingress__TagItemCondition, value_str), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "value_list", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_MESSAGE, + 0, /* quantifier_offset */ + offsetof(Ingress__TagItemCondition, value_list), + &ingress__tag_value_str_list__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "divisor", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_UINT64, + offsetof(Ingress__TagItemCondition, has_divisor), + offsetof(Ingress__TagItemCondition, divisor), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "remainder", + 4, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_UINT64, + offsetof(Ingress__TagItemCondition, has_remainder), + offsetof(Ingress__TagItemCondition, remainder), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "operator", + 5, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_ENUM, + offsetof(Ingress__TagItemCondition, has_operator_), + offsetof(Ingress__TagItemCondition, operator_), + &ingress__operator_type__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned ingress__tag_item_condition__field_indices_by_name[] = { + 2, /* field[2] = divisor */ + 4, /* field[4] = operator */ + 3, /* field[3] = remainder */ + 1, /* field[1] = value_list */ + 0, /* field[0] = value_str */ +}; +static const ProtobufCIntRange ingress__tag_item_condition__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 5 } +}; +const ProtobufCMessageDescriptor ingress__tag_item_condition__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "Ingress.TagItemCondition", + "TagItemCondition", + "Ingress__TagItemCondition", + "Ingress", + sizeof(Ingress__TagItemCondition), + 5, + ingress__tag_item_condition__field_descriptors, + ingress__tag_item_condition__field_indices_by_name, + 1, ingress__tag_item_condition__number_ranges, + (ProtobufCMessageInit) ingress__tag_item_condition__init, + NULL,NULL,NULL /* reserved[123] */ +}; static const ProtobufCFieldDescriptor ingress__tag_item__field_descriptors[4] = { { @@ -619,13 +882,13 @@ static const ProtobufCFieldDescriptor ingress__tag_item__field_descriptors[4] = 0,NULL,NULL /* reserved1,reserved2, etc */ }, { - "value", + "condition", 3, PROTOBUF_C_LABEL_OPTIONAL, - PROTOBUF_C_TYPE_STRING, + PROTOBUF_C_TYPE_MESSAGE, 0, /* quantifier_offset */ - offsetof(Ingress__TagItem, value), - NULL, + offsetof(Ingress__TagItem, condition), + &ingress__tag_item_condition__descriptor, NULL, 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ @@ -644,10 +907,10 @@ static const ProtobufCFieldDescriptor ingress__tag_item__field_descriptors[4] = }, }; static const unsigned ingress__tag_item__field_indices_by_name[] = { + 2, /* field[2] = condition */ 1, /* field[1] = key */ 0, /* field[0] = location */ 3, /* field[3] = match_type */ - 2, /* field[2] = value */ }; static const ProtobufCIntRange ingress__tag_item__number_ranges[1 + 1] = { @@ -1257,7 +1520,84 @@ const ProtobufCMessageDescriptor ingress__metadata__descriptor = (ProtobufCMessageInit) ingress__metadata__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCFieldDescriptor ingress__virtual_service__field_descriptors[5] = +static const ProtobufCFieldDescriptor ingress__action__field_descriptors[4] = +{ + { + "action_type", + 1, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_ENUM, + offsetof(Ingress__Action, has_action_type), + offsetof(Ingress__Action, action_type), + &ingress__action_type__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "value_type", + 2, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_ENUM, + offsetof(Ingress__Action, has_value_type), + offsetof(Ingress__Action, value_type), + &ingress__action_value_type__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "key", + 3, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Ingress__Action, key), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, + { + "value", + 4, + PROTOBUF_C_LABEL_OPTIONAL, + PROTOBUF_C_TYPE_STRING, + 0, /* quantifier_offset */ + offsetof(Ingress__Action, value), + NULL, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, +}; +static const unsigned ingress__action__field_indices_by_name[] = { + 0, /* field[0] = action_type */ + 2, /* field[2] = key */ + 3, /* field[3] = value */ + 1, /* field[1] = value_type */ +}; +static const ProtobufCIntRange ingress__action__number_ranges[1 + 1] = +{ + { 1, 0 }, + { 0, 4 } +}; +const ProtobufCMessageDescriptor ingress__action__descriptor = +{ + PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC, + "Ingress.Action", + "Action", + "Ingress__Action", + "Ingress", + sizeof(Ingress__Action), + 4, + ingress__action__field_descriptors, + ingress__action__field_indices_by_name, + 1, ingress__action__number_ranges, + (ProtobufCMessageInit) ingress__action__init, + NULL,NULL,NULL /* reserved[123] */ +}; +static const ProtobufCFieldDescriptor ingress__virtual_service__field_descriptors[6] = { { "service_name", @@ -1319,8 +1659,21 @@ static const ProtobufCFieldDescriptor ingress__virtual_service__field_descriptor 0, /* flags */ 0,NULL,NULL /* reserved1,reserved2, etc */ }, + { + "action", + 6, + PROTOBUF_C_LABEL_REPEATED, + PROTOBUF_C_TYPE_MESSAGE, + offsetof(Ingress__VirtualService, n_action), + offsetof(Ingress__VirtualService, action), + &ingress__action__descriptor, + NULL, + 0, /* flags */ + 0,NULL,NULL /* reserved1,reserved2, etc */ + }, }; static const unsigned ingress__virtual_service__field_indices_by_name[] = { + 5, /* field[5] = action */ 3, /* field[3] = force_https */ 4, /* field[4] = metadata */ 0, /* field[0] = service_name */ @@ -1330,7 +1683,7 @@ static const unsigned ingress__virtual_service__field_indices_by_name[] = { static const ProtobufCIntRange ingress__virtual_service__number_ranges[1 + 1] = { { 1, 0 }, - { 0, 5 } + { 0, 6 } }; const ProtobufCMessageDescriptor ingress__virtual_service__descriptor = { @@ -1340,7 +1693,7 @@ const ProtobufCMessageDescriptor ingress__virtual_service__descriptor = "Ingress__VirtualService", "Ingress", sizeof(Ingress__VirtualService), - 5, + 6, ingress__virtual_service__field_descriptors, ingress__virtual_service__field_indices_by_name, 1, ingress__virtual_service__number_ranges, @@ -1398,22 +1751,26 @@ const ProtobufCMessageDescriptor ingress__config__descriptor = (ProtobufCMessageInit) ingress__config__init, NULL,NULL,NULL /* reserved[123] */ }; -static const ProtobufCEnumValue ingress__location_type__enum_values_by_number[4] = -{ - { "LocHttpHeader", "INGRESS__LOCATION_TYPE__LocHttpHeader", 0 }, - { "LocHttpQuery", "INGRESS__LOCATION_TYPE__LocHttpQuery", 1 }, - { "LocNginxVar", "INGRESS__LOCATION_TYPE__LocNginxVar", 2 }, - { "LocXBizInfo", "INGRESS__LOCATION_TYPE__LocXBizInfo", 3 }, +static const ProtobufCEnumValue ingress__location_type__enum_values_by_number[6] = +{ + { "LocUnDefined", "INGRESS__LOCATION_TYPE__LocUnDefined", 0 }, + { "LocHttpHeader", "INGRESS__LOCATION_TYPE__LocHttpHeader", 1 }, + { "LocHttpQuery", "INGRESS__LOCATION_TYPE__LocHttpQuery", 2 }, + { "LocNginxVar", "INGRESS__LOCATION_TYPE__LocNginxVar", 3 }, + { "LocXBizInfo", "INGRESS__LOCATION_TYPE__LocXBizInfo", 4 }, + { "LocHttpCookie", "INGRESS__LOCATION_TYPE__LocHttpCookie", 5 }, }; static const ProtobufCIntRange ingress__location_type__value_ranges[] = { -{0, 0},{0, 4} +{0, 0},{0, 6} }; -static const ProtobufCEnumValueIndex ingress__location_type__enum_values_by_name[4] = -{ - { "LocHttpHeader", 0 }, - { "LocHttpQuery", 1 }, - { "LocNginxVar", 2 }, - { "LocXBizInfo", 3 }, +static const ProtobufCEnumValueIndex ingress__location_type__enum_values_by_name[6] = +{ + { "LocHttpCookie", 5 }, + { "LocHttpHeader", 1 }, + { "LocHttpQuery", 2 }, + { "LocNginxVar", 3 }, + { "LocUnDefined", 0 }, + { "LocXBizInfo", 4 }, }; const ProtobufCEnumDescriptor ingress__location_type__descriptor = { @@ -1422,9 +1779,9 @@ const ProtobufCEnumDescriptor ingress__location_type__descriptor = "LocationType", "Ingress__LocationType", "Ingress", - 4, + 6, ingress__location_type__enum_values_by_number, - 4, + 6, ingress__location_type__enum_values_by_name, 1, ingress__location_type__value_ranges, @@ -1432,20 +1789,20 @@ const ProtobufCEnumDescriptor ingress__location_type__descriptor = }; static const ProtobufCEnumValue ingress__match_type__enum_values_by_number[4] = { - { "WholeMatch", "INGRESS__MATCH_TYPE__WholeMatch", 0 }, - { "PrefixMatch", "INGRESS__MATCH_TYPE__PrefixMatch", 1 }, - { "SuffixMatch", "INGRESS__MATCH_TYPE__SuffixMatch", 2 }, - { "RegMatch", "INGRESS__MATCH_TYPE__RegMatch", 3 }, + { "MatchUnDefined", "INGRESS__MATCH_TYPE__MatchUnDefined", 0 }, + { "WholeMatch", "INGRESS__MATCH_TYPE__WholeMatch", 1 }, + { "StrListInMatch", "INGRESS__MATCH_TYPE__StrListInMatch", 2 }, + { "ModCompare", "INGRESS__MATCH_TYPE__ModCompare", 3 }, }; static const ProtobufCIntRange ingress__match_type__value_ranges[] = { {0, 0},{0, 4} }; static const ProtobufCEnumValueIndex ingress__match_type__enum_values_by_name[4] = { - { "PrefixMatch", 1 }, - { "RegMatch", 3 }, - { "SuffixMatch", 2 }, - { "WholeMatch", 0 }, + { "MatchUnDefined", 0 }, + { "ModCompare", 3 }, + { "StrListInMatch", 2 }, + { "WholeMatch", 1 }, }; const ProtobufCEnumDescriptor ingress__match_type__descriptor = { @@ -1462,3 +1819,105 @@ const ProtobufCEnumDescriptor ingress__match_type__descriptor = ingress__match_type__value_ranges, NULL,NULL,NULL,NULL /* reserved[1234] */ }; +static const ProtobufCEnumValue ingress__operator_type__enum_values_by_number[6] = +{ + { "OperatorUnDefined", "INGRESS__OPERATOR_TYPE__OperatorUnDefined", 0 }, + { "OperatorEqual", "INGRESS__OPERATOR_TYPE__OperatorEqual", 1 }, + { "OperatorGreater", "INGRESS__OPERATOR_TYPE__OperatorGreater", 2 }, + { "OperatorLess", "INGRESS__OPERATOR_TYPE__OperatorLess", 3 }, + { "OperatorGreaterEqual", "INGRESS__OPERATOR_TYPE__OperatorGreaterEqual", 4 }, + { "OperatorLessEqual", "INGRESS__OPERATOR_TYPE__OperatorLessEqual", 5 }, +}; +static const ProtobufCIntRange ingress__operator_type__value_ranges[] = { +{0, 0},{0, 6} +}; +static const ProtobufCEnumValueIndex ingress__operator_type__enum_values_by_name[6] = +{ + { "OperatorEqual", 1 }, + { "OperatorGreater", 2 }, + { "OperatorGreaterEqual", 4 }, + { "OperatorLess", 3 }, + { "OperatorLessEqual", 5 }, + { "OperatorUnDefined", 0 }, +}; +const ProtobufCEnumDescriptor ingress__operator_type__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "Ingress.OperatorType", + "OperatorType", + "Ingress__OperatorType", + "Ingress", + 6, + ingress__operator_type__enum_values_by_number, + 6, + ingress__operator_type__enum_values_by_name, + 1, + ingress__operator_type__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCEnumValue ingress__action_type__enum_values_by_number[6] = +{ + { "ActionUnDefined", "INGRESS__ACTION_TYPE__ActionUnDefined", 0 }, + { "ActionAddReqHeader", "INGRESS__ACTION_TYPE__ActionAddReqHeader", 1 }, + { "ActionAppendReqHeader", "INGRESS__ACTION_TYPE__ActionAppendReqHeader", 2 }, + { "ActionAddRespHeader", "INGRESS__ACTION_TYPE__ActionAddRespHeader", 3 }, + { "ActionAppendRespHeader", "INGRESS__ACTION_TYPE__ActionAppendRespHeader", 4 }, + { "ActionAddParam", "INGRESS__ACTION_TYPE__ActionAddParam", 5 }, +}; +static const ProtobufCIntRange ingress__action_type__value_ranges[] = { +{0, 0},{0, 6} +}; +static const ProtobufCEnumValueIndex ingress__action_type__enum_values_by_name[6] = +{ + { "ActionAddParam", 5 }, + { "ActionAddReqHeader", 1 }, + { "ActionAddRespHeader", 3 }, + { "ActionAppendReqHeader", 2 }, + { "ActionAppendRespHeader", 4 }, + { "ActionUnDefined", 0 }, +}; +const ProtobufCEnumDescriptor ingress__action_type__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "Ingress.ActionType", + "ActionType", + "Ingress__ActionType", + "Ingress", + 6, + ingress__action_type__enum_values_by_number, + 6, + ingress__action_type__enum_values_by_name, + 1, + ingress__action_type__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; +static const ProtobufCEnumValue ingress__action_value_type__enum_values_by_number[3] = +{ + { "ActionValueUnDefined", "INGRESS__ACTION_VALUE_TYPE__ActionValueUnDefined", 0 }, + { "ActionStaticValue", "INGRESS__ACTION_VALUE_TYPE__ActionStaticValue", 1 }, + { "ActionDynamicValue", "INGRESS__ACTION_VALUE_TYPE__ActionDynamicValue", 2 }, +}; +static const ProtobufCIntRange ingress__action_value_type__value_ranges[] = { +{0, 0},{0, 3} +}; +static const ProtobufCEnumValueIndex ingress__action_value_type__enum_values_by_name[3] = +{ + { "ActionDynamicValue", 2 }, + { "ActionStaticValue", 1 }, + { "ActionValueUnDefined", 0 }, +}; +const ProtobufCEnumDescriptor ingress__action_value_type__descriptor = +{ + PROTOBUF_C__ENUM_DESCRIPTOR_MAGIC, + "Ingress.ActionValueType", + "ActionValueType", + "Ingress__ActionValueType", + "Ingress", + 3, + ingress__action_value_type__enum_values_by_number, + 3, + ingress__action_value_type__enum_values_by_name, + 1, + ingress__action_value_type__value_ranges, + NULL,NULL,NULL,NULL /* reserved[1234] */ +}; diff --git a/modules/ngx_ingress_module/ingress.pb-c.h b/modules/ngx_ingress_module/ingress.pb-c.h index 78db7fb78f..81f3b1ea52 100644 --- a/modules/ngx_ingress_module/ingress.pb-c.h +++ b/modules/ngx_ingress_module/ingress.pb-c.h @@ -15,6 +15,8 @@ PROTOBUF_C__BEGIN_DECLS #endif +typedef struct _Ingress__TagValueStrList Ingress__TagValueStrList; +typedef struct _Ingress__TagItemCondition Ingress__TagItemCondition; typedef struct _Ingress__TagItem Ingress__TagItem; typedef struct _Ingress__TagRule Ingress__TagRule; typedef struct _Ingress__TagRouter Ingress__TagRouter; @@ -26,6 +28,7 @@ typedef struct _Ingress__Router Ingress__Router; typedef struct _Ingress__Timeout Ingress__Timeout; typedef struct _Ingress__Upstream Ingress__Upstream; typedef struct _Ingress__Metadata Ingress__Metadata; +typedef struct _Ingress__Action Ingress__Action; typedef struct _Ingress__VirtualService Ingress__VirtualService; typedef struct _Ingress__Config Ingress__Config; @@ -33,46 +36,169 @@ typedef struct _Ingress__Config Ingress__Config; /* --- enums --- */ typedef enum _Ingress__LocationType { + /* + * first element must be zero + */ + INGRESS__LOCATION_TYPE__LocUnDefined = 0, /* * Tag from http header */ - INGRESS__LOCATION_TYPE__LocHttpHeader = 0, + INGRESS__LOCATION_TYPE__LocHttpHeader = 1, + /* + * Tag from http query + */ + INGRESS__LOCATION_TYPE__LocHttpQuery = 2, /* - * Tag from http query (not supported yet) + * Tag from nginx var */ - INGRESS__LOCATION_TYPE__LocHttpQuery = 1, + INGRESS__LOCATION_TYPE__LocNginxVar = 3, /* - * Tag from nginx var (not supported yet) + * Tag from x-biz-info */ - INGRESS__LOCATION_TYPE__LocNginxVar = 2, + INGRESS__LOCATION_TYPE__LocXBizInfo = 4, /* - * Tag from x-biz-info (not supported yet) + * Tag from http cookie */ - INGRESS__LOCATION_TYPE__LocXBizInfo = 3 + INGRESS__LOCATION_TYPE__LocHttpCookie = 5 PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(INGRESS__LOCATION_TYPE) } Ingress__LocationType; typedef enum _Ingress__MatchType { /* - * String matches exactly + * first element must be zero */ - INGRESS__MATCH_TYPE__WholeMatch = 0, + INGRESS__MATCH_TYPE__MatchUnDefined = 0, /* - * Prefix matching (not supported yet) + * String matches exactly */ - INGRESS__MATCH_TYPE__PrefixMatch = 1, + INGRESS__MATCH_TYPE__WholeMatch = 1, /* - * Suffix matching (not supported yet) + * String list match */ - INGRESS__MATCH_TYPE__SuffixMatch = 2, + INGRESS__MATCH_TYPE__StrListInMatch = 2, /* - * Regex matching (not supported yet) + * mod result compare value */ - INGRESS__MATCH_TYPE__RegMatch = 3 + INGRESS__MATCH_TYPE__ModCompare = 3 PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(INGRESS__MATCH_TYPE) } Ingress__MatchType; +typedef enum _Ingress__OperatorType { + /* + * first element must be zero + */ + INGRESS__OPERATOR_TYPE__OperatorUnDefined = 0, + /* + * equal operation + */ + INGRESS__OPERATOR_TYPE__OperatorEqual = 1, + /* + * greater operation + */ + INGRESS__OPERATOR_TYPE__OperatorGreater = 2, + /* + * less operation + */ + INGRESS__OPERATOR_TYPE__OperatorLess = 3, + /* + * greater or equal + */ + INGRESS__OPERATOR_TYPE__OperatorGreaterEqual = 4, + /* + * less or equal + */ + INGRESS__OPERATOR_TYPE__OperatorLessEqual = 5 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(INGRESS__OPERATOR_TYPE) +} Ingress__OperatorType; +typedef enum _Ingress__ActionType { + /* + * first element must be zero + */ + INGRESS__ACTION_TYPE__ActionUnDefined = 0, + /* + * Action add http request header, add action do not care about duplicate + */ + INGRESS__ACTION_TYPE__ActionAddReqHeader = 1, + /* + * Action append http request header + */ + INGRESS__ACTION_TYPE__ActionAppendReqHeader = 2, + /* + * Action add http response header + */ + INGRESS__ACTION_TYPE__ActionAddRespHeader = 3, + /* + * Action append http response header + */ + INGRESS__ACTION_TYPE__ActionAppendRespHeader = 4, + /* + * Action add http request query param + */ + INGRESS__ACTION_TYPE__ActionAddParam = 5 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(INGRESS__ACTION_TYPE) +} Ingress__ActionType; +typedef enum _Ingress__ActionValueType { + /* + *first element must be zero + */ + INGRESS__ACTION_VALUE_TYPE__ActionValueUnDefined = 0, + /* + * value from configure + */ + INGRESS__ACTION_VALUE_TYPE__ActionStaticValue = 1, + /* + * value from nginx var + */ + INGRESS__ACTION_VALUE_TYPE__ActionDynamicValue = 2 + PROTOBUF_C__FORCE_ENUM_TO_BE_INT_SIZE(INGRESS__ACTION_VALUE_TYPE) +} Ingress__ActionValueType; /* --- messages --- */ +struct _Ingress__TagValueStrList +{ + ProtobufCMessage base; + /* + * string list + */ + size_t n_value; + char **value; +}; +#define INGRESS__TAG_VALUE_STR_LIST__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&ingress__tag_value_str_list__descriptor) \ + , 0,NULL } + + +struct _Ingress__TagItemCondition +{ + ProtobufCMessage base; + /* + * string match value, for WholeMatch,PrefixMatch,SuffixMatch, and RegMatch + */ + char *value_str; + /* + * string list for match, for StrListInMatch + */ + Ingress__TagValueStrList *value_list; + /* + * mode divisor, for ModCompare + */ + protobuf_c_boolean has_divisor; + uint64_t divisor; + /* + * compare remainder, for ModCompare + */ + protobuf_c_boolean has_remainder; + uint64_t remainder; + /* + * >, <, =, >=, <=, for ModCompare + */ + protobuf_c_boolean has_operator_; + Ingress__OperatorType operator_; +}; +#define INGRESS__TAG_ITEM_CONDITION__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&ingress__tag_item_condition__descriptor) \ + , NULL, NULL, 0, 0, 0, 0, 0, INGRESS__OPERATOR_TYPE__OperatorUnDefined } + + struct _Ingress__TagItem { ProtobufCMessage base; @@ -88,7 +214,7 @@ struct _Ingress__TagItem /* * The name of the value to be parsed */ - char *value; + Ingress__TagItemCondition *condition; /* * matching method */ @@ -97,7 +223,7 @@ struct _Ingress__TagItem }; #define INGRESS__TAG_ITEM__INIT \ { PROTOBUF_C_MESSAGE_INIT (&ingress__tag_item__descriptor) \ - , 0, INGRESS__LOCATION_TYPE__LocHttpHeader, NULL, NULL, 0, INGRESS__MATCH_TYPE__WholeMatch } + , 0, INGRESS__LOCATION_TYPE__LocUnDefined, NULL, NULL, 0, INGRESS__MATCH_TYPE__MatchUnDefined } struct _Ingress__TagRule @@ -233,6 +359,31 @@ struct _Ingress__Metadata , NULL, NULL } +struct _Ingress__Action +{ + ProtobufCMessage base; + /* + * action type + */ + protobuf_c_boolean has_action_type; + Ingress__ActionType action_type; + /* + * action value type + */ + protobuf_c_boolean has_value_type; + Ingress__ActionValueType value_type; + /* + * action key + */ + char *key; + /* + * action value + */ + char *value; +}; +#define INGRESS__ACTION__INIT \ + { PROTOBUF_C_MESSAGE_INIT (&ingress__action__descriptor) \ + , 0, INGRESS__ACTION_TYPE__ActionUnDefined, 0, INGRESS__ACTION_VALUE_TYPE__ActionValueUnDefined, NULL, NULL } struct _Ingress__VirtualService { ProtobufCMessage base; @@ -244,10 +395,12 @@ struct _Ingress__VirtualService protobuf_c_boolean force_https; size_t n_metadata; Ingress__Metadata **metadata; + size_t n_action; + Ingress__Action **action; }; #define INGRESS__VIRTUAL_SERVICE__INIT \ { PROTOBUF_C_MESSAGE_INIT (&ingress__virtual_service__descriptor) \ - , NULL, 0,NULL, NULL, 0, 0, 0,NULL } + , NULL, 0,NULL, NULL, 0, 0, 0,NULL, 0,NULL } struct _Ingress__Config @@ -263,6 +416,44 @@ struct _Ingress__Config , 0,NULL, 0,NULL } +/* Ingress__TagValueStrList methods */ +void ingress__tag_value_str_list__init + (Ingress__TagValueStrList *message); +size_t ingress__tag_value_str_list__get_packed_size + (const Ingress__TagValueStrList *message); +size_t ingress__tag_value_str_list__pack + (const Ingress__TagValueStrList *message, + uint8_t *out); +size_t ingress__tag_value_str_list__pack_to_buffer + (const Ingress__TagValueStrList *message, + ProtobufCBuffer *buffer); +Ingress__TagValueStrList * + ingress__tag_value_str_list__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void ingress__tag_value_str_list__free_unpacked + (Ingress__TagValueStrList *message, + ProtobufCAllocator *allocator); +/* Ingress__TagItemCondition methods */ +void ingress__tag_item_condition__init + (Ingress__TagItemCondition *message); +size_t ingress__tag_item_condition__get_packed_size + (const Ingress__TagItemCondition *message); +size_t ingress__tag_item_condition__pack + (const Ingress__TagItemCondition *message, + uint8_t *out); +size_t ingress__tag_item_condition__pack_to_buffer + (const Ingress__TagItemCondition *message, + ProtobufCBuffer *buffer); +Ingress__TagItemCondition * + ingress__tag_item_condition__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void ingress__tag_item_condition__free_unpacked + (Ingress__TagItemCondition *message, + ProtobufCAllocator *allocator); /* Ingress__TagItem methods */ void ingress__tag_item__init (Ingress__TagItem *message); @@ -472,6 +663,25 @@ Ingress__Metadata * void ingress__metadata__free_unpacked (Ingress__Metadata *message, ProtobufCAllocator *allocator); +/* Ingress__Action methods */ +void ingress__action__init + (Ingress__Action *message); +size_t ingress__action__get_packed_size + (const Ingress__Action *message); +size_t ingress__action__pack + (const Ingress__Action *message, + uint8_t *out); +size_t ingress__action__pack_to_buffer + (const Ingress__Action *message, + ProtobufCBuffer *buffer); +Ingress__Action * + ingress__action__unpack + (ProtobufCAllocator *allocator, + size_t len, + const uint8_t *data); +void ingress__action__free_unpacked + (Ingress__Action *message, + ProtobufCAllocator *allocator); /* Ingress__VirtualService methods */ void ingress__virtual_service__init (Ingress__VirtualService *message); @@ -512,6 +722,12 @@ void ingress__config__free_unpacked ProtobufCAllocator *allocator); /* --- per-message closures --- */ +typedef void (*Ingress__TagValueStrList_Closure) + (const Ingress__TagValueStrList *message, + void *closure_data); +typedef void (*Ingress__TagItemCondition_Closure) + (const Ingress__TagItemCondition *message, + void *closure_data); typedef void (*Ingress__TagItem_Closure) (const Ingress__TagItem *message, void *closure_data); @@ -545,6 +761,9 @@ typedef void (*Ingress__Upstream_Closure) typedef void (*Ingress__Metadata_Closure) (const Ingress__Metadata *message, void *closure_data); +typedef void (*Ingress__Action_Closure) + (const Ingress__Action *message, + void *closure_data); typedef void (*Ingress__VirtualService_Closure) (const Ingress__VirtualService *message, void *closure_data); @@ -559,6 +778,11 @@ typedef void (*Ingress__Config_Closure) extern const ProtobufCEnumDescriptor ingress__location_type__descriptor; extern const ProtobufCEnumDescriptor ingress__match_type__descriptor; +extern const ProtobufCEnumDescriptor ingress__operator_type__descriptor; +extern const ProtobufCEnumDescriptor ingress__action_type__descriptor; +extern const ProtobufCEnumDescriptor ingress__action_value_type__descriptor; +extern const ProtobufCMessageDescriptor ingress__tag_value_str_list__descriptor; +extern const ProtobufCMessageDescriptor ingress__tag_item_condition__descriptor; extern const ProtobufCMessageDescriptor ingress__tag_item__descriptor; extern const ProtobufCMessageDescriptor ingress__tag_rule__descriptor; extern const ProtobufCMessageDescriptor ingress__tag_router__descriptor; @@ -570,6 +794,7 @@ extern const ProtobufCMessageDescriptor ingress__router__descriptor; extern const ProtobufCMessageDescriptor ingress__timeout__descriptor; extern const ProtobufCMessageDescriptor ingress__upstream__descriptor; extern const ProtobufCMessageDescriptor ingress__metadata__descriptor; +extern const ProtobufCMessageDescriptor ingress__action__descriptor; extern const ProtobufCMessageDescriptor ingress__virtual_service__descriptor; extern const ProtobufCMessageDescriptor ingress__config__descriptor; diff --git a/modules/ngx_ingress_module/ingress.proto b/modules/ngx_ingress_module/ingress.proto index 837afc0af8..894f2311dc 100644 --- a/modules/ngx_ingress_module/ingress.proto +++ b/modules/ngx_ingress_module/ingress.proto @@ -3,24 +3,65 @@ syntax = "proto2"; package Ingress; enum LocationType { - LocHttpHeader = 0; // Tag from http header - LocHttpQuery = 1; // Tag from http query (not supported yet) - LocNginxVar = 2; // Tag from nginx var (not supported yet) - LocXBizInfo = 3; // Tag from x-biz-info (not supported yet) + LocUnDefined = 0; // first element must be zero + LocHttpHeader = 1; // Tag from http header + LocHttpQuery = 2; // Tag from http query + LocNginxVar = 3; // Tag from nginx var + LocXBizInfo = 4; // Tag from x-biz-info + LocHttpCookie = 5; // Tag from http cookie } enum MatchType { - WholeMatch = 0; // String matches exactly - PrefixMatch = 1; // Prefix matching (not supported yet) - SuffixMatch = 2; // Suffix matching (not supported yet) - RegMatch = 3; // Regex matching (not supported yet) + MatchUnDefined = 0; // first element must be zero + WholeMatch = 1; // String matches exactly + StrListInMatch = 2; // String list match + ModCompare = 3; // mod result compare value +} + +enum OperatorType { + OperatorUnDefined = 0; // first element must be zero + OperatorEqual = 1; // equal operation + OperatorGreater = 2; // greater operation + OperatorLess = 3; // less operation + OperatorGreaterEqual = 4; // greater or equal + OperatorLessEqual = 5; // less or equal +} + +enum ActionType +{ + ActionUnDefined = 0; // first element must be zero + ActionAddReqHeader = 1; // Action add http request header, add action do not care about duplicate + ActionAppendReqHeader = 2; // Action append http request header + ActionAddRespHeader = 3; // Action add http response header + ActionAppendRespHeader = 4; // Action append http response header + ActionAddParam = 5; // Action add http request query param +} + +enum ActionValueType +{ + ActionValueUnDefined = 0; //first element must be zero + ActionStaticValue = 1; // value from configure + ActionDynamicValue = 2; // value from nginx var +} + + +message TagValueStrList { + repeated string value = 1; // string list +} + +message TagItemCondition { + optional string value_str = 1; // string match value, for WholeMatch,PrefixMatch,SuffixMatch, and RegMatch + optional TagValueStrList value_list = 2; // string list for match, for StrListInMatch + optional uint64 divisor = 3; // mode divisor, for ModCompare + optional uint64 remainder = 4; // compare remainder, for ModCompare + optional OperatorType operator = 5; // >, <, =, >=, <=, for ModCompare } message TagItem { - optional LocationType location = 1; // which location to get the Tag - optional string key = 2; // The name of the key to be parsed - optional string value = 3; // The name of the value to be parsed - optional MatchType match_type =4; // matching method + optional LocationType location = 1; // which location to get the Tag + optional string key = 2; // The name of the key to be parsed + optional TagItemCondition condition = 3; // The name of the value to be parsed + optional MatchType match_type = 4; // matching method } message TagRule { @@ -87,6 +128,35 @@ message Metadata optional string value = 2; } + + +message Action +{ + optional ActionType action_type = 1; // action type + optional ActionValueType value_type = 2; // action value type + optional string key = 3; // action key + optional string value = 4; // action value + +} + +message UnitRedirect +{ + optional string from = 1; + optional string to = 2; +} +message UnitWeight +{ + optional string unit = 1; + optional uint32 weight = 2; +} + +message Unit +{ + optional string generic_unit = 1; + repeated UnitRedirect redirects = 2; + repeated UnitWeight weights = 3; +} + message VirtualService { optional string service_name = 1; @@ -97,6 +167,7 @@ message VirtualService optional bool force_https = 4; repeated Metadata metadata = 5; + repeated Action action = 6; } message Config diff --git a/modules/ngx_ingress_module/ngx_ingress_module.c b/modules/ngx_ingress_module/ngx_ingress_module.c index 23530425a4..3a0d6233e3 100644 --- a/modules/ngx_ingress_module/ngx_ingress_module.c +++ b/modules/ngx_ingress_module/ngx_ingress_module.c @@ -15,10 +15,6 @@ #include -#ifdef T_HTTP_VIPSERVER_MODULE -#include -#endif - #define NGX_INGRESS_UPDATE_INTERVAL (30 * 1000) #define NGX_INGRESS_SHM_POOL_SIZE (32 * 1024 * 1024) #define NGX_INGRESS_HASH_SIZE 1323323 @@ -27,6 +23,13 @@ #define NGX_INGRESS_CTX_VAR "__ingress_ctx__" +#define NGX_INGRESS_TAG_MATCH_SUCCESS NGX_OK +#define NGX_INGRESS_TAG_MATCH_FAIL NGX_DONE +#define NGX_INGRESS_TAG_MATCH_ERROR NGX_ERROR + +#define NGX_INGRESS_TAG_ACTION_APPEND_SEPARATOR "," +#define NGX_INGRESS_TAG_EAGLEEYE_APPEND_SEPARATOR "&" + static ngx_int_t ngx_ingress_add_variables(ngx_conf_t *cf); static ngx_int_t ngx_ingress_ctx_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static char *ngx_conf_set_ingress_gateway(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); @@ -40,6 +43,7 @@ static ngx_int_t ngx_ingress_route_target_variable(ngx_http_request_t *r, ngx_ht static ngx_int_t ngx_ingress_force_https_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_ingress_get_time_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static char *ngx_ingress_gateway_metadata(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +extern int ngx_ingress_metadata_compare(const void *c1, const void *c2); typedef struct { ngx_int_t initialized; @@ -51,7 +55,8 @@ typedef struct { ngx_msec_t read_timeout; ngx_msec_t write_timeout; - ngx_array_t metadata; /* ngx_ingress_metadata_t */ + ngx_array_t metadata; /* ngx_ingress_metadata_t */ + ngx_array_t action_a; /* ngx_ingress_action_t */ } ngx_ingress_ctx_t; /* function declare */ @@ -66,7 +71,7 @@ ngx_int_t ngx_ingress_update(ngx_cycle_t *cycle, void * context, ngx_shm_pool_t static ngx_command_t ngx_ingress_commands[] = { { ngx_string("ingress_gateway"), - NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, ngx_conf_set_ingress_gateway, NGX_HTTP_LOC_CONF_OFFSET, 0, @@ -178,7 +183,6 @@ ngx_ingress_init_main_conf(ngx_conf_t *cf, void *conf) u_char name_buf[NGX_INGRESS_GATEWAY_MAX_NAME_BUF_LEN]; size_t name_len; - ngx_ingress_gateway_t *gateway = (ngx_ingress_gateway_t *)imcf->gateways.elts; for (i = 0; i < imcf->gateways.nelts; i++) { /* check config valid */ @@ -229,6 +233,10 @@ ngx_ingress_init_main_conf(ngx_conf_t *cf, void *conf) "|ingress|register strategy ingress_app failed"); return NGX_CONF_ERROR; } + + ngx_log_error(NGX_LOG_DEBUG, cf->log, 0, + "|ingress|register strategy %V successfully|", + gateway[i].name.data); } ngx_str_t ngx_ingress_ctx_name = ngx_string(NGX_INGRESS_CTX_VAR); @@ -279,94 +287,146 @@ ngx_ingress_check_upstream_enable(ngx_ingress_service_t *service) return enable; } -#ifdef T_HTTP_VIPSERVER_MODULE - ngx_uint_t i; - ngx_ingress_upstream_t *ups = service->upstreams->elts; - for (i = 0; i < service->upstreams->nelts; i++) { - if (ngx_http_vipserver_check_dynamic_enable(ngx_cycle, &ups[i].target) == NGX_OK) { - /* If there is a successful one, return success */ - enable = 1; - break; - } - } -#else enable = 1; -#endif - return enable; } -static ngx_inline ngx_int_t -ngx_ingress_cmp_tag_value(Ingress__MatchType match_type, - ngx_str_t *value1, ngx_str_t *value2) +ngx_int_t +ngx_ingress_tag_value_compar(const void *v1, const void *v2) { - /* full string match */ - if (INGRESS__MATCH_TYPE__WholeMatch == match_type) { - - if ((value1->len == value2->len) - && (0 == ngx_strncasecmp(value1->data, value2->data, value1->len))) - { - return NGX_OK; + ngx_str_t *s1 = (ngx_str_t *)v1; + ngx_str_t *s2 = (ngx_str_t *)v2; + return ngx_comm_strcasecmp(s1, s2); +} - } else { - return NGX_ERROR; - } +ngx_int_t +ngx_ingress_tag_mod_compar(ngx_str_t *tag_value, ngx_int_t divisor, + ngx_int_t remainder, ngx_ingress_tag_operator_e op) +{ + ngx_int_t ret = NGX_INGRESS_TAG_MATCH_FAIL; + ngx_int_t mod_value = ngx_atoi(tag_value->data, tag_value->len); - /* prefix match TODO */ - } else if (INGRESS__MATCH_TYPE__PrefixMatch == match_type) { - // TODO + if (mod_value == NGX_ERROR || divisor == 0) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "|ingress|mod_value atoi error|"); + return NGX_INGRESS_TAG_MATCH_ERROR; + } + + ngx_int_t mod_r = mod_value % divisor; - /* suffix match TODO */ - } else if (INGRESS__MATCH_TYPE__SuffixMatch == match_type) { - // TODO + switch (op) { + case INGRESS__OPERATOR_TYPE__OperatorEqual: + if (mod_r == remainder) { + ret = NGX_INGRESS_TAG_MATCH_SUCCESS; + } + break; + case INGRESS__OPERATOR_TYPE__OperatorGreater: + if (mod_r > remainder) { + ret = NGX_INGRESS_TAG_MATCH_SUCCESS; + } + break; + case INGRESS__OPERATOR_TYPE__OperatorLess: + if (mod_r < remainder) { + ret = NGX_INGRESS_TAG_MATCH_SUCCESS; + } + break; + case INGRESS__OPERATOR_TYPE__OperatorGreaterEqual: + if (mod_r >= remainder) { + ret = NGX_INGRESS_TAG_MATCH_SUCCESS; + } + break; + case INGRESS__OPERATOR_TYPE__OperatorLessEqual: + if (mod_r <= remainder) { + ret = NGX_INGRESS_TAG_MATCH_SUCCESS; + } + break; + case INGRESS__OPERATOR_TYPE__OperatorUnDefined: + default: + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "|ingress|invalid op value:%d|", op); + ret = NGX_INGRESS_TAG_MATCH_ERROR; + break; + } - /* regular match TODO */ - } else if (INGRESS__MATCH_TYPE__RegMatch == match_type) { - // TODO + return ret; +} - } else { +/* + * return value: + * NGX_INGRESS_TAG_MATCH_SUCCESS means the value matched successfully + * NGX_INGRESS_TAG_MATCH_ERROR means an error occurred + * NGX_INGRESS_TAG_MATCH_FAIL means the value failed to match + */ +static ngx_inline ngx_int_t +ngx_ingress_cmp_tag_value(ngx_ingress_tag_match_type_e match_type, + ngx_ingress_tag_condition_t *p_cond, ngx_str_t *tag_value) +{ + ngx_int_t ret = NGX_INGRESS_TAG_MATCH_FAIL; + void *s_result = NULL; + switch (match_type) { + case INGRESS__MATCH_TYPE__WholeMatch: + if (ngx_comm_strcasecmp(tag_value, &p_cond->value_str) == 0) { + ret = NGX_INGRESS_TAG_MATCH_SUCCESS; + } + break; + case INGRESS__MATCH_TYPE__StrListInMatch: + s_result = ngx_shm_search_array(p_cond->value_a, tag_value, (ngx_shm_compar_func)ngx_ingress_tag_value_compar); + if (s_result != NULL) { + ret = NGX_INGRESS_TAG_MATCH_SUCCESS; + } + break; + case INGRESS__MATCH_TYPE__ModCompare: + ret = ngx_ingress_tag_mod_compar(tag_value, p_cond->divisor, p_cond->remainder, p_cond->op); + break; + case INGRESS__MATCH_TYPE__MatchUnDefined: + default: ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "|ingress|invalid match type|%d|", match_type); - return NGX_ERROR; + ret = NGX_INGRESS_TAG_MATCH_ERROR; + break; } - return NGX_ERROR; + return ret; } +/* + * function: get tag rule value from http request + * return: NGX_OK means that the tag rule's value has found + * other value means that the tag rule's value hasn't found, or there is an error + */ static ngx_inline ngx_int_t -ngx_ingress_get_req_tag_value(ngx_http_request_t *r, Ingress__LocationType location, +ngx_ingress_get_req_tag_value(ngx_http_request_t *r, ngx_ingress_tag_value_location_e location, ngx_str_t *tag_key, ngx_str_t *tag_value) { ngx_int_t ret = NGX_ERROR; - - /* Tag from HttpHeader */ - if (INGRESS__LOCATION_TYPE__LocHttpHeader == location) { - + ngx_table_elt_t *cookie; + tag_value->data = NULL; + tag_value->len = 0; + switch (location) { + case INGRESS__LOCATION_TYPE__LocHttpHeader: ret = ngx_http_header_in(r, (u_char *)tag_key->data, tag_key->len, tag_value); - - /* Tag from HttpQuery TODO */ - } else if (INGRESS__LOCATION_TYPE__LocHttpQuery == location) { - // TODO - - /* Tag from nginx var TODO */ - } else if (INGRESS__LOCATION_TYPE__LocNginxVar == location) { - // TODO - - /* Tag from x-biz-info TODO */ - } else if (INGRESS__LOCATION_TYPE__LocXBizInfo == location) { - // TODO - - } else { + break; + case INGRESS__LOCATION_TYPE__LocHttpQuery: + ret = ngx_http_arg(r, (u_char *)tag_key->data, tag_key->len, tag_value); + break; + case INGRESS__LOCATION_TYPE__LocNginxVar: + ret = NGX_ABORT; + break; + case INGRESS__LOCATION_TYPE__LocXBizInfo: + ret = NGX_ABORT; + break; + case INGRESS__LOCATION_TYPE__LocHttpCookie: + cookie = ngx_http_parse_multi_header_lines(r, r->headers_in.cookie, tag_key, tag_value); + if (cookie != NULL && tag_value->data != NULL) { + ret = NGX_OK; + } + break; + case INGRESS__LOCATION_TYPE__LocUnDefined: + default: ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "|ingress|invalid loc type|%d|", location); + ret = NGX_ERROR; + break; } - - if (ret != NGX_OK) { - tag_value->data = NULL; - tag_value->len = 0; - } - - return NGX_OK; + return ret; } static ngx_ingress_service_t * @@ -387,9 +447,12 @@ ngx_http_request_t *r, ngx_shm_array_t *tags) /* Traversing each tag rule (sorted in the array by priority), the first match is returned */ for (j = 0; j < tag_router[i].rules->nelts; j++) { + if (tag_rule[j].items->nelts == 0) { /* no items */ + continue; + } ngx_ingress_tag_item_t *tag_item = tag_rule[j].items->elts; - + /* Traversing each tag item, each item must match before returning */ for (k = 0; k < tag_rule[j].items->nelts; k++) { @@ -397,10 +460,9 @@ ngx_http_request_t *r, ngx_shm_array_t *tags) /* The request does not carry the target parameter */ if (ret != NGX_OK) { break; - } else { - ret = ngx_ingress_cmp_tag_value(tag_item[k].match_type, &tag_item[k].value, &value); - if (ret != NGX_OK) { + ret = ngx_ingress_cmp_tag_value(tag_item[k].match_type, &tag_item[k].condition, &value); + if (ret != NGX_INGRESS_TAG_MATCH_SUCCESS) { break; } } @@ -418,23 +480,42 @@ ngx_http_request_t *r, ngx_shm_array_t *tags) return service; } -static ngx_ingress_service_t * -ngx_ingress_match_service(ngx_ingress_gateway_t *gateway, ngx_http_request_t* r) +ngx_int_t +ngx_ingress_service_queue_head_insert(ngx_http_request_t *r, ngx_queue_t *head, ngx_ingress_service_t *service) +{ + ngx_ingress_service_queue_t *service_queue = ngx_pcalloc(r->pool, sizeof(ngx_ingress_service_queue_t)); + if (service_queue == NULL) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|ingress alloc service queue error|"); + return NGX_ERROR; + } + service_queue->service = service; + ngx_queue_insert_head(head, &service_queue->queue_node); + return NGX_OK; +} + +static ngx_int_t +ngx_ingress_match_service(ngx_ingress_gateway_t *gateway, ngx_http_request_t* r, ngx_queue_t *head) { ngx_uint_t i; ngx_ingress_t *current; ngx_ingress_service_t *service = NULL; ngx_ingress_host_router_t host_key; ngx_ingress_host_router_t *host_router; + ngx_int_t rc; current = ngx_strategy_get_current_slot(gateway->ingress_app); if (current == NULL) { - return NULL; + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|get ingress_app failed|"); + return NGX_ERROR; } /* request no host */ if (r->headers_in.server.len == 0) { - return NULL; + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|request no host|"); + return NGX_ERROR; } host_key.host = r->headers_in.server; @@ -452,9 +533,32 @@ ngx_ingress_match_service(ngx_ingress_gateway_t *gateway, ngx_http_request_t* r) } if (host_router == NULL) { - ngx_log_error(NGX_LOG_DEBUG, ngx_cycle->log, 0, + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "|ingress|ingress host router not found|%V|", &host_key.host); - return NULL; + return NGX_ERROR; + } + + if (host_router->service) { + rc = ngx_ingress_service_queue_head_insert(r, head, host_router->service); + if (rc != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|host service insert service queue failed|"); + return NGX_ERROR; + } + } + + + /* if host route has tag router, match */ + if (host_router->tags) { + service = ngx_ingress_get_tag_match_service(gateway, r, host_router->tags); + if (service) { + rc = ngx_ingress_service_queue_head_insert(r, head, service); + if (rc != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|host tag service insert service queue failed|"); + return NGX_ERROR; + } + } } /* match path */ @@ -462,36 +566,40 @@ ngx_ingress_match_service(ngx_ingress_gateway_t *gateway, ngx_http_request_t* r) for (i = 0; i < host_router->paths->nelts; i++) { if (ngx_comm_prefix_casecmp(&r->uri, &path_router[i].prefix) == 0) { ngx_log_error(NGX_LOG_DEBUG, ngx_cycle->log, 0, - "|ingress|match prefix prefix|%V|%V|", - &host_key.host, - &r->uri); + "|ingress|match prefix prefix|%V|%V|", + &host_key.host, + &r->uri); + if (ngx_ingress_check_upstream_enable(path_router[i].service)) { + rc = ngx_ingress_service_queue_head_insert(r, head, path_router[i].service); + if (rc != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|path service insert service queue failed|"); + return NGX_ERROR; + } + } + /* if path route has tag router, match first */ if (path_router[i].tags) { service = ngx_ingress_get_tag_match_service(gateway, r, path_router[i].tags); if (service) { - return service; + rc = ngx_ingress_service_queue_head_insert(r, head, service); + if (rc != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|path service with tag insert service queue failed|"); + return NGX_ERROR; + } } } - - if (ngx_ingress_check_upstream_enable(path_router[i].service)) { - return path_router[i].service; - } - } - } - - /* if host route has tag router, match first */ - if (host_router->tags) { - service = ngx_ingress_get_tag_match_service(gateway, r, host_router->tags); - if (service) { - return service; + + break; } } ngx_log_error(NGX_LOG_DEBUG, ngx_cycle->log, 0, "|ingress|match host|%V|%V|", &host_key.host, &r->uri); - return host_router->service; + return NGX_OK; } @@ -904,45 +1012,336 @@ ngx_ingress_gateway_shm_config(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) } static ngx_int_t -ngx_ingress_init_ctx(ngx_ingress_ctx_t *ctx, ngx_http_request_t *r) +ngx_ingress_service_get_value_from_nginx_var(ngx_http_request_t *r, ngx_str_t *key, + ngx_str_t *var_value) { - ngx_ingress_loc_conf_t *ilcf = NULL; - ngx_ingress_upstream_t *ups; - ngx_int_t ups_index; - ngx_int_t rc; - ngx_uint_t i; + ngx_str_t var_name; + u_char *p_strlow = ngx_pnalloc(r->pool, key->len); + if (p_strlow == NULL) { + return NGX_ERROR; + } + ngx_uint_t hash = ngx_hash_strlow(p_strlow, key->data, key->len); + var_name.data = p_strlow; + var_name.len = key->len; + ngx_http_variable_value_t *vv = ngx_http_get_variable(r, &var_name, hash); - ilcf = ngx_http_get_module_loc_conf(r, ngx_ingress_module); - if (ilcf->gateway == NULL) { - return NGX_DECLINED; + if (vv == NULL || vv->not_found || vv->len == 0) { + return NGX_ERROR; } - ngx_ingress_service_t *service = ngx_ingress_match_service(ilcf->gateway, r); - if (service == NULL) { - ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, - "|ingress|route service not found|"); - return NGX_DECLINED; + var_value->len = vv->len; + var_value->data = vv->data; + return NGX_OK; +} + +/* + * add header, if header key which add already exists in request, + * this fuction will add a new header with the same key + */ +static ngx_int_t +ngx_ingress_service_request_add_header(ngx_http_request_t *r, ngx_str_t *key, + ngx_str_t *value) +{ + ngx_table_elt_t *h; + h = ngx_list_push(&r->headers_in.headers); + if (h == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|ingress add header push headers error|"); + return NGX_ERROR; } - /* assign target */ - if (service->upstreams == NULL || service->upstreams->nelts == 0) { - ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, - "|ingress|route service no upstream|"); + h->key.len = key->len; + h->key.data = key->data; + h->hash = ngx_hash_key_lc(h->key.data, h->key.len); + + h->lowcase_key = ngx_pnalloc(r->pool, h->key.len); + if (h->lowcase_key == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|ingress add header alloc error|"); + ngx_list_delete(&r->headers_in.headers, h); return NGX_ERROR; } + ngx_strlow(h->lowcase_key, key->data, key->len); - ups = service->upstreams->elts; - ups_index = 0; - if (service->upstream_weight != 0) { - ngx_int_t offset = ngx_random() % service->upstream_weight; - ngx_uint_t i; + h->value.data = value->data; + h->value.len = value->len; - ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, - "|ingress|weight target|%i|%i|%i|", service->upstream_weight, offset, service->upstreams->nelts); - for (i = 0; i < service->upstreams->nelts; i++) { + return NGX_OK; +} + +/* + * If header key exists in the request, value will be appended + * otherwise, new header will be added to the request + * Based on RFC2616, the multiple message-header fields with the same field-name + * MAY be present in a message if and only if the entire field-value for that + * header field is defined as a comma-separated list [i.e., #(values)]. + * For the header Eagleeye-UserData, the APPEND_SEPARATOR will use '&' specifically. + */ +static ngx_int_t +ngx_ingress_service_request_append_header(ngx_http_request_t *r, ngx_str_t *key, + ngx_str_t *value) +{ + ngx_uint_t i, hash, tag_len; + ngx_table_elt_t *h; + ngx_list_part_t *part; + ngx_str_t new_value = ngx_null_string; + u_char *p = NULL; + ngx_int_t rc; + + if (value->len == 0) { + return NGX_OK; + } + + part = &r->headers_in.headers.part; + h = part->elts; + hash = ngx_hash_key_lc(key->data, key->len); + + for (i = 0; /* void */; i++) { + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + part = part->next; + h = part->elts; + i = 0; + } + + if (hash == h[i].hash + && key->len == h[i].key.len + && ngx_strncasecmp(key->data, h[i].lowcase_key, key->len) == 0) + { + tag_len = sizeof(NGX_INGRESS_TAG_ACTION_APPEND_SEPARATOR) - 1; + new_value.len = h[i].value.len + value->len + tag_len; + new_value.data = ngx_pnalloc(r->pool, new_value.len); + if (new_value.data == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|ingress append header alloc error|"); + return NGX_ERROR; + } + + p = ngx_copy(new_value.data, h[i].value.data, h[i].value.len); + p = ngx_copy(p, NGX_INGRESS_TAG_ACTION_APPEND_SEPARATOR, tag_len); + p = ngx_copy(p, value->data, value->len); + h[i].value.data = new_value.data; + h[i].value.len = new_value.len; + return NGX_OK; + } + } + + /* match failed */ + rc = ngx_ingress_service_request_add_header(r, key, value); + if (rc != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|ingress append header do add error|"); + return NGX_ERROR; + } + + return NGX_OK; +} + +static ngx_int_t +ngx_ingress_service_response_add_header(ngx_http_request_t *r, ngx_str_t *key, + ngx_str_t *value) +{ + ngx_table_elt_t *h; + h = ngx_list_push(&r->headers_out.headers); + if (h == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|ingress do action push headers_out error|"); + return NGX_ERROR; + } + + h->hash = 1; + h->key = *key; + h->value = *value; + + return NGX_OK; +} + +/* + * add param: no matter the key is exist in the query or not + * add action append 'key=value' at the end of the query + * + */ +static ngx_int_t +ngx_ingress_service_query_add_param(ngx_http_request_t *r, ngx_str_t *key, ngx_str_t *value) +{ + u_char *p; + ngx_str_t new_unparsed_uri = ngx_null_string; + new_unparsed_uri.len = r->unparsed_uri.len + key->len + value->len + 2; + new_unparsed_uri.data = ngx_pnalloc(r->pool, new_unparsed_uri.len); + if (new_unparsed_uri.data == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|ingress action add param alloc error|"); + return NGX_ERROR; + } + + if (r->args.len == 0) { + p = ngx_copy(new_unparsed_uri.data, r->unparsed_uri.data, r->unparsed_uri.len); + p = ngx_copy(p, "?", 1); + p = ngx_copy(p, key->data, key->len); + p = ngx_copy(p, "=", 1); + p = ngx_copy(p, value->data, value->len); + } else { + p = ngx_copy(new_unparsed_uri.data, r->unparsed_uri.data, r->unparsed_uri.len); + p = ngx_copy(p, "&", 1); + p = ngx_copy(p, key->data, key->len); + p = ngx_copy(p, "=", 1); + p = ngx_copy(p, value->data, value->len); + } + + r->unparsed_uri.data = new_unparsed_uri.data; + r->unparsed_uri.len = new_unparsed_uri.len; + return NGX_OK; +} + +static ngx_int_t +ngx_ingress_service_do_action(ngx_http_request_t *r, ngx_ingress_action_t *action) +{ + ngx_int_t rc = NGX_ERROR; + ngx_str_t value = ngx_null_string, key = ngx_null_string; + + if (action->key.data == NULL || action->key.len == 0 + || action->value.len == 0 || action->value.data == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|ingress action key or value NULL|"); + return NGX_ERROR; + } + + key.data = action->key.data; + key.len = action->key.len; + + switch (action->value_type) { + case INGRESS__ACTION_VALUE_TYPE__ActionValueUnDefined: + /* action value type not defined */ + break; + case INGRESS__ACTION_VALUE_TYPE__ActionStaticValue: + value.data = action->value.data; + value.len = action->value.len; + break; + case INGRESS__ACTION_VALUE_TYPE__ActionDynamicValue: + rc = ngx_ingress_service_get_value_from_nginx_var(r, &action->value, &value); + if (rc != NGX_OK || value.len == 0 || value.data == NULL ) { + ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, + "|ingress|ingress find nginx var failed, %V|", &action->value); + return NGX_OK; /* nginx var not found is not error */ + } + break; + default: + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|ingress action value type error|"); + return NGX_ERROR; + } + + switch (action->action_type) { + case INGRESS__ACTION_TYPE__ActionAddReqHeader: + if (value.len == 0 || value.data == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|ingress action add req header value invalid|"); + return NGX_ERROR;; + } + + rc = ngx_ingress_service_request_add_header(r, &key, &value); + break; + case INGRESS__ACTION_TYPE__ActionAppendReqHeader: + if (value.len == 0 || value.data == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|ingress action append req header value invalid|"); + return NGX_ERROR; + } + + rc = ngx_ingress_service_request_append_header(r, &key, &value); + break; + case INGRESS__ACTION_TYPE__ActionAddRespHeader: + if (value.len == 0 || value.data == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|ingress action add resp header value invalid|"); + break; + } + + rc = ngx_ingress_service_response_add_header(r, &key, &value); + break; + case INGRESS__ACTION_TYPE__ActionAddParam: + if (value.len == 0 || value.data == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|ingress action add param value invalid|"); + break; + } + + rc = ngx_ingress_service_query_add_param(r, &key, &value); + break; + case INGRESS__ACTION_TYPE__ActionUnDefined: + default: + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|ingress action type invalid|"); + return NGX_ERROR; + } + + return rc; +} + +ngx_int_t +ngx_ingress_read_value_from_service_queue(ngx_ingress_ctx_t *ctx, + ngx_http_request_t *r, ngx_queue_t *head) + +{ + ngx_ingress_service_t *target_service = NULL; + ngx_ingress_service_t *timeout_service = NULL; + ngx_ingress_service_t *force_https_service = NULL; + ngx_ingress_service_t *action_service = NULL; + ngx_int_t action_num = 0; + ngx_int_t metadata_num = 0; + ngx_int_t rc; + ngx_queue_t *node; + for (node = ngx_queue_head(head); node != ngx_queue_sentinel(head); node = ngx_queue_next(node)) { + ngx_ingress_service_queue_t *service_queue = + ngx_queue_data(node, ngx_ingress_service_queue_t, queue_node); + if (service_queue->service == NULL) { + continue; + } + if (service_queue->service->metadata->nelts > 0) { + metadata_num += service_queue->service->metadata->nelts; + } + + if (service_queue->service->upstreams != NULL + && service_queue->service->upstreams->nelts > 0 + && target_service == NULL) { + target_service = service_queue->service; + } + + if (service_queue->service->timeout.set_flag == NGX_INGRESS_TIMEOUT_SET + && timeout_service == NULL) { + timeout_service = service_queue->service; + } + + if (service_queue->service->force_https != NGX_INGRESS_FORCE_HTTPS_UNSET + && force_https_service == NULL) { + force_https_service = service_queue->service; + } + + if (service_queue->service->action_a != NULL + && service_queue->service->action_a->nelts > 0 + && action_service == NULL) { + action_num += service_queue->service->action_a->nelts; + action_service = service_queue->service; + } + } + + if (target_service == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|get target from service queue error|"); + /* some api may match host service without target, no need match again, so return declined */ + return NGX_DECLINED; + } + + ngx_ingress_upstream_t *ups = target_service->upstreams->elts; + ngx_int_t ups_index = 0; + if (target_service->upstream_weight != 0) { + ngx_int_t offset = ngx_random() % target_service->upstream_weight; + for (ngx_uint_t i = 0; i < target_service->upstreams->nelts; i++) { if (ups[i].start <= offset && ups[i].end > offset) { ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, - "|ingress|hit weight target|%i|%V|", ups_index, &ups[ups_index].target); + "|ingress|hit weight target|%i|%V|", ups_index, &ups[ups_index].target); ups_index = i; break; } @@ -958,46 +1357,145 @@ ngx_ingress_init_ctx(ngx_ingress_ctx_t *ctx, ngx_http_request_t *r) } ngx_memcpy(ctx->target.data, ups[ups_index].target.data, ctx->target.len); - /* assign force https */ - ctx->force_https = service->force_https; + if (timeout_service != NULL) { + ctx->connect_timeout = timeout_service->timeout.connect_timeout; + ctx->write_timeout = timeout_service->timeout.write_timeout; + ctx->read_timeout = timeout_service->timeout.read_timeout; + } else { /* timeout unset, default value 0 */ + ctx->connect_timeout = 0; + ctx->write_timeout = 0; + ctx->read_timeout = 0; + } - ctx->connect_timeout = service->timeout.connect_timeout; - ctx->write_timeout = service->timeout.write_timeout; - ctx->read_timeout = service->timeout.read_timeout; + if (force_https_service != NULL) { + ctx->force_https = force_https_service->force_https; + } else { + ctx->force_https = 0; + } - rc = ngx_array_init(&ctx->metadata, r->pool, service->metadata->nelts, sizeof(ngx_ingress_metadata_t)); + rc = ngx_array_init(&ctx->action_a, r->pool, action_num, + sizeof(ngx_ingress_action_t)); + if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "|ingress|init ctx metadata array failed|"); + "|ingress|init ctx alloc action array failed|"); return NGX_ERROR; } - ngx_ingress_metadata_t *shm_metas = service->metadata->elts; - for (i = 0; i < service->metadata->nelts; i++) { - ngx_ingress_metadata_t *metadata = ngx_array_push(&ctx->metadata); - if (metadata == NULL) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "|ingress|init ctx push metadata failed|"); - return NGX_ERROR; + if (action_service != NULL) { + ngx_ingress_action_t *shm_action = action_service->action_a->elts; + for (ngx_uint_t i = 0; i < action_service->action_a->nelts; i++) { + ngx_ingress_action_t *action = ngx_array_push(&ctx->action_a); + if (action == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|init ctx alloc action failed|"); + return NGX_ERROR; + } + + action->action_type = shm_action[i].action_type; + action->value_type = shm_action[i].value_type; + + action->key.data = ngx_palloc(r->pool, shm_action[i].key.len); + if (action->key.data == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|init ctx alloc action key failed:%d|", shm_action[i].key.len); + return NGX_ERROR; + } + ngx_memcpy(action->key.data, shm_action[i].key.data, shm_action[i].key.len); + action->key.len = shm_action[i].key.len; + + action->value.data = ngx_palloc(r->pool, shm_action[i].value.len); + if (action->value.data == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|init ctx alloc action value failed:%d|", shm_action[i].value.len); + return NGX_ERROR; + } + ngx_memcpy(action->value.data, shm_action[i].value.data, shm_action[i].value.len); + action->value.len = shm_action[i].value.len; } + } - metadata->key.data = ngx_palloc(r->pool, shm_metas[i].key.len); - if (metadata->key.data == NULL) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "|ingress|init ctx alloc meta key failed|"); - return NGX_ERROR; + rc = ngx_array_init(&ctx->metadata, r->pool, metadata_num, sizeof(ngx_ingress_metadata_t)); + if (rc != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|init ctx metadata array failed|"); + return NGX_ERROR; + } + + for (node = ngx_queue_head(head); node != ngx_queue_sentinel(head); node = ngx_queue_next(node)) { + ngx_ingress_service_queue_t *service_queue = + ngx_queue_data(node, ngx_ingress_service_queue_t, queue_node); + if (service_queue->service == NULL) { + continue; } - ngx_memcpy(metadata->key.data, shm_metas[i].key.data, shm_metas[i].key.len); - metadata->key.len = shm_metas[i].key.len; + ngx_ingress_metadata_t *shm_metas = service_queue->service->metadata->elts; + for (ngx_uint_t i = 0; i < service_queue->service->metadata->nelts; i++) { + ngx_ingress_metadata_t *metadata = ngx_array_push(&ctx->metadata); + if (metadata == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|init ctx push metadata failed|"); + return NGX_ERROR; + } - metadata->value.data = ngx_palloc(r->pool, shm_metas[i].value.len); - if (metadata->value.data == NULL) { - ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, - "|ingress|init ctx alloc meta value failed|"); - return NGX_ERROR; + metadata->key.data = ngx_palloc(r->pool, shm_metas[i].key.len); + if (metadata->key.data == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|init ctx alloc meta key failed|"); + return NGX_ERROR; + } + ngx_memcpy(metadata->key.data, shm_metas[i].key.data, shm_metas[i].key.len); + metadata->key.len = shm_metas[i].key.len; + + metadata->value.data = ngx_palloc(r->pool, shm_metas[i].value.len); + if (metadata->value.data == NULL) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|init ctx alloc meta value failed|"); + return NGX_ERROR; + } + ngx_memcpy(metadata->value.data, shm_metas[i].value.data, shm_metas[i].value.len); + metadata->value.len = shm_metas[i].value.len; } - ngx_memcpy(metadata->value.data, shm_metas[i].value.data, shm_metas[i].value.len); - metadata->value.len = shm_metas[i].value.len; + } + if (metadata_num > 0) { + qsort(ctx->metadata.elts, ctx->metadata.nelts, ctx->metadata.size, ngx_ingress_metadata_compare); + } + + return NGX_OK; +} + +/* + * return NGX_ERROR: may match again + * return NGX_DECLINED: no need to match again + */ + +static ngx_int_t +ngx_ingress_init_ctx(ngx_ingress_ctx_t *ctx, ngx_http_request_t *r) +{ + ngx_ingress_loc_conf_t *ilcf = NULL; + ngx_int_t rc; + + ilcf = ngx_http_get_module_loc_conf(r, ngx_ingress_module); + if (ilcf->gateway == NULL) { + return NGX_DECLINED; + } + + ngx_queue_t service_head; + ngx_queue_init(&service_head); + + rc = ngx_ingress_match_service(ilcf->gateway, r, &service_head); + if (rc != NGX_OK || ngx_queue_empty(&service_head)) { + ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, + "|ingress|route service not found|"); + + /* not found probably, no need to match again */ + return NGX_DECLINED; + } + + rc = ngx_ingress_read_value_from_service_queue(ctx, r, &service_head); + if (rc != NGX_OK) { + ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0, + "|ingress|read value from service queue failed|"); + return rc; } return NGX_OK; @@ -1010,6 +1508,7 @@ ngx_ingress_get_ctx(ngx_ingress_main_conf_t *imcf, ngx_ingress_ctx_t *ctx = NULL; ngx_http_variable_value_t *vv; ngx_int_t rc; + ngx_uint_t i; ctx = ngx_http_get_module_ctx(r, ngx_ingress_module); if (ctx != NULL) { @@ -1034,8 +1533,24 @@ ngx_ingress_get_ctx(ngx_ingress_main_conf_t *imcf, "|ingress|init ctx failed|"); return NULL; } - - ctx->initialized = 1; + ctx->initialized = 1; /* initialized flag 1 indicates no need to match again */ + + if (rc == NGX_OK && ctx->action_a.nelts > 0) { + /* + * action should do while ctx->initialized equal 1, + * so it can avoid to do action duplicately + */ + ngx_ingress_action_t *action = ctx->action_a.elts; + for (i = 0; i < ctx->action_a.nelts; i++) { + rc = ngx_ingress_service_do_action(r, &action[i]); + if (rc != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "|ingress|ingress service do action error|"); + /* just log error */ + } + } + } + } return ctx; @@ -1150,7 +1665,6 @@ typedef struct { ngx_str_t key; } ngx_ingress_metadata_ctx_t; -extern int ngx_ingress_metadata_compare(const void *c1, const void *c2); static ngx_int_t ngx_ingress_gateway_metadata_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, diff --git a/modules/ngx_ingress_module/ngx_ingress_module.h b/modules/ngx_ingress_module/ngx_ingress_module.h index 27a39bb453..9fb3e788d6 100644 --- a/modules/ngx_ingress_module/ngx_ingress_module.h +++ b/modules/ngx_ingress_module/ngx_ingress_module.h @@ -14,10 +14,15 @@ #include #include +#define NGX_INGRESS_FORCE_HTTPS_UNSET -1 +#define NGX_INGRESS_TIMEOUT_UNSET 0 +#define NGX_INGRESS_TIMEOUT_SET 1 + typedef struct { ngx_msec_t connect_timeout; ngx_msec_t read_timeout; ngx_msec_t write_timeout; + ngx_int_t set_flag; } ngx_ingress_timeout_t; typedef struct { @@ -32,6 +37,27 @@ typedef struct { ngx_str_t value; } ngx_ingress_metadata_t; +typedef Ingress__LocationType ngx_ingress_tag_value_location_e; +typedef Ingress__MatchType ngx_ingress_tag_match_type_e; +typedef Ingress__OperatorType ngx_ingress_tag_operator_e; +typedef Ingress__ActionType ngx_ingress_action_type_e; +typedef Ingress__ActionValueType ngx_ingress_action_value_type_e; + +typedef struct { + ngx_str_t value_str; + ngx_shm_array_t *value_a; /* ngx_str_t, already sorted */ + ngx_int_t divisor; + ngx_int_t remainder; + ngx_ingress_tag_operator_e op; +} ngx_ingress_tag_condition_t; + +typedef struct { + ngx_ingress_action_type_e action_type; + ngx_ingress_action_value_type_e value_type; + ngx_str_t key; + ngx_str_t value; +} ngx_ingress_action_t; + typedef struct { ngx_str_t name; @@ -41,14 +67,21 @@ typedef struct { ngx_ingress_timeout_t timeout; ngx_int_t force_https; + ngx_shm_array_t *action_a; /* ngx_ingress_action_t */ + ngx_shm_array_t *metadata; /* ngx_ingress_metadata_t */ } ngx_ingress_service_t; typedef struct { - Ingress__LocationType location; /* match field location */ - ngx_str_t key; /* match field name */ - ngx_str_t value; /* match field value */ - Ingress__MatchType match_type; /* match field type */ + ngx_queue_t queue_node; + ngx_ingress_service_t *service; +} ngx_ingress_service_queue_t; + +typedef struct { + ngx_ingress_tag_value_location_e location; /* match field location */ + ngx_str_t key; /* match field name */ + ngx_ingress_tag_match_type_e match_type; /* match field type */ + ngx_ingress_tag_condition_t condition; /* match condition */ } ngx_ingress_tag_item_t; typedef struct { @@ -115,6 +148,6 @@ typedef struct { ngx_int_t ngx_ingress_update_shm_by_pb(ngx_ingress_gateway_t *gateway, ngx_ingress_shared_memory_config_t *shm_pb_config, ngx_ingress_t *ingress); - +ngx_int_t ngx_ingress_tag_value_compar(const void *v1, const void *v2); #endif // NGX_INGRESS_MODULE_H diff --git a/modules/ngx_ingress_module/ngx_ingress_protobuf.c b/modules/ngx_ingress_module/ngx_ingress_protobuf.c index 364ababfa0..4f3d85429d 100644 --- a/modules/ngx_ingress_module/ngx_ingress_protobuf.c +++ b/modules/ngx_ingress_module/ngx_ingress_protobuf.c @@ -327,6 +327,84 @@ ngx_ingress_metadata_compare(const void *c1, const void *c2) return ngx_comm_str_compare(&meta1->key, &meta2->key); } +static ngx_int_t +ngx_ingress_service_action_data_check(ngx_ingress_action_t *action) +{ + ngx_int_t rc = NGX_ERROR; + switch (action->action_type) { + case INGRESS__ACTION_TYPE__ActionAddReqHeader: + case INGRESS__ACTION_TYPE__ActionAppendReqHeader: + case INGRESS__ACTION_TYPE__ActionAddRespHeader: + case INGRESS__ACTION_TYPE__ActionAppendRespHeader: + case INGRESS__ACTION_TYPE__ActionAddParam: + switch (action->value_type) { + case INGRESS__ACTION_VALUE_TYPE__ActionStaticValue: + case INGRESS__ACTION_VALUE_TYPE__ActionDynamicValue: + if (action->key.data != NULL && action->value.data != NULL) { + rc = NGX_OK; + } else { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|service action value or key NULL|"); + } + break; + case INGRESS__ACTION_VALUE_TYPE__ActionValueUnDefined: + default: + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "|ingress|service action value type error|"); + break; + } + break; + case INGRESS__ACTION_TYPE__ActionUnDefined: + default: + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "|ingress|service action type error|"); + break; + } + return rc; +} + +static ngx_int_t +ngx_ingress_service_parse_action(ngx_ingress_t *ingress, + ngx_ingress_action_t *shm_action, Ingress__Action *pb_action) +{ + ngx_memset(shm_action, 0, sizeof(ngx_ingress_action_t)); + shm_action->action_type = pb_action->action_type; + if (pb_action->has_value_type) { + shm_action->value_type = pb_action->value_type; + } + if (pb_action->key != NULL && ngx_strlen(pb_action->key) != 0) { + shm_action->key.len = ngx_strlen(pb_action->key); + shm_action->key.data + = ngx_shm_pool_calloc(ingress->pool, shm_action->key.len); + if (shm_action->key.data == NULL) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|alloc action key error, len:%d|", shm_action->key.len); + return NGX_ERROR; + } + ngx_memcpy(shm_action->key.data, pb_action->key, shm_action->key.len); + } + + if (pb_action->value != NULL && ngx_strlen(pb_action->value) != 0) { + shm_action->value.len = ngx_strlen(pb_action->value); + shm_action->value.data = + ngx_shm_pool_calloc(ingress->pool, shm_action->value.len); + + if (shm_action->value.data == NULL) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|alloc action value error, len:%d|", + shm_action->value.len); + return NGX_ERROR; + } + ngx_memcpy(shm_action->value.data, pb_action->value, shm_action->value.len); + } + + if (ngx_ingress_service_action_data_check(shm_action) != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|action data check error|"); + return NGX_ERROR; + } + + return NGX_OK; +} + static ngx_int_t ngx_ingress_update_shm_service(ngx_ingress_t *ingress, ngx_ingress_service_t *shm_service, @@ -356,10 +434,13 @@ ngx_ingress_update_shm_service(ngx_ingress_t *ingress, /* force https */ if (pbservice->has_force_https) { shm_service->force_https = pbservice->force_https; + } else { + shm_service->force_https = NGX_INGRESS_FORCE_HTTPS_UNSET; } - + /* timeout */ if (pbservice->timeout_ms != NULL) { + shm_service->timeout.set_flag = NGX_INGRESS_TIMEOUT_SET; if (pbservice->timeout_ms->has_connect_timeout) { shm_service->timeout.connect_timeout = pbservice->timeout_ms->connect_timeout; } else { @@ -377,6 +458,8 @@ ngx_ingress_update_shm_service(ngx_ingress_t *ingress, } else { shm_service->timeout.write_timeout = NGX_CONF_UNSET_MSEC; } + } else { + shm_service->timeout.set_flag = NGX_INGRESS_TIMEOUT_UNSET; } /* upstreams */ @@ -477,6 +560,37 @@ ngx_ingress_update_shm_service(ngx_ingress_t *ingress, ngx_memcpy(metadata->value.data, pb_metadata[i]->value, len); } + shm_service->action_a = ngx_shm_array_create(ingress->pool, + pbservice->n_action, sizeof(ngx_ingress_action_t)); + if (shm_service->action_a == NULL) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|alloc action_a failed|service=%V|", &shm_service->name); + return NGX_ERROR; + } + + Ingress__Action **pb_action_a = pbservice->action; + for (i = 0; i < pbservice->n_action; i++) { + ngx_ingress_action_t *shm_action = ngx_shm_array_push(shm_service->action_a); + if (shm_action == NULL) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|push action_a failed|service=%V|", &shm_service->name); + return NGX_ERROR; + } + if (pb_action_a[i]->has_action_type) { + if (ngx_ingress_service_parse_action(ingress, shm_action, pb_action_a[i]) != NGX_OK) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|parse action error|service=%V|", &shm_service->name); + return NGX_ERROR; + } + } else { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|action type null|service=%V|", &shm_service->name); + + return NGX_ERROR; + } + + } + ngx_shm_sort_array(shm_service->metadata, ngx_ingress_metadata_compare); return NGX_OK; @@ -498,6 +612,157 @@ ngx_path_prefix_compare(const void *c1, const void *c2) return ngx_comm_str_compare(&router1->prefix, &router2->prefix); } + +/* + * this function check the tag item's data when reading configuration. + */ +static ngx_int_t +ngx_ingress_pb_tag_item_data_check(ngx_ingress_tag_item_t *item) +{ + ngx_int_t ret = NGX_ERROR; + switch (item->match_type) { + case INGRESS__MATCH_TYPE__MatchUnDefined: + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|tag item match type invalid|"); + break; + case INGRESS__MATCH_TYPE__WholeMatch: + if (item->condition.value_str.data == NULL || item->condition.value_str.len == 0) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|tag item condition value_str invalid|"); + break; + } + ret = NGX_OK; + break; + case INGRESS__MATCH_TYPE__StrListInMatch: + if (item->condition.value_a == NULL || item->condition.value_a->nelts == 0) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|tag item condition value_a invalid|"); + break; + } + ret = NGX_OK; + break; + case INGRESS__MATCH_TYPE__ModCompare: + if (item->condition.divisor == 0 + || item->condition.op == INGRESS__OPERATOR_TYPE__OperatorUnDefined) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|tag item condition divisor or operator invalid|"); + break; + } + ret = NGX_OK; + break; + default: + break; + } + + return ret; +} + +static ngx_int_t +ngx_ingress_pb_parse_tag_condition(ngx_ingress_t *ingress, + ngx_ingress_tag_condition_t *cond, Ingress__TagItemCondition *pb_cond) +{ + ngx_uint_t i = 0; + if (pb_cond->value_str != NULL && strlen(pb_cond->value_str) > 0) { + cond->value_str.len = strlen(pb_cond->value_str); + cond->value_str.data = ngx_shm_pool_calloc(ingress->pool, cond->value_str.len); + if (cond->value_str.data == NULL) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|tag condition value_str alloc error, len:%d|", cond->value_str.len); + return NGX_ERROR; + } + ngx_memcpy(cond->value_str.data, pb_cond->value_str, cond->value_str.len); + } + + if (pb_cond->value_list != NULL && pb_cond->value_list->n_value > 0) { + cond->value_a = ngx_shm_array_create(ingress->pool, + pb_cond->value_list->n_value, sizeof(ngx_str_t)); + if (cond->value_a == NULL) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|tag condition value_a alloc error, n_value:%d", pb_cond->value_list->n_value); + return NGX_ERROR; + } + for (i = 0; i < pb_cond->value_list->n_value; i++) { + char *p_v = pb_cond->value_list->value[i]; + if (p_v == NULL || strlen(p_v) == 0) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|tag condition value_list str NULL|"); + return NGX_ERROR; + } + + ngx_str_t *v_str = ngx_shm_array_push(cond->value_a); + if (v_str == NULL) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|tag condition value_a push error|"); + return NGX_ERROR; + } + v_str->len = strlen(p_v); + v_str->data = ngx_shm_pool_calloc(ingress->pool, v_str->len); + if (v_str->data == NULL) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|tag condition value alloc error, len:%d|", v_str->len); + return NGX_ERROR; + } + ngx_memcpy(v_str->data, p_v, v_str->len); + } + ngx_shm_sort_array(cond->value_a, (ngx_shm_compar_func)ngx_ingress_tag_value_compar); + } + + if (pb_cond->has_divisor) { + cond->divisor = pb_cond->divisor; + } + + if (pb_cond->has_remainder) { + cond->remainder = pb_cond->remainder; + } + + if (pb_cond->has_operator_) { + cond->op = pb_cond->operator_; + } + + return NGX_OK; +} + +static ngx_int_t +ngx_ingress_pb_parse_tag_item(ngx_ingress_t *ingress, + ngx_ingress_tag_item_t *shm_item, Ingress__TagItem *pb_item) +{ + shm_item->location = pb_item->location; + shm_item->match_type = pb_item->match_type; + + /* parse key from pb */ + if (pb_item->key == NULL || ngx_strlen(pb_item->key) == 0) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|tag itme key NULL|"); + return NGX_ERROR; + } + shm_item->key.len = ngx_strlen(pb_item->key); + shm_item->key.data = ngx_shm_pool_calloc(ingress->pool, shm_item->key.len); + if (shm_item->key.data == NULL) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|tag item key alloc error, key len:%d|", shm_item->key.len); + return NGX_ERROR; + } + ngx_memcpy(shm_item->key.data, pb_item->key, shm_item->key.len); + + /* parse condition from pb */ + if (pb_item->condition == NULL) { + ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, + "|ingress|tag itme condition NULL|"); + return NGX_ERROR; + } + + if (ngx_ingress_pb_parse_tag_condition(ingress, &shm_item->condition, + pb_item->condition) != NGX_OK) { + return NGX_ERROR; + } + + if (ngx_ingress_pb_tag_item_data_check(shm_item) != NGX_OK) { + return NGX_ERROR; + } + + return NGX_OK; +} + static ngx_int_t ngx_ingress_update_shm_tag_routers(ngx_ingress_t *ingress, size_t n_tags, Ingress__TagRouter **pb_tag_routers, @@ -505,7 +770,6 @@ ngx_ingress_update_shm_tag_routers(ngx_ingress_t *ingress, { size_t i, j, k; ngx_shm_array_t *ptags = NULL; - ngx_int_t key_len, value_len; #if 0 @@ -626,31 +890,13 @@ ngx_ingress_update_shm_tag_routers(ngx_ingress_t *ingress, "|ingress|tag item alloc failed|"); return NGX_ERROR; } + ngx_memset(shm_item, 0, sizeof(ngx_ingress_tag_item_t)); if (pb_items[k]->has_location && pb_items[k]->has_match_type) { - - shm_item->location = pb_items[k]->location; - shm_item->match_type = pb_items[k]->match_type; - - key_len = strlen(pb_items[k]->key); - value_len = strlen(pb_items[k]->value); - - shm_item->key.data = ngx_shm_pool_calloc(ingress->pool, key_len); - shm_item->value.data = ngx_shm_pool_calloc(ingress->pool, value_len); - if ((shm_item->key.data == NULL) - || (shm_item->value.data == NULL)) - { + if (ngx_ingress_pb_parse_tag_item(ingress, shm_item, pb_items[k]) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, - "|ingress|k-v alloc failed|"); - return NGX_ERROR; + "|ingress|pb parse tag item error|"); } - - shm_item->key.len = key_len; - shm_item->value.len = value_len; - - ngx_memcpy(shm_item->key.data, pb_items[k]->key, key_len); - ngx_memcpy(shm_item->value.data, pb_items[k]->value, value_len); - } else { ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0, "|ingress|miss loc type or match type|"); From 8ddc2cae8370d0efbbdcc802326b39724d95272d Mon Sep 17 00:00:00 2001 From: lianglli Date: Wed, 20 Sep 2023 20:39:28 +0800 Subject: [PATCH 2/2] HTTP Route: crash with logs --- modules/ngx_ingress_module/ngx_ingress_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ngx_ingress_module/ngx_ingress_module.c b/modules/ngx_ingress_module/ngx_ingress_module.c index 3a0d6233e3..78bba75a09 100644 --- a/modules/ngx_ingress_module/ngx_ingress_module.c +++ b/modules/ngx_ingress_module/ngx_ingress_module.c @@ -236,7 +236,7 @@ ngx_ingress_init_main_conf(ngx_conf_t *cf, void *conf) ngx_log_error(NGX_LOG_DEBUG, cf->log, 0, "|ingress|register strategy %V successfully|", - gateway[i].name.data); + &gateway[i].name); } ngx_str_t ngx_ingress_ctx_name = ngx_string(NGX_INGRESS_CTX_VAR);