/** * Yobi, Project Hosting SW * * Copyright 2012 NAVER Corp. * http://yobi.io * * @author Yi EungJun * * Licensed 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 utils; import org.apache.commons.lang3.StringUtils; import play.api.http.MediaRange; import play.mvc.Http; import java.io.UnsupportedEncodingException; import java.net.*; import java.util.*; public class HttpUtil { /** * Finds the first value by given the key from the given query. * * This method is used to get a value from a URI query string. * * @param query * @param key * @return the value, "" if the query does not have the key. */ public static String getFirstValueFromQuery(Map<String, String[]> query, String key) { if (query == null) { return ""; } String[] values = query.get(key); if (values != null && values.length > 0) { return values[0]; } else { return ""; } } /** * Encodes a filename according to RFC 2231; IE 8 or less, and Safari 5 or * less are not supported. * * @param filename * @return * @throws UnsupportedEncodingException * @see http://greenbytes.de/tech/tc2231/ */ public static String encodeContentDisposition(String filename) throws UnsupportedEncodingException { filename = filename.replaceAll("[:\\x5c\\/{?]", "_"); filename = URLEncoder.encode(filename, "UTF-8").replaceAll("\\+", "%20"); filename = "filename*=UTF-8''" + filename; return filename; } /** * Returns the most preferred content-type among supported types. * * @param request the request of the client * @param types the supported types * @return the most preferred type; {@code null} if the client has no * preference among the supported types. */ public static String getPreferType(Http.Request request, String ... types) { // acceptedTypes is sorted by preference. for(MediaRange range : request.acceptedTypes()) { for(String type : types) { if (range.accepts(type)) { return type; } } } return null; } /** * Returns whether is the client prefers "application/json" most * using getPreferType() * * @param request * @return */ public static Boolean isJSONPreferred(Http.Request request){ String preferredType = getPreferType(request, "text/html", "application/json"); return (preferredType != null) ? preferredType.equals("application/json") : false; } /** * Return a url formed by appending key-value pairs to the query string of * the given {@code url}. * * The format of the key-value pair is {@code "key=value"}. * * @param url * @param encodedPairs encoded pairs to compose the query string * @return the resulting url * @throws URISyntaxException */ public static String addQueryString(String url, String ... encodedPairs) throws URISyntaxException { URI aURI = new URI(url); String query = (aURI.getQuery() != null) ? aURI.getQuery() : ""; query += (query.length() > 0 ? "&" : "") + StringUtils.join(encodedPairs, "&"); return new URI(aURI.getScheme(), aURI.getAuthority(), aURI.getPath(), query, aURI.getFragment()).toString(); } /** * Removes key-value pairs from the query string of the given url. * * The format of the key-value pair is {@code "key=value"}. * * @param url * @param keys keys to be removed; The key must not be encoded. * @return the resulting url * @throws URISyntaxException * @throws UnsupportedEncodingException */ public static String removeQueryString(String url, String ... keys) throws URISyntaxException, UnsupportedEncodingException { URI aURI = new URI(url); if (aURI.getQuery() == null) { return url; } List<String> pairStrings = new ArrayList<>(); Set<String> keySet = new HashSet<>(Arrays.asList(keys)); for (String pairString : aURI.getQuery().split("&")) { String[] pair = pairString.split("="); if (pair.length == 0) { continue; } if (!keySet.contains(URLDecoder.decode(pair[0], "UTF-8"))) { pairStrings.add(pairString); } } return new URI(aURI.getScheme(), aURI.getAuthority(), aURI.getPath(), StringUtils.join(pairStrings, "&"), aURI.getFragment()).toString(); } /** * Returns whether request header has "X-Requested-With" * and also its value equals to "XMLHttpRequest". * * Most JavaScript frameworks like jQuery, prototype and JindoJS * set "XMLHttpRequest" in the "X-Requested-With" header when they call XHR. * * @param request * @return Boolean */ public static Boolean isRequestedWithXHR(Http.Request request){ String requestedWith = request.getHeader("X-Requested-With"); return (requestedWith != null && requestedWith.toLowerCase().equals("xmlhttprequest")); } /** * Returns whether {@code request} has "X-PJAX" header * * @param request * @return Boolean */ public static Boolean isPJAXRequest(Http.Request request){ return Boolean.parseBoolean(request.getHeader("X-PJAX")); } /** * Decodes the percent-encoded path segment. * * @param pathSegment * @return decoded path segment or null if the given path segment is null * @throws UnsupportedEncodingException */ public static String decodePathSegment(String pathSegment) throws UnsupportedEncodingException { if (pathSegment != null) { return URLDecoder.decode(pathSegment, "UTF-8"); } else { return null; } } }