I'm working with SOLR on a software website where each node has 300 CCK field Yes/No settings (software features). I tried enabling all CCK filters for SOLR, but was getting "400 Status Bad Request" errors, though SOLR appeared to be working and indexing fine.
I imagine the problem is that SOLR filters / search requests are sent via $_GET[] over http, I mean like ?filters=tid:11 tid:12 tid:13
Now imagine 300 CCK filters... The URL length limit is 2048 characters. I believe that is the cause of the "400 Status Bad Request": the query URL ?filters= is over 2048 characters long, and therefore doesnt work.
Is there a way to send the filters via a $_POST instead? Like saving in a $_SESSION? Anything instead of $_GET. Does anyone have a suggestion or workaround for 300+ CCK filters?
You in my use case, users would be able to tick off 300 Yes/No filters, and find their matching software. E.g. "SOLR Search integration: Yes/No", "Blog feature: Yes/No" etc. With SOLR it would make an extremely powerful software search machine!
| Comment | File | Size | Author |
|---|---|---|---|
| #60 | 761990-60.patch | 1.24 KB | nick_vh |
| #58 | 761990-58.patch | 1.24 KB | nick_vh |
| #56 | 761990-56.patch | 1.23 KB | nick_vh |
| #53 | 761990-53.patch | 1.04 KB | pwolanin |
| #49 | apachesolr-761990-49.patch | 2.35 KB | jhedstrom |
Comments
Comment #1
pwolanin commentedLikely this is the same problem as: #685924: Coherent Access + Apache Solr = Buffer Overflow
URL limits is 2048 or 4096 depending on the web server - there is no easy way around this - just enable the filters you need.
Comment #2
Anonymous (not verified) commentedOk, eventually I'll have to find a better solution. I'm planning on building a super-detailed software-search machine. Which requires at least 300 CCK "Yes/No" fields to work with SOLR. Anyway, maybe in Drupal 8...
Comment #3
jpmckinney commentedWhat if we call Apache_Solr_Service::search with Apache_Solr_Service::METHOD_POST as the last argument?
Comment #4
jpmckinney commentedThis seems to have no ill effect.
Comment #5
jpmckinney commentedComment #6
pwolanin commentedDid you check the request to see if the parameters are actually going into the POST body?
Comment #7
jpmckinney commentedYes, they are. From the search method in Service.php in SolrPhpClient:
And the _sendRawPost method:
Comment #8
jpmckinney commentedMarked #685924: Coherent Access + Apache Solr = Buffer Overflow duplicate.
Comment #9
pwolanin commentedsome extra confirmation:
http://www.ibm.com/developerworks/java/library/j-solr1/
Thanks for actually trying it James!
Comment #10
pwolanin commentedGiven that using POST request has potential performance implications I do not think it should be the default.
For example, the Solr servers for drupal.org are behind a varnish cache, so making all search requests via POST would typically bypass the cache.
Can we make this controlled by an opaque variable (i.e. one that is not set in the UI but only in settings.php or via devel etc.)? It would be good to have it there as an option for people that hit this problem, but 99% of users will never need it and should not enable it by mistake.
Comment #11
jpmckinney commentedComment #12
jpmckinney commentedInstead of a setting, how about using POST if the querystring is too long? No point in sending a GET request that will fail.
Comment #13
pwolanin commentedThe problem with that is that the max URL length may differ by server, so we'd still need a variable to control it.
Comment #14
jpmckinney commentedOk, maybe this is not a bug in the module, but a server misconfiguration.
In Tomcat, it is possible to configure the maximum URL length using maxHttpHeaderSize http://tomcat.apache.org/tomcat-5.5-doc/config/http.html
In Apache, use the LimitRequestLine directive: http://httpd.apache.org/docs/2.2/mod/core.html#limitrequestline
Also configurable in IIS http://www.asp.net/Learn/whitepapers/aspnet4#0.2__Toc253429244
Comment #15
jpmckinney commentedComment #16
jpmckinney commentedComment #17
pwolanin commentedWe use nginx in front of tomcat, but that can also be configured per:
http://forum.nginx.org/read.php?2,25207,25429 and http://wiki.nginx.org/NginxHttpCoreModule#large_client_header_buffers
So, I think it's still worth thinking about how to fix this in extreme cases - we'd probably override the search() method - but it's low priority.
Comment #18
janusman commentedThis *seems* to be the solution for those of us using the Jetty server included with Solr.
In etc/jetty.xml, add:*EDIT* See correct solution in comment #25 below =)Needs testing, though.
Comment #20
Anonymous (not verified) commented@#14: isn't URL length also limited by the browser? I thought IExplorer has a maximum of 2048 chars?
Comment #21
jpmckinney commentedFor GET requests, yes. But not for POST requests (or, at least, the limit for POST requests is so high that a Solr URL is unlikely to reach it).
Comment #22
Scott Reynolds commentedWait, we are now spreading FUD. This problem has nothing to do with a web browser.
relevant lines from _sendRawGet
As you can see, the web browser is not making the request. The users web browser is not used here at all. The Apache web server is making the call to the Solr server.
Comment #23
jpmckinney commentedFUD is a strong word for miscommunication :P There is a separate issue that if a user selects a massive number of facets, for example, the browser URL may exceed Internet Explorer's limit. There's no solution for dealing with that right now. But, it is a tangential issue.
Comment #24
pwolanin commentedRight, the problem where we've seen it in practice is from massive numbers of node access conditions, which are not exposed in the end-user URLs
Comment #25
janusman commented@Axol00 (who is a coworker) found out how to configure Jetty (bundled with Solr) to fix this =)
In jetty.xml, a line like
should be added within the <Call name="addConnector"> section. Like so:
I'm wondering if we should include a modified jetty.xml file along with the module... don't think it would hurt if they are the same across different versions of Solr.
I'll add this info to the Troubleshooting section of the handbook.
Comment #26
digi24 commentedI do not agree with #10. Of course we can start to patch or edit configs for all available solr servers, but I do not see any reason. If the request is large, varnish and other caches might turnout less performant than just passing the query to solr.
Is there any other reason, why not to take the suggested patch from #4 and maybe incorporate some length check defaulting to 8kb max or so?
The major advantage would be that even unforeseen large request would work by default.
Comment #27
pwolanin commentedJame's patch gives me fatal errors:
Here's a quick patch for testing purposes that uses the raw values of the constants.
Comment #28
pwolanin commentedHere's a rough stab at doing it from within the search method - sadly we can only do it correctly if we duplicate all the code from the base method. This is jsut a rough approximation based on param count.
Comment #29
reneve2010 commentedSubscribe
Comment #30
pwolanin commentedI think we can revisit this now
Comment #31
jpmckinney commentedFix in HEAD first.
Comment #32
jhedstromI experienced this issue when enabling the apachesolr_text module. The patch in #28 fixes it, but only if I set the apachesolr_search_post_threshold to a very low number (site has about 20 text fields, using content permission module).
Comment #33
pwolanin commentedWe need to put together a real fix here - basically overriding the search() method of the underlying class so that we can determine the string length of the URL and decide on the method to use.
Comment #34
jhedstromI don't quite understand the difference between what you're saying in #33, and what the patch in #28 actually does. The patch does override the underlying search method.
Comment #35
pwolanin commentedYes, but not completely. It just counts the #param. We need the actual final string length to really get good behavior.
Comment #36
jhedstromHere's a patch that overrides the
Apache_Solr_Service::searchmethod. Once the query string is built, it checks for the length, and if longer than 2000 characters, changes the method to use POST. The 2000 character limit is hard-coded. Not sure if that should be configurable (a little googling indicated that this was a rough limit, there's probably an actual limit somewhere in the Solr codebase).Comment #37
pwolanin commentedLooks like a reasonable start.
However, I think the should be 4000 by default, and be a variable. tomcat6, jetty, etc have different defaults and are configurable themselves. tomcat6 default is 4096 afaik.
Also, if we are bringing this code in, we should clean up the code style to Drupal standards.
Comment #38
jhedstromHere is an updated patch that makes the threshold configurable (4k default), and also cleans up the coding standards (my reasoning with the previous patch left them as they were in the Apache_Solr_Service::search method for ease of diffing future changes to that code).
Comment #39
jhedstromOops. Incorrectly formatted patch.
Comment #40
pwolanin commentedShould potentially merge with http://drupal.org/node/1107502
Also, might make sense to haev this a per-server variables, since different servers might have different limits?
Comment #41
pwolanin commentedthe patch for 7 is now pretty small.
Comment #42
pwolanin commentedcommitted to 7.x
Comment #43
elliotttf commentedShould the variable be 'apachesolr_post_threshold' instead of 'apachesolr_search_post_threshold'? Seems like most of the server level config is namespaced under apachesolr_ not apachesolr_search_
Comment #44
jpmckinney commentedI guess patch to review is #28
Comment #45
pwolanin commentedWell I was interpreting the name like "apachesolr: search post threshold", not "apachesolr search: post threshold"
Comment #46
pwolanin commentedHere's a patch for 6.x-1.x rolled based on #39 with some minor cleanup.
Comment #47
pwolanin commentedComment #49
jhedstromLooks like this didn't make it into the 6.x-2.x branch. Here's the patch from #46 rolled against 2.x.
Comment #50
jpmckinney commentedFixed thanks!
Comment #52
pwolanin commentedSo, it turns out 4000 isn't quite conservative enough - there is a range of request sies < 4000 but where content added as headers, etc, still seems to make tomcat6 fail
Let's reduce the default limit to 3700 or 3500?
Comment #53
pwolanin commentedHere's a possible patch that implements per-server (i.e. per search environment) limits.
Comment #54
pwolanin commenteddo we need an update function to copy the since current setting over to each environment?
Comment #55
nick_vhLooks good to me, a bit confusing that the $this->env_id is in that line. Can't we do that check earlier somewhere where it would make more sense?
Comment #56
nick_vhI'm still not sure why you would want to go to the POST method if the $env_id is empty? Also we should not change variable names now. And aside of that - do we really need to hard code this 1800 limit? If someone wants to debug and always wants to use POST - we should not prevent that.
Comment #57
nick_vhComment #58
nick_vhSame patch, better documentation
Comment #59
nick_vhCommitted to 7.x-1.x
Comment #60
nick_vhComment #61
nick_vhFixed, Thanks for all the contributions!
Comment #62
nick_vhCleaning up queue