/** * Sahi - Web Automation and Test Tool * * Copyright 2006 V Narayan Raman * * 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 net.sf.sahi.request; import java.io.IOException; import java.io.InputStream; import java.net.URLDecoder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.StringTokenizer; import java.util.logging.Level; import net.sf.sahi.StreamHandler; import net.sf.sahi.config.Configuration; import net.sf.sahi.session.Session; import net.sf.sahi.util.Utils; import org.apache.log4j.Logger; /** * User: nraman Date: May 13, 2005 Time: 10:01:13 PM */ public class HttpRequest extends StreamHandler { private String host; private int port; private String uri; private String queryString = ""; private Map<String, String> params = new HashMap<String, String>(); // private Map<String, String> cookies = null; private static final Logger logger = Logger.getLogger(HttpRequest.class); private boolean isSSLSocket; private boolean isAjax; private String fileExtension; private String hostWithPort; private String fileName; private Session session; private String sahiCookie = ""; HttpRequest() { } @Override public String toString() { return "HttpRequest{" + "host='" + host + '\'' + ", port=" + port + ", uri='" + uri + '\'' + ", queryString='" + queryString + '\'' + ", params=" + params + ", isSSLSocket=" + isSSLSocket + ", isAjax=" + isAjax + '}'; } public HttpRequest(final InputStream in) throws IOException { this(in, false); } public HttpRequest(final InputStream in, final boolean isSSLSocket) throws IOException { this.isSSLSocket = isSSLSocket; populateHeaders(in, true); isAjax = hasHeader("sahi-isxhr") || isAjaxHeaderPresent() || isMicrosoftAjaxHeaderPresent(); if (isPost() || isPut()) { populateData(in); } if (isPost() || isGet() || isPut() || isDelete() || isConnect()) { setHostAndPort(); setUri(); setQueryString(); } handleSahiCookies(); } private boolean isMicrosoftAjaxHeaderPresent() { String xReqWith = getLastSetValueOfHeader("x-microsoftajax"); return "Delta=true".equals(xReqWith); } private boolean isAjaxHeaderPresent() { String xReqWith = getLastSetValueOfHeader("X-Requested-With"); return "XMLHttpRequest".equals(xReqWith); } public String host() { return host; } public int port() { return port; } public void setHost(final String host) { this.host = host; } public boolean isPost() { return "post".equalsIgnoreCase(method()); } public boolean isPut() { return "put".equalsIgnoreCase(method()); } public boolean isDelete() { return "delete".equalsIgnoreCase(method()); } public boolean isGet() { return "get".equalsIgnoreCase(method()); } public boolean isConnect() { return "connect".equalsIgnoreCase(method()); } public boolean isSSL() { return isSSLSocket || isConnect(); } public String method() { if (firstLine() == null) { return null; } return firstLine().substring(0, firstLine().indexOf(" ")); } void setUri() { if (isConnect()) { uri = ""; return; } String withHost = firstLine().substring(firstLine().indexOf(" "), firstLine().lastIndexOf(" ")).trim(); uri = stripHostName(withHost, host, isSSL()); } String stripHostName(final String withHost, final String hostName, final boolean ssl) { String stripped = withHost; if (withHost.startsWith("http://") || withHost.startsWith("https://")) { int indexOfSlash = withHost .indexOf("/", withHost.indexOf(hostName)); stripped = withHost.substring(indexOfSlash); } return stripped; } public String uri() { return uri; } public String protocol() { return firstLine().substring(firstLine().lastIndexOf(" ")); } private void setHostAndPort() { hostWithPort = getLastSetValueOfHeader("Host"); host = hostWithPort; port = 80; if (isSSL()) { port = 443; } int indexOfColon = hostWithPort.indexOf(":"); if (indexOfColon != -1) { host = hostWithPort.substring(0, indexOfColon); try { port = Integer.parseInt(hostWithPort .substring(indexOfColon + 1).trim()); } catch (Exception e) { e.printStackTrace(); } } host = Utils.stripChildSessionId(host); } private void setQueryString() { if (uri == null) { return; } int qIx = uri.indexOf("?"); String uriWithoutQueryString = uri; if (qIx != -1 && qIx + 1 < uri.length()) { uriWithoutQueryString = uri.substring(0, qIx); queryString = uri.substring(qIx + 1); } fileExtension = ""; int dotIx = uriWithoutQueryString.indexOf("."); if (dotIx != -1) { fileExtension = uriWithoutQueryString.substring(dotIx + 1); } int lastSlashIx = uriWithoutQueryString.lastIndexOf("/"); if (lastSlashIx != -1) { if (lastSlashIx + 1 < uriWithoutQueryString.length()) { fileName = uriWithoutQueryString.substring(lastSlashIx + 1); } else { fileName = "no_filename"; } } } private void setGetParameters() { try { setGetParameters(queryString()); if (isPost()) setGetParameters(new String(data(), "UTF-8")); } catch (Exception e) { e.printStackTrace(); } } private void setGetParameters(String paramStr) { paramStr = paramStr.replaceAll("__SahiAmpersandSahi__", "&"); StringTokenizer tokenizer = new StringTokenizer(paramStr, "&"); while (tokenizer.hasMoreTokens()) { String keyVal = tokenizer.nextToken(); int eqIx = keyVal.indexOf('='); if (eqIx != -1) { String key = keyVal.substring(0, eqIx); String value = ""; if (eqIx + 1 <= keyVal.length()) { value = keyVal.substring(eqIx + 1); } try { params.put(key, URLDecoder.decode(value, "UTF8")); } catch (Exception e) { params.put(key, value); } } } } public String queryString() { return queryString; } public String getParameter(String key) { if (params.size() == 0) { setGetParameters(); } return (String) params.get(key); } public HttpRequest modifyForFetch() { logger.debug("REQUEST HEADERS BEFORE MODIFICATION"); logger.debug(new String(rawHeaders())); removeHeader("Proxy-Connection"); removeHeader("Accept-Encoding"); addHeader("Accept-Encoding", "gzip"); removeHeader("Keep-Alive"); removeHeader("sahi-isxhr"); // Not sure whether Authorization and Proxy-Authorization should be removed. removeHeader("Authorization"); removeHeader("Proxy-Authorization"); // cookies().remove("sahisid"); // setHeader("Cookie", rebuildCookies()); resetRawHeaders(); logger.debug("REQUEST HEADERS AFTER MODIFICATION"); logger.debug(firstLine()); logger.debug("\n------------\n\nRequest Headers:\n" + headers()); return this; } public Session session() { if (this.session == null) { String sessionId; sessionId = getParameter("sahisid"); // sessionId = "SAHI_HARDCODED_IDsahixSAHI_CHILD_IDx"; // Change in Utils too logger.debug("SessionId from parameter:" + sessionId); if (Utils.isBlankOrNull(sessionId)) { sessionId = sahiCookie; logger.debug("SessionId from cookie:" + sessionId); } if (Utils.isBlankOrNull(sessionId)) { sessionId = Utils.generateId(); logger.debug("SessionId generated:" + sessionId); } this.session = Session.getInstance(sessionId); } return this.session; } void handleSahiCookies() { final List<String> cookieHeaders = headers().getHeaders("Cookie"); if (cookieHeaders == null) return; List<String> modifiedCookieHeaders = new ArrayList<String>(); for (int i = 0; i < cookieHeaders.size(); i++) { final String modifed = handleSahiCookie(cookieHeaders.get(i)); if (!Utils.isBlankOrNull(modifed)) modifiedCookieHeaders.add(modifed); } headers().removeHeader("Cookie"); headers().addHeaders("Cookie", modifiedCookieHeaders); } String handleSahiCookie(String cookieString) { if (Utils.isBlankOrNull(cookieString)) return cookieString; int ix = cookieString.indexOf("sahisid="); if (ix == -1) return cookieString; int endIx = cookieString.indexOf(";", ix + 1); int length = cookieString.length(); String stripped; if (endIx == -1) { sahiCookie = cookieString.substring(ix + "sahisid=".length()); stripped = cookieString.substring(0, ix); } else { sahiCookie = cookieString.substring(ix + "sahisid=".length(), endIx); stripped = cookieString.substring(0, ix) + cookieString.substring(endIx + 1, length).trim(); } stripped = stripped.trim(); if (stripped.endsWith(";")) stripped = stripped.substring(0, stripped.length() - 1); return stripped.trim(); } public String sahiCookie() { return sahiCookie; } public String fileExtension() { return fileExtension; } public String fileName() { return fileName; } public String url() { return (isSSL() ? "https" : "http") + "://" + hostWithPort + (uri == null ? "" : uri); } public boolean isMultipart() { String contentType = getLastSetValueOfHeader("Content-Type"); return contentType != null && contentType.startsWith("multipart/form-data"); } public void setSSL(boolean isSSL) { this.isSSLSocket = isSSL; } public boolean isIE() { String agent = getLastSetValueOfHeader("User-Agent"); return (agent == null || agent.indexOf("MSIE") != -1); } public boolean isAjax() { return isAjax; } public String referer() { String header = headers().getLastHeader("referer"); return header; } public boolean isExcluded() { logger.debug("isAjax=" + isAjax + " for " + url()); if (isAjax) { return true; } String url = url(); String[] exclusionList = Configuration.getExclusionList(); for (int i = 0; i < exclusionList.length; i++) { String pattern = exclusionList[i]; if (url.matches(pattern.trim())) { return true; } } return false; } }