From ce46fecc2896cd91ed7bbc241bb759425cf7664f Mon Sep 17 00:00:00 2001 From: Ryan Ernst Date: Tue, 3 Dec 2013 09:19:30 +0000 Subject: [PATCH] SOLR-5517: Return HTTP error on POST requests with no Content-Type git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1547322 13f79535-47bb-0310-9956-ffa450edef68 --- solr/CHANGES.txt | 3 +++ .../solr/handler/UpdateRequestHandler.java | 4 ++-- .../solr/handler/component/SearchHandler.java | 6 ++++++ .../apache/solr/servlet/SolrRequestParsers.java | 9 ++++++--- .../solr/request/TestRemoteStreaming.java | 11 ++++++++--- .../solr/servlet/SolrRequestParserTest.java | 17 +++++++++++++++++ .../org/apache/solr/common/SolrException.java | 1 + 7 files changed, 43 insertions(+), 8 deletions(-) diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 5a5c1bca2ca..cf95edc9454 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -218,6 +218,9 @@ Other Changes * SOLR-5499: Log a warning if /get is not registered when using SolrCloud. (Daniel Collins via shalin) +* SOLR-5517: Return HTTP error on POST requests with no Content-Type. + (Ryan Ernst, Uwe Schindler) + ================== 4.6.0 ================== Versions of Major Components diff --git a/solr/core/src/java/org/apache/solr/handler/UpdateRequestHandler.java b/solr/core/src/java/org/apache/solr/handler/UpdateRequestHandler.java index 3d136ebb28d..aa46b2ef0b8 100644 --- a/solr/core/src/java/org/apache/solr/handler/UpdateRequestHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/UpdateRequestHandler.java @@ -75,7 +75,7 @@ public class UpdateRequestHandler extends ContentStreamHandlerBase { type = stream.getContentType(); } if( type == null ) { // Normal requests will not get here. - throw new SolrException(ErrorCode.BAD_REQUEST, "Missing ContentType"); + throw new SolrException(ErrorCode.UNSUPPORTED_MEDIA_TYPE, "Missing ContentType"); } int idx = type.indexOf(';'); if(idx>0) { @@ -83,7 +83,7 @@ public class UpdateRequestHandler extends ContentStreamHandlerBase { } ContentStreamLoader loader = loaders.get(type); if(loader==null) { - throw new SolrException(ErrorCode.BAD_REQUEST, "Unsupported ContentType: " + throw new SolrException(ErrorCode.UNSUPPORTED_MEDIA_TYPE, "Unsupported ContentType: " +type+ " Not in: "+loaders.keySet()); } if(loader.getDefaultWT()!=null) { diff --git a/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java b/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java index 2f49229ed10..05c766441ad 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/component/SearchHandler.java @@ -22,9 +22,11 @@ import java.util.LinkedList; import java.util.List; import org.apache.solr.common.SolrException; +import org.apache.solr.common.SolrException.ErrorCode; import org.apache.solr.common.params.CommonParams; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.ShardParams; +import org.apache.solr.common.util.ContentStream; import org.apache.solr.core.CloseHook; import org.apache.solr.core.PluginInfo; import org.apache.solr.core.SolrCore; @@ -165,6 +167,10 @@ public class SearchHandler extends RequestHandlerBase implements SolrCoreAware , { // int sleep = req.getParams().getInt("sleep",0); // if (sleep > 0) {log.error("SLEEPING for " + sleep); Thread.sleep(sleep);} + if (req.getContentStreams() != null && req.getContentStreams().iterator().hasNext()) { + throw new SolrException(ErrorCode.BAD_REQUEST, "Search requests cannot accept content streams"); + } + ResponseBuilder rb = new ResponseBuilder(req, rsp, components); if (rb.requestInfo != null) { rb.requestInfo.setResponseBuilder(rb); diff --git a/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java b/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java index 4e76eac2611..ccba0d65ed1 100644 --- a/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java +++ b/solr/core/src/java/org/apache/solr/servlet/SolrRequestParsers.java @@ -584,7 +584,7 @@ public class SolrRequestParsers if (!isFormData(req)) { throw new SolrException( ErrorCode.BAD_REQUEST, "Not application/x-www-form-urlencoded content: "+req.getContentType() ); } - + final Map map = new HashMap(); // also add possible URL parameters and include into the map (parsed using UTF-8): @@ -600,7 +600,7 @@ public class SolrRequestParsers throw new SolrException(ErrorCode.BAD_REQUEST, "application/x-www-form-urlencoded content length (" + totalLength + " bytes) exceeds upload limit of " + uploadLimitKB + " KB"); } - + // get query String from request body, using the charset given in content-type: final String cs = ContentStreamBase.getCharsetFromContentType(req.getContentType()); final Charset charset = (cs == null) ? IOUtils.CHARSET_UTF_8 : Charset.forName(cs); @@ -680,7 +680,10 @@ public class SolrRequestParsers if (ServletFileUpload.isMultipartContent(req)) { return multipart.parseParamsAndFillStreams(req, streams); } - return raw.parseParamsAndFillStreams(req, streams); + if (req.getContentType() != null) { + return raw.parseParamsAndFillStreams(req, streams); + } + throw new SolrException(ErrorCode.UNSUPPORTED_MEDIA_TYPE, "Must specify a Content-Type header with POST requests"); } throw new SolrException(ErrorCode.BAD_REQUEST, "Unsupported method: " + method + " for request " + req); } diff --git a/solr/core/src/test/org/apache/solr/request/TestRemoteStreaming.java b/solr/core/src/test/org/apache/solr/request/TestRemoteStreaming.java index c1f74ac13c7..1217ecefeeb 100644 --- a/solr/core/src/test/org/apache/solr/request/TestRemoteStreaming.java +++ b/solr/core/src/test/org/apache/solr/request/TestRemoteStreaming.java @@ -27,6 +27,7 @@ import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrException; import org.apache.solr.common.SolrInputDocument; +import org.apache.solr.common.SolrException.ErrorCode; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; @@ -103,14 +104,18 @@ public class TestRemoteStreaming extends SolrJettyTestBase { return null; } - /** Do a select query with the stream.url. Solr should NOT access that URL, and so the data should be there. */ + /** Do a select query with the stream.url. Solr should fail */ @Test public void testNoUrlAccess() throws Exception { SolrQuery query = new SolrQuery(); query.setQuery( "*:*" );//for anything query.add("stream.url",makeDeleteAllUrl()); - getSolrServer().query(query); - assertTrue(searchFindsIt());//still there + try { + getSolrServer().query(query); + fail(); + } catch (SolrException se) { + assertSame(ErrorCode.BAD_REQUEST, ErrorCode.getErrorCode(se.code())); + } } /** SOLR-3161 diff --git a/solr/core/src/test/org/apache/solr/servlet/SolrRequestParserTest.java b/solr/core/src/test/org/apache/solr/servlet/SolrRequestParserTest.java index 6017ab9368e..e569b510e1c 100644 --- a/solr/core/src/test/org/apache/solr/servlet/SolrRequestParserTest.java +++ b/solr/core/src/test/org/apache/solr/servlet/SolrRequestParserTest.java @@ -379,4 +379,21 @@ public class SolrRequestParserTest extends SolrTestCaseJ4 { assertEquals("10.0.0.1", ((HttpServletRequest)solrReq.getContext().get("httpRequest")).getHeaders("X-Forwarded-For").nextElement()); } + + public void testPostMissingContentType() throws Exception { + HttpServletRequest request = createMock(HttpServletRequest.class); + expect(request.getMethod()).andReturn("POST").anyTimes(); + expect(request.getContentType()).andReturn(null).anyTimes(); + expect(request.getQueryString()).andReturn(null).anyTimes(); + replay(request); + + SolrRequestParsers parsers = new SolrRequestParsers(h.getCore().getSolrConfig()); + try { + parsers.parse(h.getCore(), "/select", request); + fail("should throw SolrException"); + } catch (SolrException e) { + assertTrue(e.getMessage().startsWith("Must specify a Content-Type header with POST requests")); + assertEquals(415, e.code()); + } + } } diff --git a/solr/solrj/src/java/org/apache/solr/common/SolrException.java b/solr/solrj/src/java/org/apache/solr/common/SolrException.java index a89783ad405..3cd03e5d71d 100644 --- a/solr/solrj/src/java/org/apache/solr/common/SolrException.java +++ b/solr/solrj/src/java/org/apache/solr/common/SolrException.java @@ -42,6 +42,7 @@ public class SolrException extends RuntimeException { FORBIDDEN( 403 ), NOT_FOUND( 404 ), CONFLICT( 409 ), + UNSUPPORTED_MEDIA_TYPE( 415 ), SERVER_ERROR( 500 ), SERVICE_UNAVAILABLE( 503 ), UNKNOWN(0);