Coverage Report

Created: 2026-10-31 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/trafficserver/include/proxy/http/remap/UrlRewrite.h
Line
Count
Source
1
/** @file
2
3
  URL rewriting.
4
5
  @section license License
6
7
  Licensed to the Apache Software Foundation (ASF) under one
8
  or more contributor license agreements.  See the NOTICE file
9
  distributed with this work for additional information
10
  regarding copyright ownership.  The ASF licenses this file
11
  to you under the Apache License, Version 2.0 (the
12
  "License"); you may not use this file except in compliance
13
  with the License.  You may obtain a copy of the License at
14
15
      http://www.apache.org/licenses/LICENSE-2.0
16
17
  Unless required by applicable law or agreed to in writing, software
18
  distributed under the License is distributed on an "AS IS" BASIS,
19
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20
  See the License for the specific language governing permissions and
21
  limitations under the License.
22
23
 */
24
25
#pragma once
26
27
#include "iocore/eventsystem/Freer.h"
28
#include "mgmt/config/ConfigContext.h"
29
#include "proxy/http/remap/UrlMapping.h"
30
#include "proxy/http/remap/UrlMappingPathIndex.h"
31
#include "proxy/http/HttpTransact.h"
32
#include "tsutil/Regex.h"
33
#include "proxy/http/remap/PluginFactory.h"
34
#include "proxy/http/remap/NextHopStrategyFactory.h"
35
#include "proxy/http/remap/RemapConfig.h"
36
37
#include <memory>
38
39
#define URL_REMAP_FILTER_NONE         0x00000000
40
0
#define URL_REMAP_FILTER_REFERER      0x00000001 /* enable "referer" header validation */
41
0
#define URL_REMAP_FILTER_REDIRECT_FMT 0x00010000 /* enable redirect URL formatting */
42
43
/**
44
45
 * used for redirection, mapping, and reverse mapping
46
 **/
47
enum class mapping_type {
48
  FORWARD_MAP,
49
  REVERSE_MAP,
50
  PERMANENT_REDIRECT,
51
  TEMPORARY_REDIRECT,
52
  FORWARD_MAP_REFERER,
53
  FORWARD_MAP_WITH_RECV_PORT,
54
  NONE
55
};
56
57
/**
58
 *
59
 **/
60
class UrlRewrite
61
{
62
public:
63
  using URLTable = std::unordered_map<std::string, UrlMappingPathIndex *>;
64
0
  UrlRewrite()   = default;
65
  ~UrlRewrite();
66
67
  /** Retrieve the configured ACL matching policy.
68
   *
69
   * @param[out] policy The configured ACL behavior policy.
70
   * @return @c true if the policy is configured to an appropriate value, @c
71
   * false if not.
72
   */
73
  static bool get_acl_behavior_policy(ACLBehaviorPolicy &policy);
74
75
  /** Load the configuration.
76
   *
77
   * This access data in librecords to obtain the information needed for loading the configuration.
78
   *
79
   * @return @c true if the instance state is valid, @c false if not.
80
   */
81
  bool load(ConfigContext ctx = {});
82
83
  /** Build the tables from @a path, or from @a remap_node when it is set.
84
   *
85
   * @param path Configuration file to parse. Ignored when @a remap_node is set, so inline callers pass it empty.
86
   * @param remap_node Inline remap.yaml style rule sequence, or @c nullptr to parse @a path.
87
   * @param ctx ConfigContext for reload status tracking.
88
   */
89
  bool load_table(const std::string &path, YAML::Node const *remap_node, ConfigContext ctx = {});
90
91
  /** Build the internal url write tables.
92
   *
93
   * @param path Path to configuration file.
94
   * @param ctx  ConfigContext for reload status tracking.
95
   * @return 0 on success, non-zero error code on failure.
96
   */
97
  int BuildTable(const char *path, YAML::Node const *remap_node = nullptr, ConfigContext ctx = {});
98
99
  mapping_type Remap_redirect(HTTPHdr *request_header, URL *redirect_url);
100
  bool         ReverseMap(HTTPHdr *response_header);
101
  void         SetReverseFlag(int flag);
102
  void         Print() const;
103
104
  bool
105
  is_valid() const
106
0
  {
107
0
    return _valid;
108
0
  };
109
110
  bool
111
  is_remap_yaml() const
112
0
  {
113
0
    return _remap_yaml;
114
0
  };
115
116
  void
117
  set_remap_yaml(bool yaml)
118
0
  {
119
0
    _remap_yaml = yaml;
120
0
  };
121
122
  /// @return  Number of rules defined.
123
  int
124
  rule_count() const
125
0
  {
126
0
    return num_rules_forward + num_rules_reverse + num_rules_redirect_permanent + num_rules_redirect_temporary +
127
0
           num_rules_forward_with_recv_port;
128
0
  }
129
130
  static constexpr int MAX_REGEX_SUBS = 10;
131
132
  struct RegexMapping {
133
    url_mapping *url_map;
134
    Regex        regular_expression;
135
136
    // we store the host-string-to-substitute here; if a match is found,
137
    // the substitutions are made and the resulting url is stored
138
    // directly in toURL's host field
139
    char *to_url_host_template;
140
    int   to_url_host_template_len;
141
142
    // stores the number of substitutions
143
    int n_substitutions;
144
145
    // these two together point to template string places where
146
    // substitutions need to be made and the matching substring
147
    // to use
148
    int substitution_markers[MAX_REGEX_SUBS];
149
    int substitution_ids[MAX_REGEX_SUBS];
150
151
    LINK(RegexMapping, link);
152
  };
153
154
  using RegexMappingList = Queue<RegexMapping>;
155
156
  struct MappingsStore {
157
    std::unique_ptr<URLTable> hash_lookup;
158
    RegexMappingList          regex_list;
159
    bool
160
    empty()
161
0
    {
162
0
      return ((hash_lookup == nullptr) && regex_list.empty());
163
0
    }
164
  };
165
166
  void        PerformACLFiltering(HttpTransact::State *s, const url_mapping *const mapping);
167
  void        PrintStore(const MappingsStore &store) const;
168
  std::string PrintRemapHits();
169
  std::string PrintRemapHitsStore(MappingsStore &store);
170
171
  void
172
  DestroyStore(MappingsStore &store)
173
0
  {
174
0
    _destroyTable(store.hash_lookup);
175
0
    _destroyList(store.regex_list);
176
0
  }
177
178
  bool InsertForwardMapping(mapping_type maptype, url_mapping *mapping, const char *src_host);
179
  bool InsertMapping(mapping_type maptype, url_mapping *new_mapping, RegexMapping *reg_map, const char *src_host,
180
                     bool is_cur_mapping_regex);
181
182
  bool TableInsert(std::unique_ptr<URLTable> &h_table, url_mapping *mapping, const char *src_host);
183
184
  MappingsStore forward_mappings;
185
  MappingsStore reverse_mappings;
186
  MappingsStore permanent_redirects;
187
  MappingsStore temporary_redirects;
188
  MappingsStore forward_mappings_with_recv_port;
189
190
  bool
191
  forwardMappingLookup(URL *request_url, int request_port, const char *request_host, int request_host_len,
192
                       UrlMappingContainer &mapping_container)
193
0
  {
194
0
    return _mappingLookup(forward_mappings, request_url, request_port, request_host, request_host_len, mapping_container);
195
0
  }
196
  bool
197
  reverseMappingLookup(URL *request_url, int request_port, const char *request_host, int request_host_len,
198
                       UrlMappingContainer &mapping_container)
199
0
  {
200
0
    return _mappingLookup(reverse_mappings, request_url, request_port, request_host, request_host_len, mapping_container);
201
0
  }
202
  bool
203
  permanentRedirectLookup(URL *request_url, int request_port, const char *request_host, int request_host_len,
204
                          UrlMappingContainer &mapping_container)
205
0
  {
206
0
    return _mappingLookup(permanent_redirects, request_url, request_port, request_host, request_host_len, mapping_container);
207
0
  }
208
  bool
209
  temporaryRedirectLookup(URL *request_url, int request_port, const char *request_host, int request_host_len,
210
                          UrlMappingContainer &mapping_container)
211
0
  {
212
0
    return _mappingLookup(temporary_redirects, request_url, request_port, request_host, request_host_len, mapping_container);
213
0
  }
214
  bool
215
  forwardMappingWithRecvPortLookup(URL *request_url, int recv_port, const char *request_host, int request_host_len,
216
                                   UrlMappingContainer &mapping_container)
217
0
  {
218
0
    return _mappingLookup(forward_mappings_with_recv_port, request_url, recv_port, request_host, request_host_len,
219
0
                          mapping_container);
220
0
  }
221
222
  int nohost_rules  = 0;
223
  int reverse_proxy = 0;
224
225
  char *ts_name = nullptr; // Used to send redirects when no host info
226
227
  char *http_default_redirect_url        = nullptr; // Used if redirect in "referer" filtering was not defined properly
228
  int   num_rules_forward                = 0;
229
  int   num_rules_reverse                = 0;
230
  int   num_rules_redirect_permanent     = 0;
231
  int   num_rules_redirect_temporary     = 0;
232
  int   num_rules_forward_with_recv_port = 0;
233
234
  PluginFactory           pluginFactory;
235
  NextHopStrategyFactory *strategyFactory = nullptr;
236
237
private:
238
  bool              _valid               = false;
239
  bool              _remap_yaml          = false;
240
  ACLBehaviorPolicy _acl_behavior_policy = ACLBehaviorPolicy::ACL_BEHAVIOR_LEGACY;
241
242
  bool _mappingLookup(MappingsStore &mappings, URL *request_url, int request_port, const char *request_host, int request_host_len,
243
                      UrlMappingContainer &mapping_container);
244
  url_mapping *_tableLookup(std::unique_ptr<URLTable> &h_table, URL *request_url, int request_port, char *request_host,
245
                            int request_host_len);
246
  bool         _regexMappingLookup(RegexMappingList &regex_mappings, URL *request_url, int request_port, const char *request_host,
247
                                   int request_host_len, int rank_ceiling, UrlMappingContainer &mapping_container);
248
  int          _expandSubstitutions(size_t *matches_info, const RegexMapping *reg_map, const char *matched_string, char *dest_buf,
249
                                    int dest_buf_size);
250
  void         _destroyTable(std::unique_ptr<URLTable> &h_table);
251
  void         _destroyList(RegexMappingList &regexes);
252
  inline bool  _addToStore(MappingsStore &store, url_mapping *new_mapping, RegexMapping *reg_map, const char *src_host,
253
                           bool is_cur_mapping_regex, int &count);
254
};
255
256
void url_rewrite_remap_request(const UrlMappingContainer &mapping_container, URL *request_url, int scheme = -1);
257
258
mapping_type get_mapping_type(const char *type_str, BUILD_TABLE_INFO *bti);
259
260
bool process_regex_mapping_config(const char *from_host_lower, url_mapping *new_mapping, UrlRewrite::RegexMapping *reg_map);