This commit introduced the basic URI rewrite. It allows users to change request URI. Note the "rewrite" option ignores the contained query if any and the query from the request is preserverd.
An example:
"routes": [
{
"match": {
"uri": "/v1/test"
},
"action": {
"return": 200
}
},
{
"action": {
"rewrite": "/v1$uri",
"pass": "routes"
}
}
]
Reviewed-by: Alejandro Colomar <alx@nginx.com>
160 lines
4.4 KiB
C
160 lines
4.4 KiB
C
|
|
/*
|
|
* Copyright (C) NGINX, Inc.
|
|
* Copyright (C) Valentin V. Bartenev
|
|
*/
|
|
|
|
#ifndef _NXT_HTTP_PARSER_H_INCLUDED_
|
|
#define _NXT_HTTP_PARSER_H_INCLUDED_
|
|
|
|
|
|
typedef enum {
|
|
NXT_HTTP_PARSE_INVALID = 1,
|
|
NXT_HTTP_PARSE_UNSUPPORTED_VERSION,
|
|
NXT_HTTP_PARSE_TOO_LARGE_FIELD,
|
|
} nxt_http_parse_error_t;
|
|
|
|
|
|
typedef struct nxt_http_request_parse_s nxt_http_request_parse_t;
|
|
typedef struct nxt_http_field_s nxt_http_field_t;
|
|
typedef struct nxt_http_fields_hash_s nxt_http_fields_hash_t;
|
|
|
|
|
|
typedef union {
|
|
u_char str[8];
|
|
uint64_t ui64;
|
|
|
|
struct {
|
|
u_char prefix[5];
|
|
u_char major;
|
|
u_char point;
|
|
u_char minor;
|
|
} s;
|
|
} nxt_http_ver_t;
|
|
|
|
|
|
struct nxt_http_request_parse_s {
|
|
nxt_int_t (*handler)(nxt_http_request_parse_t *rp,
|
|
u_char **pos, const u_char *end);
|
|
|
|
nxt_str_t method;
|
|
|
|
u_char *target_start;
|
|
u_char *target_end;
|
|
u_char *request_line_end;
|
|
|
|
nxt_str_t path;
|
|
nxt_str_t args;
|
|
|
|
nxt_http_ver_t version;
|
|
|
|
nxt_list_t *fields;
|
|
nxt_mp_t *mem_pool;
|
|
|
|
nxt_str_t field_name;
|
|
nxt_str_t field_value;
|
|
|
|
uint32_t field_hash;
|
|
|
|
uint8_t skip_field; /* 1 bit */
|
|
uint8_t discard_unsafe_fields; /* 1 bit */
|
|
|
|
/* target with "/." */
|
|
uint8_t complex_target; /* 1 bit */
|
|
#if 0
|
|
/* target with "%" */
|
|
uint8_t quoted_target; /* 1 bit */
|
|
/* target with " " */
|
|
uint8_t space_in_target; /* 1 bit */
|
|
#endif
|
|
/* Preserve encoded '/' (%2F) and '%' (%25). */
|
|
uint8_t encoded_slashes; /* 1 bit */
|
|
};
|
|
|
|
|
|
typedef nxt_int_t (*nxt_http_field_handler_t)(void *ctx,
|
|
nxt_http_field_t *field,
|
|
uintptr_t data);
|
|
|
|
|
|
typedef struct {
|
|
nxt_str_t name;
|
|
nxt_http_field_handler_t handler;
|
|
uintptr_t data;
|
|
} nxt_http_field_proc_t;
|
|
|
|
|
|
struct nxt_http_field_s {
|
|
uint16_t hash;
|
|
uint8_t skip:1;
|
|
uint8_t hopbyhop:1;
|
|
uint8_t name_length;
|
|
uint32_t value_length;
|
|
u_char *name;
|
|
u_char *value;
|
|
};
|
|
|
|
|
|
typedef struct {
|
|
u_char *pos;
|
|
nxt_mp_t *mem_pool;
|
|
|
|
uint64_t chunk_size;
|
|
|
|
uint8_t state;
|
|
uint8_t last; /* 1 bit */
|
|
uint8_t chunk_error; /* 1 bit */
|
|
uint8_t error; /* 1 bit */
|
|
} nxt_http_chunk_parse_t;
|
|
|
|
|
|
#define NXT_HTTP_FIELD_HASH_INIT 159406U
|
|
#define nxt_http_field_hash_char(h, c) (((h) << 4) + (h) + (c))
|
|
#define nxt_http_field_hash_end(h) (((h) >> 16) ^ (h))
|
|
|
|
|
|
nxt_int_t nxt_http_parse_request_init(nxt_http_request_parse_t *rp,
|
|
nxt_mp_t *mp);
|
|
nxt_int_t nxt_http_parse_request(nxt_http_request_parse_t *rp,
|
|
nxt_buf_mem_t *b);
|
|
nxt_int_t nxt_http_parse_fields(nxt_http_request_parse_t *rp,
|
|
nxt_buf_mem_t *b);
|
|
|
|
nxt_int_t nxt_http_fields_hash(nxt_lvlhsh_t *hash,
|
|
nxt_http_field_proc_t items[], nxt_uint_t count);
|
|
nxt_uint_t nxt_http_fields_hash_collisions(nxt_lvlhsh_t *hash,
|
|
nxt_http_field_proc_t items[], nxt_uint_t count, nxt_bool_t level);
|
|
nxt_int_t nxt_http_fields_process(nxt_list_t *fields, nxt_lvlhsh_t *hash,
|
|
void *ctx);
|
|
|
|
nxt_int_t nxt_http_parse_complex_target(nxt_http_request_parse_t *rp);
|
|
nxt_buf_t *nxt_http_chunk_parse(nxt_task_t *task, nxt_http_chunk_parse_t *hcp,
|
|
nxt_buf_t *in);
|
|
|
|
|
|
extern const nxt_lvlhsh_proto_t nxt_http_fields_hash_proto;
|
|
|
|
nxt_inline nxt_int_t
|
|
nxt_http_field_process(nxt_http_field_t *field, nxt_lvlhsh_t *hash, void *ctx)
|
|
{
|
|
nxt_lvlhsh_query_t lhq;
|
|
nxt_http_field_proc_t *proc;
|
|
|
|
lhq.proto = &nxt_http_fields_hash_proto;
|
|
|
|
lhq.key_hash = field->hash;
|
|
lhq.key.length = field->name_length;
|
|
lhq.key.start = field->name;
|
|
|
|
if (nxt_lvlhsh_find(hash, &lhq) != NXT_OK) {
|
|
return NXT_OK;
|
|
}
|
|
|
|
proc = lhq.value;
|
|
|
|
return proc->handler(ctx, field, proc->data);
|
|
}
|
|
|
|
|
|
#endif /* _NXT_HTTP_PARSER_H_INCLUDED_ */
|