Bug: 447781 Allow additional methods to be x-www-form-encoded
Added configuration to the HttpConfiguration class to allow additional methods to be set as acceptable for x-www-form-encoding.
This commit is contained in:
parent
99ce82e4cd
commit
814000531f
|
@ -20,10 +20,14 @@ package org.eclipse.jetty.server;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.http.HttpScheme;
|
||||
import org.eclipse.jetty.util.Jetty;
|
||||
import org.eclipse.jetty.util.TreeTrie;
|
||||
import org.eclipse.jetty.util.Trie;
|
||||
import org.eclipse.jetty.util.annotation.ManagedAttribute;
|
||||
import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||
|
||||
|
@ -44,7 +48,8 @@ public class HttpConfiguration
|
|||
{
|
||||
public static final String SERVER_VERSION = "Jetty(" + Jetty.VERSION + ")";
|
||||
|
||||
private List<Customizer> _customizers=new CopyOnWriteArrayList<>();
|
||||
private final List<Customizer> _customizers=new CopyOnWriteArrayList<>();
|
||||
private final Trie<Boolean> _formEncodedMethods = new TreeTrie<>();
|
||||
private int _outputBufferSize=32*1024;
|
||||
private int _outputAggregationSize=_outputBufferSize/4;
|
||||
private int _requestHeaderSize=8*1024;
|
||||
|
@ -86,6 +91,8 @@ public class HttpConfiguration
|
|||
|
||||
public HttpConfiguration()
|
||||
{
|
||||
_formEncodedMethods.put(HttpMethod.POST.asString(),Boolean.TRUE);
|
||||
_formEncodedMethods.put(HttpMethod.PUT.asString(),Boolean.TRUE);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -356,6 +363,7 @@ public class HttpConfiguration
|
|||
_secureScheme = secureScheme;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
@ -367,4 +375,51 @@ public class HttpConfiguration
|
|||
_secureScheme,_securePort,
|
||||
_customizers);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the form encoded methods.
|
||||
* @param methods HTTP Methods of requests that can be decoded as
|
||||
* x-www-form-urlencoded content to be made available via the
|
||||
* {@link Request#getParameter(String)} and associated APIs
|
||||
*/
|
||||
public void setFormEncodedMethods(String... methods)
|
||||
{
|
||||
_formEncodedMethods.clear();
|
||||
for (String method:methods)
|
||||
addFormEncodedMethod(method);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return Set of HTTP Methods of requests that can be decoded as
|
||||
* x-www-form-urlencoded content to be made available via the
|
||||
* {@link Request#getParameter(String)} and associated APIs
|
||||
*/
|
||||
public Set<String> getFormEncodedMethods()
|
||||
{
|
||||
return _formEncodedMethods.keySet();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Add a form encoded HTTP Method
|
||||
* @param method HTTP Method of requests that can be decoded as
|
||||
* x-www-form-urlencoded content to be made available via the
|
||||
* {@link Request#getParameter(String)} and associated APIs
|
||||
*/
|
||||
public void addFormEncodedMethod(String method)
|
||||
{
|
||||
_formEncodedMethods.put(method,Boolean.TRUE);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param method
|
||||
* @return True of the requests of this method type can be
|
||||
* decoded as x-www-form-urlencoded content to be made available via the
|
||||
* {@link Request#getParameter(String)} and associated APIs
|
||||
*/
|
||||
public boolean isFormEncodedMethod(String method)
|
||||
{
|
||||
return Boolean.TRUE.equals(_formEncodedMethods.get(method));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -406,7 +406,7 @@ public class Request implements HttpServletRequest
|
|||
if (contentLength != 0)
|
||||
{
|
||||
if (MimeTypes.Type.FORM_ENCODED.is(contentType) && _inputState == __NONE &&
|
||||
(HttpMethod.POST.is(getMethod()) || HttpMethod.PUT.is(getMethod())))
|
||||
_channel.getHttpConfiguration().isFormEncodedMethod(getMethod()))
|
||||
{
|
||||
extractFormParameters(_contentParameters);
|
||||
}
|
||||
|
|
|
@ -643,6 +643,82 @@ public class RequestTest
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodedForm() throws Exception
|
||||
{
|
||||
_handler._checker = new RequestTester()
|
||||
{
|
||||
@Override
|
||||
public boolean check(HttpServletRequest request,HttpServletResponse response) throws IOException
|
||||
{
|
||||
String actual = request.getParameter("name2");
|
||||
return "test2".equals(actual);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
String content="name1=test&name2=test2&name3=&name4=test";
|
||||
String request="POST / HTTP/1.1\r\n"+
|
||||
"Host: whatever\r\n"+
|
||||
"Content-Type: "+MimeTypes.Type.FORM_ENCODED.asString()+"\r\n" +
|
||||
"Content-Length: "+content.length()+"\r\n"+
|
||||
"Connection: close\r\n"+
|
||||
"\r\n"+
|
||||
content;
|
||||
String response = _connector.getResponses(request);
|
||||
assertThat(response,Matchers.containsString(" 200 OK"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodedFormUnknownMethod() throws Exception
|
||||
{
|
||||
_handler._checker = new RequestTester()
|
||||
{
|
||||
@Override
|
||||
public boolean check(HttpServletRequest request,HttpServletResponse response) throws IOException
|
||||
{
|
||||
return request.getParameter("name1")==null && request.getParameter("name2")==null && request.getParameter("name3")==null;
|
||||
}
|
||||
};
|
||||
|
||||
String content="name1=test&name2=test2&name3=&name4=test";
|
||||
String request="UNKNOWN / HTTP/1.1\r\n"+
|
||||
"Host: whatever\r\n"+
|
||||
"Content-Type: "+MimeTypes.Type.FORM_ENCODED.asString()+"\r\n" +
|
||||
"Content-Length: "+content.length()+"\r\n"+
|
||||
"Connection: close\r\n"+
|
||||
"\r\n"+
|
||||
content;
|
||||
String response = _connector.getResponses(request);
|
||||
assertThat(response,Matchers.containsString(" 200 OK"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodedFormExtraMethod() throws Exception
|
||||
{
|
||||
_handler._checker = new RequestTester()
|
||||
{
|
||||
@Override
|
||||
public boolean check(HttpServletRequest request,HttpServletResponse response) throws IOException
|
||||
{
|
||||
String actual = request.getParameter("name2");
|
||||
return "test2".equals(actual);
|
||||
}
|
||||
};
|
||||
|
||||
_connector.getConnectionFactory(HttpConnectionFactory.class).getHttpConfiguration().addFormEncodedMethod("Extra");
|
||||
String content="name1=test&name2=test2&name3=&name4=test";
|
||||
String request="EXTRA / HTTP/1.1\r\n"+
|
||||
"Host: whatever\r\n"+
|
||||
"Content-Type: "+MimeTypes.Type.FORM_ENCODED.asString()+"\r\n" +
|
||||
"Content-Length: "+content.length()+"\r\n"+
|
||||
"Connection: close\r\n"+
|
||||
"\r\n"+
|
||||
content;
|
||||
String response = _connector.getResponses(request);
|
||||
assertThat(response,Matchers.containsString(" 200 OK"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test8859EncodedForm() throws Exception
|
||||
{
|
||||
|
@ -659,7 +735,6 @@ public class RequestTest
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
String content="name1=test&name2=test%E4&name3=&name4=test";
|
||||
String request="POST / HTTP/1.1\r\n"+
|
||||
"Host: whatever\r\n"+
|
||||
|
|
|
@ -155,6 +155,16 @@ public class ArrayTernaryTrie<V> extends AbstractTrie<V>
|
|||
_tree=Arrays.copyOf(trie._tree, capacity*ROW_SIZE);
|
||||
_key=Arrays.copyOf(trie._key, capacity);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void clear()
|
||||
{
|
||||
_rows=0;
|
||||
Arrays.fill(_value,null);
|
||||
Arrays.fill(_tree,(char)0);
|
||||
Arrays.fill(_key,null);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
|
|
|
@ -20,6 +20,7 @@ package org.eclipse.jetty.util;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -132,7 +133,16 @@ public class ArrayTrie<V> extends AbstractTrie<V>
|
|||
_rowIndex=new char[capacity*32];
|
||||
_key=new String[capacity];
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public void clear()
|
||||
{
|
||||
_rows=0;
|
||||
Arrays.fill(_value,null);
|
||||
Arrays.fill(_rowIndex,(char)0);
|
||||
Arrays.fill(_key,null);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
|
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.util;
|
|||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
@ -33,7 +34,7 @@ import java.util.Set;
|
|||
* <p>This Trie is stored in a Tree and is unlimited in capacity</p>
|
||||
*
|
||||
* <p>This Trie is not Threadsafe and contains no mutual exclusion
|
||||
* or deliberate memory barriers. It is intended for an ArrayTrie to be
|
||||
* or deliberate memory barriers. It is intended for an TreeTrie to be
|
||||
* built by a single thread and then used concurrently by multiple threads
|
||||
* and not mutated during that access. If concurrent mutations of the
|
||||
* Trie is required external locks need to be applied.
|
||||
|
@ -74,6 +75,15 @@ public class TreeTrie<V> extends AbstractTrie<V>
|
|||
_nextIndex = new TreeTrie[INDEX];
|
||||
this._c=c;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear()
|
||||
{
|
||||
Arrays.fill(_nextIndex,null);
|
||||
_nextOther.clear();
|
||||
_key=null;
|
||||
_value=null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean put(String s, V v)
|
||||
|
|
|
@ -123,4 +123,7 @@ public interface Trie<V>
|
|||
/* ------------------------------------------------------------ */
|
||||
public boolean isCaseInsensitive();
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void clear();
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue