1 /*
2 * Copyright 2012-2025 CodeLibs Project and the Others.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13 * either express or implied. See the License for the specific language
14 * governing permissions and limitations under the License.
15 */
16 package org.codelibs.fess.helper;
17
18 import static org.codelibs.core.stream.StreamUtil.stream;
19
20 import java.util.function.Function;
21
22 import org.codelibs.core.lang.StringUtil;
23 import org.codelibs.core.misc.Tuple3;
24 import org.codelibs.fess.mylasta.direction.FessConfig;
25 import org.codelibs.fess.util.ComponentUtil;
26 import org.lastaflute.web.response.next.HtmlNext;
27 import org.lastaflute.web.util.LaRequestUtil;
28
29 /**
30 * Helper class for managing virtual host configurations and routing.
31 * This class provides functionality to handle virtual host-based routing
32 * and path resolution based on HTTP headers.
33 */
34 public class VirtualHostHelper {
35
36 /**
37 * Default constructor.
38 */
39 public VirtualHostHelper() {
40 // Default constructor
41 }
42
43 /**
44 * Gets the virtual host path for the specified HTML page.
45 *
46 * @param page The HTML page to get the virtual host path for
47 * @return The HTML page with updated virtual host path
48 */
49 public HtmlNext getVirtualHostPath(final HtmlNext page) {
50 return processVirtualHost(s -> {
51 final String basePath = getVirtualHostBasePath(s, page);
52 return new HtmlNext(basePath + page.getRoutingPath());
53 }, page);
54 }
55
56 /**
57 * Gets the base path for virtual host based on the virtual host key and page.
58 *
59 * @param s The virtual host key
60 * @param page The HTML page
61 * @return The base path for the virtual host
62 */
63 protected String getVirtualHostBasePath(final String s, final HtmlNext page) {
64 return StringUtil.isBlank(s) ? StringUtil.EMPTY : "/" + s;
65 }
66
67 /**
68 * Gets the virtual host key from the current request.
69 * The key is determined by matching HTTP headers against configured virtual hosts.
70 *
71 * @return The virtual host key, or empty string if no match found
72 */
73 public String getVirtualHostKey() {
74 return LaRequestUtil.getOptionalRequest().map(req -> (String) req.getAttribute(FessConfig.VIRTUAL_HOST_VALUE)).orElseGet(() -> {
75 final String value = processVirtualHost(s -> s, StringUtil.EMPTY);
76 LaRequestUtil.getOptionalRequest().ifPresent(req -> req.setAttribute(FessConfig.VIRTUAL_HOST_VALUE, value));
77 return value;
78 });
79 }
80
81 /**
82 * Processes virtual host configuration by applying a function to the matched virtual host key.
83 *
84 * @param <T> The return type of the function
85 * @param func The function to apply to the virtual host key
86 * @param defaultValue The default value to return if no virtual host matches
87 * @return The result of applying the function, or the default value
88 */
89 protected <T> T processVirtualHost(final Function<String, T> func, final T defaultValue) {
90 final Tuple3<String, String, String>[] vHosts = ComponentUtil.getFessConfig().getVirtualHosts();
91 return LaRequestUtil.getOptionalRequest().map(req -> {
92 for (final Tuple3<String, String, String> host : vHosts) {
93 final String headerValue = req.getHeader(host.getValue1());
94 if (host.getValue2().equalsIgnoreCase(headerValue)) {
95 return func.apply(host.getValue3());
96 }
97 }
98 return defaultValue;
99 }).orElse(defaultValue);
100 }
101
102 /**
103 * Gets all configured virtual host paths.
104 *
105 * @return An array of virtual host paths
106 */
107 public String[] getVirtualHostPaths() {
108 return stream(ComponentUtil.getFessConfig().getVirtualHosts())
109 .get(stream -> stream.map(h -> "/" + h.getValue3()).toArray(n -> new String[n]));
110 }
111 }