/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.hadoop.yarn.server.webproxy; import static org.apache.hadoop.yarn.util.StringHelper.ujoin; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.net.URLEncoder; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.yarn.api.records.ApplicationId; public class ProxyUriUtils { @SuppressWarnings("unused") private static final Log LOG = LogFactory.getLog(ProxyUriUtils.class); /**Name of the servlet to use when registering the proxy servlet. */ public static final String PROXY_SERVLET_NAME = "proxy"; /**Base path where the proxy servlet will handle requests.*/ public static final String PROXY_BASE = "/proxy/"; /**Path Specification for the proxy servlet.*/ public static final String PROXY_PATH_SPEC = PROXY_BASE+"*"; /**Query Parameter indicating that the URI was approved.*/ public static final String PROXY_APPROVAL_PARAM = "proxyapproved"; private static String uriEncode(Object o) { try { assert (o != null) : "o canot be null"; return URLEncoder.encode(o.toString(), "UTF-8"); } catch (UnsupportedEncodingException e) { //This should never happen throw new RuntimeException("UTF-8 is not supported by this system?", e); } } /** * Get the proxied path for an application. * @param id the application id to use. * @return the base path to that application through the proxy. */ public static String getPath(ApplicationId id) { if(id == null) { throw new IllegalArgumentException("Application id cannot be null "); } return ujoin(PROXY_BASE, uriEncode(id)); } /** * Get the proxied path for an application. * @param id the application id to use. * @param path the rest of the path to the application. * @return the base path to that application through the proxy. */ public static String getPath(ApplicationId id, String path) { if(path == null) { return getPath(id); } else { return ujoin(getPath(id), path); } } /** * Get the proxied path for an application * @param id the id of the application * @param path the path of the application. * @param query the query parameters * @param approved true if the user has approved accessing this app. * @return the proxied path for this app. */ public static String getPathAndQuery(ApplicationId id, String path, String query, boolean approved) { StringBuilder newp = new StringBuilder(); newp.append(getPath(id, path)); boolean first = appendQuery(newp, query, true); if(approved) { appendQuery(newp, PROXY_APPROVAL_PARAM+"=true", first); } return newp.toString(); } private static boolean appendQuery(StringBuilder builder, String query, boolean first) { if(query != null && !query.isEmpty()) { if(first && !query.startsWith("?")) { builder.append('?'); } if(!first && !query.startsWith("&")) { builder.append('&'); } builder.append(query); return false; } return first; } /** * Get a proxied URI for the original URI. * @param originalUri the original URI to go through the proxy, or null if * a default path "/" can be used. * @param proxyUri the URI of the proxy itself, scheme, host and port are used. * @param id the id of the application * @return the proxied URI */ public static URI getProxyUri(URI originalUri, URI proxyUri, ApplicationId id) { try { String path = getPath(id, originalUri == null ? "/" : originalUri.getPath()); return new URI(proxyUri.getScheme(), proxyUri.getAuthority(), path, originalUri == null ? null : originalUri.getQuery(), originalUri == null ? null : originalUri.getFragment()); } catch (URISyntaxException e) { throw new RuntimeException("Could not proxify "+originalUri,e); } } /** * Create a URI form a no scheme Url, such as is returned by the AM. * @param noSchemeUrl the URL formate returned by an AM * @return a URI with an http scheme * @throws URISyntaxException if the url is not formatted correctly. */ public static URI getUriFromAMUrl(String noSchemeUrl) throws URISyntaxException { return new URI("http://"+noSchemeUrl); } }