/* * Copyright (c) 2002-2012 Alibaba Group Holding Limited. * All rights reserved. * * 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 com.alibaba.citrus.service.requestcontext.parser; import static com.alibaba.citrus.test.TestEnvStatic.*; import static com.alibaba.citrus.util.CollectionUtil.*; import static org.easymock.EasyMock.*; import static org.junit.Assert.*; import java.io.File; import java.net.URLEncoder; import java.util.Enumeration; import java.util.List; import java.util.Locale; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.alibaba.citrus.service.requestcontext.AbstractRequestContextsTests; import com.alibaba.citrus.util.i18n.LocaleUtil; import org.apache.commons.fileupload.FileItem; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; /** 测试<code>ParserRequestContext</code>。 */ public class ParserRequestContextTests extends AbstractRequestContextsTests<ParserRequestContext> { @BeforeClass public static void initFactory() { createBeanFactory("services-parser.xml"); } @Before public void init() throws Exception { invokeReadFileServlet("form.html"); initRequestContext(); // 设置thread context编码,以便url encoding正确执行 LocaleUtil.setContext(null, "GBK"); } @Test public void urlEncodeForm() throws Exception { invokeReadFileServlet("form2.html"); initRequestContext(); assertEquals("hello", requestContext.getParameters().getString("myparam")); assertEquals("hello", requestContext.getParameters().getStrings("myparam")[0]); assertEquals("中华人民共和国", requestContext.getParameters().getStrings("myparam")[1]); // 用request接口直接取值 assertEquals("hello", newRequest.getParameter("myparam")); assertEquals("hello", newRequest.getParameterValues("myparam")[0]); assertEquals("中华人民共和国", newRequest.getParameterValues("myparam")[1]); } @Test public void multipartForm() throws Exception { assertEquals("hello", requestContext.getParameters().getString("myparam")); // 取得单个file item FileItem fileItem = requestContext.getParameters().getFileItem("myfile"); assertEquals("myfile", fileItem.getFieldName()); assertEquals(new File(srcdir, "smallfile.txt"), new File(fileItem.getName())); assertFalse(fileItem.isFormField()); assertEquals(new String("中华人民共和国".getBytes("GBK"), "8859_1"), fileItem.getString()); assertEquals("中华人民共和国", fileItem.getString("GBK")); assertTrue(fileItem.isInMemory()); // 取得多个file items FileItem[] fileItems = requestContext.getParameters().getFileItems("myfile"); String[] fileNames = requestContext.getParameters().getStrings("myfile"); assertEquals(fileItems.length, fileNames.length); assertEquals(4, fileNames.length); assertEquals(new File(srcdir, "smallfile.txt"), new File(fileItems[0].getName())); assertEquals(new File(srcdir, "smallfile_.JPG"), new File(fileItems[1].getName())); // case insensitive assertEquals(new File(srcdir, "smallfile.gif"), new File(fileItems[2].getName())); assertEquals(new File(srcdir, "smallfile"), new File(fileItems[3].getName())); assertEquals(new File(srcdir, "smallfile.txt"), new File(fileNames[0])); assertEquals(new File(srcdir, "smallfile_.JPG"), new File(fileNames[1])); // case insensitive assertEquals(new File(srcdir, "smallfile.gif"), new File(fileNames[2])); assertEquals(new File(srcdir, "smallfile"), new File(fileNames[3])); // 用request接口直接取值 assertEquals("hello", newRequest.getParameter("myparam")); assertEquals(new File(srcdir, "smallfile.txt"), new File(newRequest.getParameter("myfile"))); } @Test public void uploaded_file_whitelist() throws Exception { invokeReadFileServlet("form.html"); initRequestContext("parser_whitelist"); // 取得多个file items FileItem[] fileItems = requestContext.getParameters().getFileItems("myfile"); String[] fileNames = requestContext.getParameters().getStrings("myfile"); assertEquals(2, fileItems.length); assertEquals(4, fileNames.length); assertEquals(new File(srcdir, "smallfile_.JPG"), new File(fileItems[0].getName())); // case insensitive assertEquals(new File(srcdir, "smallfile.gif"), new File(fileItems[1].getName())); assertEquals("", fileNames[0]); assertEquals(new File(srcdir, "smallfile_.JPG"), new File(fileNames[1])); // case insensitive assertEquals(new File(srcdir, "smallfile.gif"), new File(fileNames[2])); assertEquals("", fileNames[3]); } @Test public void uploaded_file_whitelist2() throws Exception { invokeReadFileServlet("form.html"); initRequestContext("parser_whitelist2"); // 取得多个file items FileItem[] fileItems = requestContext.getParameters().getFileItems("myfile"); String[] fileNames = requestContext.getParameters().getStrings("myfile"); assertEquals(2, fileItems.length); assertEquals(4, fileNames.length); assertEquals(new File(srcdir, "smallfile.txt"), new File(fileItems[0].getName())); assertEquals(new File(srcdir, "smallfile"), new File(fileItems[1].getName())); assertEquals(new File(srcdir, "smallfile.txt"), new File(fileNames[0])); assertEquals("", fileNames[1]); assertEquals("", fileNames[2]); assertEquals(new File(srcdir, "smallfile"), new File(fileNames[3])); } @Test public void cookies() throws Exception { assertEquals("mycookievalue", requestContext.getCookies().getString("mycookie")); requestContext.getCookies().setCookie("hello", "baobao"); commitToClient(); assertEquals("baobao", clientResponse.getNewCookieValue("hello")); } @Test @SuppressWarnings("unchecked") public void getParameterNames() { List<String> keys = createArrayList(); for (Enumeration<String> e = newRequest.getParameterNames(); e.hasMoreElements(); ) { keys.add(e.nextElement()); } assertArrayEquals(requestContext.getParameters().keySet().toArray(new String[0]), keys.toArray(new String[0])); } @Test @SuppressWarnings({ "unchecked", "rawtypes" }) public void getRequestMap() throws Exception { Map paramMap = newRequest.getParameterMap(); // unmodifiable try { paramMap.put("test", "fail"); fail("UnsupportedOperationException expected"); } catch (UnsupportedOperationException e) { } try { paramMap.remove("myparam"); fail("UnsupportedOperationException expected"); } catch (UnsupportedOperationException e) { } try { ((Map.Entry) paramMap.entrySet().iterator().next()).setValue(null); fail("UnsupportedOperationException expected"); } catch (UnsupportedOperationException e) { } // containsKey assertTrue(paramMap.containsKey("myparam")); assertFalse(paramMap.containsKey(new Object())); // not a String key // get assertNull(paramMap.get(new Object())); // not a String key String[] myparam = (String[]) paramMap.get("myparam"); String[] myfile = (String[]) paramMap.get("myfile"); String[] submit = (String[]) paramMap.get("submit"); assertEquals("hello", myparam[0]); assertEquals("中华人民共和国", myparam[1]); assertEquals(new File(srcdir, "smallfile.txt"), new File(myfile[0])); assertEquals("upload", submit[0]); // keySet assertArrayEquals(requestContext.getParameters().keySet().toArray(new String[0]), paramMap.keySet().toArray(new String[0])); // values String[][] values = new String[requestContext.getParameters().size()][]; int i = 0; for (String key : requestContext.getParameters().keySet()) { values[i++] = requestContext.getParameters().getStrings(key); } assertArrayEquals(values, paramMap.values().toArray(new String[0][])); } @Test public void toQueryString() throws Exception { ParameterParser params = requestContext.getParameters(); assertEquals("myparam=hello&myparam=%D6%D0%BB%AA%C8%CB%C3%F1%B9%B2%BA%CD%B9%FA&submit=upload", params.toQueryString()); params.setStrings("array", new String[] { "11", "22", "33" }); assertEquals( "myparam=hello&myparam=%D6%D0%BB%AA%C8%CB%C3%F1%B9%B2%BA%CD%B9%FA&submit=upload&array=11&array=22&array=33", params.toQueryString()); } @Test public void parse_post() throws Exception { // 在post/put方法中,将由引擎来解码form data Map<String, String[]> engineDecodedParams = createLinkedHashMap(); engineDecodedParams.put("a", new String[] { "2" }); initMockRequest("POST", "a=1", null, engineDecodedParams); initRequestContext(); assertTrue(requestContext.isUseBodyEncodingForURI()); assertArrayEquals(new String[] { "2" }, newRequest.getParameterValues("a")); initMockRequest("PUT", "a=1", null, engineDecodedParams); initRequestContext(); assertTrue(requestContext.isUseBodyEncodingForURI()); assertArrayEquals(new String[] { "2" }, newRequest.getParameterValues("a")); } @Test public void parse_get() throws Exception { String utf8_中国 = URLEncoder.encode("中国", "UTF-8"); String gbk_中国 = URLEncoder.encode("中国", "GBK"); String utf8_中国_raw = new String("中国".getBytes("UTF-8"), "8859_1"); // 模仿ie行为,不进行urlencoding String gbk_中国_raw = new String("中国".getBytes("GBK"), "8859_1"); // 模仿ie行为,不进行urlencoding Map<String, String[]> engineDecodedParams = createLinkedHashMap(); engineDecodedParams.put("a", new String[] { "China" }); // 在get/head方法中,将自行解析query,不调用引擎 // 且useBodyEncodingForURI=true,使用指定的charset来解码 initMockRequest("GET", "a=" + gbk_中国, "GBK", null); initRequestContext(); assertFalse(requestContext.isUseServletEngineParser()); assertTrue(requestContext.isUseBodyEncodingForURI()); assertArrayEquals(new String[] { "中国" }, newRequest.getParameterValues("a")); initMockRequest("HEAD", gbk_中国 + "=1", "GBK", null); initRequestContext(); assertFalse(requestContext.isUseServletEngineParser()); assertTrue(requestContext.isUseBodyEncodingForURI()); assertArrayEquals(new String[] { "1" }, newRequest.getParameterValues("中国")); initMockRequest("GET", "a=" + gbk_中国_raw, "GBK", null); initRequestContext(); assertFalse(requestContext.isUseServletEngineParser()); assertTrue(requestContext.isUseBodyEncodingForURI()); assertArrayEquals(new String[] { "中国" }, newRequest.getParameterValues("a")); initMockRequest("HEAD", gbk_中国_raw + "=1", "GBK", null); initRequestContext(); assertFalse(requestContext.isUseServletEngineParser()); assertTrue(requestContext.isUseBodyEncodingForURI()); assertArrayEquals(new String[] { "1" }, newRequest.getParameterValues("中国")); // 在get/head方法中,明确设置useServletEngineParser,此时useBodyEncodingForURI无效 initMockRequest("GET", null, null, engineDecodedParams); initRequestContext("parser_useServletEngineParser"); assertTrue(requestContext.isUseServletEngineParser()); assertTrue(requestContext.isUseBodyEncodingForURI()); assertArrayEquals(new String[] { "China" }, newRequest.getParameterValues("a")); // 在get/head方法中,useBodyEncodingForURI=false,总是使用utf-8解码 initMockRequest("GET", "a=" + utf8_中国, "GBK", null); initRequestContext("parser_dont_useBodyEncodingForURI"); assertFalse(requestContext.isUseServletEngineParser()); assertFalse(requestContext.isUseBodyEncodingForURI()); assertEquals("UTF-8", requestContext.getURIEncoding()); assertArrayEquals(new String[] { "中国" }, newRequest.getParameterValues("a")); initMockRequest("GET", "a=" + utf8_中国_raw, "GBK", null); initRequestContext("parser_dont_useBodyEncodingForURI"); assertFalse(requestContext.isUseServletEngineParser()); assertFalse(requestContext.isUseBodyEncodingForURI()); assertEquals("UTF-8", requestContext.getURIEncoding()); assertArrayEquals(new String[] { "中国" }, newRequest.getParameterValues("a")); // 在get/head方法中,useBodyEncodingForURI=true,但未指定charset,则使用ISO-8859-1 initMockRequest("GET", "a=" + gbk_中国, null, null); initRequestContext(); assertFalse(requestContext.isUseServletEngineParser()); assertTrue(requestContext.isUseBodyEncodingForURI()); assertArrayEquals(new String[] { new String("中国".getBytes("GBK"), "8859_1") }, newRequest.getParameterValues("a")); } @Test public void parse_query() throws Exception { // 多值 initMockRequest("GET", " &a=1&a=2&b=3& ", "GBK", null); initRequestContext(); assertArrayEquals(new String[] { "1", "2" }, newRequest.getParameterValues("a")); assertArrayEquals(new String[] { "3" }, newRequest.getParameterValues("b")); assertArrayEquals(new Object[] { "a", "b" }, newRequest.getParameterMap().keySet().toArray()); // 空值 initMockRequest("GET", "a", "GBK", null); initRequestContext(); assertArrayEquals(new String[] { }, newRequest.getParameterValues("a")); assertArrayEquals(new Object[] { "a" }, newRequest.getParameterMap().keySet().toArray()); initMockRequest("GET", "a&b=&=1", "GBK", null); initRequestContext(); assertArrayEquals(new String[] { }, newRequest.getParameterValues("a")); assertArrayEquals(new String[] { }, newRequest.getParameterValues("b")); assertArrayEquals(new Object[] { "a", "b" }, newRequest.getParameterMap().keySet().toArray()); } @Test public void parse_trimming() throws Exception { initMockRequest("GET", " &a=++&a=+2+&b=+3+& ", "GBK", null); initRequestContext(); assertArrayEquals(new String[] { "", "2" }, newRequest.getParameterValues("a")); assertArrayEquals(new String[] { "3" }, newRequest.getParameterValues("b")); assertArrayEquals(new Object[] { "a", "b" }, newRequest.getParameterMap().keySet().toArray()); } private void initMockRequest(String method, String queryString, String charset, Map<String, String[]> engineDecodedParams) { request = createMock(HttpServletRequest.class); response = createMock(HttpServletResponse.class); request.setAttribute(org.easymock.EasyMock.<String>anyObject(), anyObject()); expectLastCall().anyTimes(); expect(request.getLocale()).andReturn(Locale.CHINA).anyTimes(); expect(request.getContentType()).andReturn(null).anyTimes(); expect(request.getMethod()).andReturn(method).anyTimes(); expect(request.getQueryString()).andReturn(queryString).anyTimes(); expect(request.getCharacterEncoding()).andReturn(charset).anyTimes(); if (engineDecodedParams != null) { expect(request.getParameterMap()).andReturn(engineDecodedParams).anyTimes(); } replay(request, response); } }